Brother even blockchain tutorial Ethereum source Analysis core-state-process Source Analysis (ii):
About the calculation of G0, in the Yellow Book by the detailed introduction
Part of the Yellow Book is the If contractcreation && homestead {IGas. SetUint64 (params. Txgascontractcreation) This is because gtxcreate+gtransaction = txgascontractcreation
func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int { igas := new(big.Int) if contractCreation && homestead { igas.SetUint64(params.TxGasContractCreation) } else { igas.SetUint64(params.TxGas) } if len(data) > 0 { var nz int64 for _, byt := range data { if byt != 0 { nz++ } } m := big.NewInt(nz) m.Mul(m, new(big.Int).SetUint64(params.TxDataNonZeroGas)) igas.Add(igas, m) m.SetInt64(int64(len(data)) - nz) m.Mul(m, new(big.Int).SetUint64(params.TxDataZeroGas)) igas.Add(igas, m) } return igas}
Pre-execution checks
Func (St *statetransition) PreCheck () error {
msg: = St.msg
Sender: = St.from ()
// Make sure this transaction‘s nonce is correctif msg.CheckNonce() { nonce := st.state.GetNonce(sender.Address()) // 当前本地的nonce 需要和 msg的Nonce一样 不然就是状态不同步了。 if nonce < msg.Nonce() { return ErrNonceTooHigh } else if nonce > msg.Nonce() { return ErrNonceTooLow }}return st.buyGas()
}
Buygas, realize gas withholding fee, first of all deduct your gaslimit gasprice money. Then according to the calculated status in the refund part.
Func (St statetransition) Buygas () error {
MGAs: = St.msg.Gas ()
If MGAs. Bitlen () > 64 {
Return VM. Erroutofgas
}
mgval := new(big.Int).Mul(mgas, st.gasPrice)var ( state = st.state sender = st.from())if state.GetBalance(sender.Address()).Cmp(mgval) < 0 { return errInsufficientBalanceForGas}if err := st.gp.SubGas(mgas); err != nil { // 从区块的gaspool里面减去, 因为区块是由GasLimit限制整个区块的Gas使用的。 return err}st.gas += mgas.Uint64()st.initialGas.Set(mgas)state.SubBalance(sender.Address(), mgval)// 从账号里面减去 GasLimit * GasPricereturn nil
}
The drawback is to reward you for running some of the instructions that can reduce the burden of the blockchain, such as emptying the storage of your account. or run the suicide command to clear the account.
Func (St *statetransition) Refundgas () {
Return ETH for remaining gas to the sender account,
Exchanged at the original rate.
Sender: = St.from ()//Err already checked
Remaining: = new (big. INT). Mul (New big. INT). SetUint64 (St.gas), St.gasprice)
First, the user has left the gas back.
St.state.AddBalance (sender. Address (), remaining)
// Apply refund counter, capped to half of the used gas.// 然后退税的总金额不会超过用户Gas总使用的1/2。uhalf := remaining.Div(st.gasUsed(), common.Big2)refund := math.BigMin(uhalf, st.state.GetRefund())st.gas += refund.Uint64()// 把退税的金额加到用户账户上。st.state.AddBalance(sender.Address(), refund.Mul(refund, st.gasPrice))// Also return remaining gas to the block gas counter so it is// available for the next transaction.// 同时也把退税的钱还给gaspool给下个交易腾点Gas空间。st.gp.AddGas(new(big.Int).SetUint64(st.gas))
}
Stateprocessor
Statetransition is used to deal with a single transaction. Then Stateprocessor is used to deal with block-level transactions.
Structure and construction
Stateprocessor is a basic Processor, which takes care of transitioning
State from one point to another.
//
Stateprocessor implements Processor.
Type stateprocessor struct {
Config params. Chainconfig//Chain configuration options
BC BlockChain//Canonical block chain
Engine consensus. Engine//Consensus engine used for block rewards
}
Newstateprocessor initialises a new stateprocessor.
Func newstateprocessor (config params. Chainconfig, BC BlockChain, engine consensus. Engine) *stateprocessor {
Return &stateprocessor{
Config:config,
BC:BC,
Engine:engine,
}
}
Process, this method will be called by Blockchain.
Process processes the state changes according to the Ethereum rules by running//the transaction messages using the STA Tedb and applying any rewards to both//the processor (Coinbase) and any included uncles.//Process runs trading information according to the Ethereum rules to Statedb Make state changes, and reward miners or other uncle nodes. Process returns the receipts and logs accumulated during the process and//returns the amount of gas is used in t He process. If any of the the//transactions failed to the execute due to insufficient gas it would return an error.//process returns the accumulated receipts and logs during execution and Returns the gas used in the process. If any transaction execution fails due to gas shortage, an error is returned. Func (P *stateprocessor) Process (Block *types. Block, Statedb *state. Statedb, cfg vm. Config) (types. receipts, []*types. Log, *big. Int, error) {var (Receipts types. Receipts Totalusedgas = big. Newint (0) Header = block. Header () alllogs []*types. Log GP = new (Gaspool). Addgas (block. Gaslimit ())//Mutate the the The block and state according to any hard-fork specs//DAO event Hard fork processing if p.config. Daoforksupport && P.config.daoforkblock! = Nil && p.config.daoforkblock.cmp (block. Number ()) = = 0 {Misc. Applydaohardfork (Statedb)}//iterate over and process the individual transactions for I, TX: = range block. Transactions () {Statedb. Prepare (TX. Hash (), block. Hash (), I) Receipt, _, Err: = Applytransaction (P.config, P.BC, Nil, GP, Statedb, Header, TX, Totalusedgas, CFG) If err! = Nil {return nil, nil, nil, err} receipts = append (receipts, receipt) Alllo GS = Append (Alllogs, receipt. Logs ...) }//Finalize The block, applying any consensus engine specific extras (e.g. Block rewards) P.engine.finalize (P.BC, Header, Statedb, block. Transactions (), Block. Uncles (), receipts)//Return receipt log Total gas usage and nil return receipts, Alllogs, Totalusedgas, nil}
Applytransaction
Applytransaction attempts to apply a transaction to the given State database//and uses the input parameters for its EN Vironment. It returns the receipt//for the transaction, gas used and a error if the transaction failed,//indicating the block was Invalid. Applytransaction tries to apply the transaction to the given State database and uses the input parameters of its environment. It returns the receipt of the transaction, uses gas and error, if the transaction fails, indicating that the block is invalid. Func applytransaction (config *params. Chainconfig, BC *blockchain, author *common. Address, GP *gaspool, Statedb *state. Statedb, Header *types. Header, TX *types. Transaction, Usedgas *big. Int, cfg vm. Config) (*types. Receipt, *big. Int, error) {//Translate the transaction into a message//Here's how to verify that the messages are actually sent by sender. TODO msg, err: = Tx. Asmessage (types. Makesigner (config, header.) Number)) If err! = Nil {return nil, nil, err}//Create a new context to being used in the EVM environment Each transaction creates a new virtual machine environment. Context: = Newevmcontext (msg, header, BC, author)//Create a new environment which holds all relevant information/ /about the transaction and CalLing mechanisms. Vmenv: = VM. NEWEVM (context, statedb, config, cfg)//Apply The transaction to the current state (included in the Env) _, gas, FA iled, err: = Applymessage (vmenv, MSG, GP) if err! = Nil {return nil, nil, err}//Update the state with Pending Changes//evaluates the middle state var root []byte if config. Isbyzantium (header. Number) {Statedb. Finalise (True)} else {root = Statedb. Intermediateroot (config. IsEIP158 (header. Number)). Bytes ()} usedgas.add (Usedgas, gas)//Create A new receipt for the transaction, storing the intermediate root an D gas used by the TX//based on the EIP phase, we ' re passing wether the root touch-delete accounts. Create a receipt that is used to store the root of the middle State, and the gas receipt used for the trade: = Types. Newreceipt (Root, failed, Usedgas) receipt. Txhash = Tx. Hash () Receipt. gasused = new (big. INT). Set (GAS)//If the transaction created a contract, store the creation address in the receipt. If it is a transaction that creates a contract. Then we store the creation address in the receipt. If Msg. to () = = Nil {receipt. Contractaddress = crypto. Createaddress (vmenv. Context.origin, TX. Nonce ())}//Set the receipt logs and create a bloom for filtering receipt. Logs = Statedb. Getlogs (TX. Hash ()) receipt. Bloom = types. Createbloom (types. Receipts{receipt})//Get all the logs and create a log of the fabric filter. Return receipt, gas, err}
Blockchain tutorial Ethereum source Analysis core-state-process Source Analysis (ii)