兄弟連區塊鏈入門教程以太坊原始碼分析core-vm原始碼分析
摘要:## contract.go
contract 代表了eth state database裡面的一個合約。包含了合約程式碼,呼叫引數。
結構
// ContractRef is a reference to the contract's backing object
...
## contract.go contract 代表了eth state database裡面的一個合約。包含了合約程式碼,呼叫引數。 結構 // ContractRef is a reference to the contract's backing object type ContractRef interface { Address() common.Address } // AccountRef implements ContractRef. // // Account references are used during EVM initialisation and // it's primary use is to fetch addresses. Removing this object // proves difficult because of the cached jump destinations which // are fetched from the parent contract (i.e. the caller), which // is a ContractRef. type AccountRef common.Address // Address casts AccountRef to a Address func (ar AccountRef) Address() common.Address { return (common.Address)(ar) } // Contract represents an ethereum contract in the state database. It contains // the the contract code, calling arguments. Contract implements ContractRef type Contract struct { // CallerAddress is the result of the caller which initialised this // contract. However when the "call method" is delegated this value // needs to be initialised to that of the caller's caller. // CallerAddress是初始化這個合約的人。 如果是delegate,這個值被設定為呼叫者的呼叫者。 CallerAddress common.Address caller ContractRef self ContractRef jumpdests destinations // result of JUMPDEST analysis. JUMPDEST指令的分析 Code []byte //程式碼 CodeHash common.Hash //程式碼的HASH CodeAddr *common.Address //程式碼地址 Input []byte // 入參 Gas uint64// 合約還有多少Gas value *big.Int Args []byte //好像沒有使用 DelegateCall bool } 構造 // NewContract returns a new contract environment for the execution of EVM. func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract { c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil} if parent, ok := caller.(*Contract); ok { // Reuse JUMPDEST analysis from parent context if available. // 如果 caller 是一個合約,說明是合約呼叫了我們。 jumpdests設定為caller的jumpdests c.jumpdests = parent.jumpdests } else { c.jumpdests = make(destinations) } // Gas should be a pointer so it can safely be reduced through the run // This pointer will be off the state transition c.Gas = gas // ensures a value is set c.value = value return c } AsDelegate將合約設定為委託呼叫並返回當前合同(用於鏈式呼叫) // AsDelegate sets the contract to be a delegate call and returns the current // contract (for chaining calls) func (c *Contract) AsDelegate() *Contract { c.DelegateCall = true // NOTE: caller must, at all times be a contract. It should never happen // that caller is something other than a Contract. parent := c.caller.(*Contract) c.CallerAddress = parent.CallerAddress c.value = parent.value return c } GetOp 用來獲取下一跳指令 // GetOp returns the n'th element in the contract's byte array func (c *Contract) GetOp(n uint64) OpCode { return OpCode(c.GetByte(n)) } // GetByte returns the n'th byte in the contract's byte array func (c *Contract) GetByte(n uint64) byte { if n < uint64(len(c.Code)) { return c.Code[n] } return 0 } // Caller returns the caller of the contract. // // Caller will recursively call caller when the contract is a delegate // call, including that of caller's caller. func (c *Contract) Caller() common.Address { return c.CallerAddress } UseGas使用Gas。 // UseGas attempts the use gas and subtracts it and returns true on success func (c *Contract) UseGas(gas uint64) (ok bool) { if c.Gas < gas { return false } c.Gas -= gas return true } // Address returns the contracts address func (c *Contract) Address() common.Address { return c.self.Address() } // Value returns the contracts value (sent to it from it's caller) func (c *Contract) Value() *big.Int { return c.value } SetCode ,SetCallCode 設定程式碼。 // SetCode sets the code to the contract func (self *Contract) SetCode(hash common.Hash, code []byte) { self.Code = code self.CodeHash = hash } // SetCallCode sets the code of the contract and address of the backing data // object func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) { self.Code = code self.CodeHash = hash self.CodeAddr = addr } ## evm.go 結構 // Context provides the EVM with auxiliary information. Once provided // it shouldn't be modified. // 上下文為EVM提供輔助資訊。 一旦提供,不應該修改。 type Context struct { // CanTransfer returns whether the account contains // sufficient ether to transfer the value // CanTransfer 函式返回賬戶是否有足夠的ether用來轉賬 CanTransfer CanTransferFunc // Transfer transfers ether from one account to the other // Transfer 用來從一個賬戶給另一個賬戶轉賬 Transfer TransferFunc // GetHash returns the hash corresponding to n // GetHash用來返回入參n對應的hash值 GetHash GetHashFunc // Message information // 用來提供Origin的資訊 sender的地址 Origin common.Address // Provides information for ORIGIN // 用來提供GasPrice資訊 GasPrice *big.Int // Provides information for GASPRICE // Block information Coinbase common.Address // Provides information for COINBASE GasLimit *big.Int // Provides information for GASLIMIT BlockNumber *big.Int // Provides information for NUMBER Time *big.Int // Provides information for TIME Difficulty *big.Int // Provides information for DIFFICULTY } // EVM is the Ethereum Virtual Machine base object and provides // the necessary tools to run a contract on the given state with // the provided context. It should be noted that any error // generated through any of the calls should be considered a // revert-state-and-consume-all-gas operation, no checks on // specific errors should ever be performed. The interpreter makes // sure that any errors generated are to be considered faulty code. // EVM是eth虛擬機器基礎物件,並提供必要的工具,以使用提供的上下文執行給定狀態的合約。 // 應該指出的是,任何呼叫產生的任何錯誤都應該被認為是一種回滾修改狀態和消耗所有GAS操作, // 不應該執行對具體錯誤的檢查。 直譯器確保生成的任何錯誤都被認為是錯誤的程式碼。 // The EVM should never be reused and is not thread safe. type EVM struct { // Context provides auxiliary blockchain related information Context // StateDB gives access to the underlying state StateDB StateDB // Depth is the current call stack // 當前的呼叫堆疊 depth int // chainConfig contains information about the current chain // 包含了當前的區塊鏈的資訊 chainConfig *params.ChainConfig // chain rules contains the chain rules for the current epoch chainRules params.Rules // virtual machine configuration options used to initialise the // evm. vmConfig Config // global (to this context) ethereum virtual machine // used throughout the execution of the tx. interpreter *Interpreter // abort is used to abort the EVM calling operations // NOTE: must be set atomically abort int32 } 建構函式 // NewEVM retutrns a new EVM . The returned EVM is not thread safe and should // only ever be used *once*. func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM { evm := &EVM{ Context: ctx, StateDB: statedb, vmConfig: vmConfig, chainConfig: chainConfig, chainRules: chainConfig.Rules(ctx.BlockNumber), } evm.interpreter = NewInterpreter(evm, vmConfig) return evm } // Cancel cancels any running EVM operation. This may be called concurrently and // it's safe to be called multiple times. func (evm *EVM) Cancel() { atomic.StoreInt32(&evm.abort, 1) }