I prepared this gist to confirm from the community if my assumption on Ethereum POA (clique) gas burning is correct?
From what I groked today in the ethereum go code, it appears that the gas used during the contract execution is burned, that is debited from the contract transaction submitter’s account but not credited to anyone.
Please see the code snippets below:
code base groked: geth 'release/1.8'
go-ethereum/core/blockchain.go
L:1069 Bockchain InsertChain calls Blockchain.Process at L:1200
Process then calls ApplyTransaction which in-turn calls ApplyMessage()
Function ApplyMessage calls TransitionDb(), which deducts gass from the executor address and credits to the coinbase
address.
coinbase is set to all zero during init of clique, so gas is deducted and burned but not recycled. (TODO re-verify) see:
consensus/clique/clique.go L:517 func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) error
L:519 header.Coinbase = common.Address{}
go-ethereum/core/state_processor.go
// Process processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb and applying any rewards to both // the processor (coinbase) and any included uncles. // // Process returns the receipts and logs accumulated during the process and // returns the amount of gas that was used in the process. If any of the // transactions failed to execute due to insufficient gas it will return an error. func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
L:71 calls ApplyTransaction which in-turn calls ApplyMessage()
go-ethereum/consensus/ethash/consensus.go
Ethash uses mining workers…see below:
go-ethereum/miner/worker.go
L:402 func (w *worker) mainLoop()
worker mainloop
function uses channel select pattern to call commitTransaction
function.
func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) { snap := w.current.state.Snapshot() receipt, _, err := core.ApplyTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig())
go-ethereum/core/chain_makers.go
Chain Makers is only used for test & sim.
// AddTx adds a transaction to the generated block. If no coinbase has // been set, the block's coinbase is set to the zero address. // // AddTx panics if the transaction cannot be executed. In addition to // the protocol-imposed limitations (gas limit, etc.), there are some // further limitations on the content of transactions that can be // added. Notably, contract code relying on the BLOCKHASH instruction // will panic during execution. func (b *BlockGen) AddTx(tx *types.Transaction) { b.AddTxWithChain(nil, tx) }
// AddTxWithChain adds a transaction to the generated block. If no coinbase has // been set, the block's coinbase is set to the zero address. // // AddTxWithChain panics if the transaction cannot be executed. In addition to // the protocol-imposed limitations (gas limit, etc.), there are some // further limitations on the content of transactions that can be // added. If contract code relies on the BLOCKHASH instruction, // the block in chain will be returned. func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { L:99 receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{})
go-ethereum/consensus/ethash/consensus.go
func (ethash *Ethash) Finalize(...
L:569 accumulateRewards(chain.Config(), state, header, uncles)
L:605: func accumulateRewards(…)
// AccumulateRewards credits the coinbase of the given block with the mining // reward. The total reward consists of the static block reward and rewards for // included uncles. The coinbase of each uncle block is also rewarded.
core/state_processor.go
L:88 ApplyTransaction calls ApplyMessage()
internal/ethapi/api.go
L:686 func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, timeout time.Duration) ([]byte, uint64, bool, error) {
L:741 res, gas, failed, err := core.ApplyMessage(evm, msg, gp)
// Call executes the given transaction on the state for the given block number. // It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values. func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { result, _, _, err := s.doCall(ctx, args, blockNr, 5*time.Second) return (hexutil.Bytes)(result), err }
go-ethereum/core/state_transition.go
L:123 func (st *StateTransition) useGas(amount uint64)
L:124
// ApplyMessage computes the new state by applying the given message // against the old state within the environment. // // ApplyMessage returns the bytes returned by any EVM execution (if it took place), // the gas used (which includes gas refunds) and an error if it failed. An error always // indicates a core error meaning that the message would always fail for that particular // state and would never be accepted within a block. func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool, error) { return NewStateTransition(evm, msg, gp).TransitionDb() }
L:152 func (st *StateTransition) buyGas() error
L:183 func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bool, err error)
// TransitionDb will transition the state by applying the current message and // returning the result including the used gas. It returns an error if failed. // An error indicates a consensus issue.
L:224 st.refundGas() st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
core/state/statedb.go
L:328 func (self *StateDB) SubBalance(addr common.Address, amount *big.Int)
I know, it's 3 years later, now, but I was wondering the very same thing: Does Clique burn transaction fees? From mere observation it seems so. Did you ever get any feedback on this?