區塊鏈教程以太坊源碼分析core-state-process源碼分析(二)

來源:互聯網
上載者:User

標籤:nts   current   big   以太坊   add   虛擬機器   輸入   type   rate   

兄弟連區塊鏈教程以太坊源碼分析core-state-process源碼分析(二):
關於g0的計算,在黃皮書上由詳細的介紹
和黃皮書有一定出入的部分在於if contractCreation && homestead {igas.SetUint64(params.TxGasContractCreation) 這是因為 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}

執行前的檢查
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, 實現Gas的預計費, 首先就扣除你的GasLimit GasPrice的錢。 然後根據計算完的狀態在退還一部分。
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

}

退稅,退稅是為了獎勵大家運行一些能夠減輕區塊鏈負擔的指令, 比如清空賬戶的storage. 或者是運行suicide命令來清空帳號。

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)
// 首先把使用者還剩下的Gas還回去。
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是用來處理一個一個的交易的。那麼StateProcessor就是用來處理區塊層級的交易的。

結構和構造

// 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,這個方法會被blockchain調用。

// 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 根據以太坊規則運行交易資訊來對statedb進行狀態改變,以及獎勵挖礦者或者是其他的叔父節點。// 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.// Process返回執行過程中累計的收據和日誌,並返回過程中使用的Gas。 如果由於Gas不足而導致任何交易執行失敗,將返回錯誤。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 block and state according to any hard-fork specs    // DAO 事件的硬分叉處理    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)        allLogs = 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)    // 返回收據 日誌 總的Gas使用量和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 environment. It returns the receipt// for the transaction, gas used and an error if the transaction failed,// indicating the block was invalid.ApplyTransaction嘗試將事務應用於給定的狀態資料庫,並使用其環境的輸入參數。//它返回事務的收據,使用的Gas和錯誤,如果交易失敗,表明塊是無效的。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) {    // 把交易轉換成Message    // 這裡如何驗證訊息確實是Sender發送的。 TODO    msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))    if err != nil {        return nil, nil, err    }    // Create a new context to be used in the EVM 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, failed, err := ApplyMessage(vmenv, msg, gp)    if err != nil {        return nil, nil, err    }    // Update the state with pending changes    // 求得中間狀態    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 and gas used by the tx    // based on the eip phase, we‘re passing wether the root touch-delete accounts.    // 建立一個收據, 用來儲存中間狀態的root, 以及交易使用的gas    receipt := 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 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})    // 拿到所有的日誌並建立日誌的布隆過濾器.    return receipt, gas, err}

區塊鏈教程以太坊源碼分析core-state-process源碼分析(二)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.