Documentation ¶
Index ¶
- Constants
- Variables
- func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error)
- type AccountRef
- type CanTransferFunc
- type Config
- type Context
- type Contract
- func (c *Contract) Address() common.Address
- func (c *Contract) AsDelegate() *Contract
- func (c *Contract) Caller() common.Address
- func (c *Contract) GetByte(n uint64) byte
- func (c *Contract) GetOp(n uint64) OpCode
- func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte)
- func (c *Contract) SetCode(hash common.Hash, code []byte)
- func (c *Contract) UseGas(gas uint64) (ok bool)
- func (c *Contract) Value() uint64
- type ContractRef
- type Destinations
- type EVM
- func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, ...) (ret []byte, snapshot int, leftOverGas uint64, err error)
- func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, ...) (ret []byte, leftOverGas uint64, err error)
- func (evm *EVM) Cancel()
- func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []byte, gas uint64, ...) (ret []byte, snapshot int, leftOverGas uint64, err error)
- func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error)
- func (evm *EVM) GasTable(num *big.Int) gas.Table
- func (evm *EVM) SetMaxCodeSize(maxCodeSize int)
- func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error)
- type ExecutionFunc
- type GetHashFunc
- type Interpreter
- type JSONLogger
- func (logger *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error
- func (logger *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, ...) error
- func (logger *JSONLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, ...) error
- func (logger *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, ...) error
- type OpCode
- type Operation
- type PrecompiledContract
- type StructLog
- type Tracer
- type TransferFunc
Constants ¶
const ( // CREATE 过程调用 CREATE OpCode = 0xf0 + iota // CALL op CALL // CALLCODE op CALLCODE // RETURN op RETURN // DELEGATECALL op DELEGATECALL // STATICCALL op STATICCALL = 0xfa // REVERT op REVERT = 0xfd // SELFDESTRUCT op SELFDESTRUCT = 0xff )
Variables ¶
var ( // ConstantinopleInstructionSet 对应EVM不同版本的指令集,从上往下,从旧版本到新版本, // 新版本包含旧版本的指令集(目前直接使用康士坦丁堡指令集) ConstantinopleInstructionSet = NewConstantinopleInstructionSet() )
var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{1}): &ecrecover{}, common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{}, common.BytesToAddress([]byte{4}): &dataCopy{}, common.BytesToAddress([]byte{5}): &bigModExp{}, common.BytesToAddress([]byte{6}): &bn256Add{}, common.BytesToAddress([]byte{7}): &bn256ScalarMul{}, common.BytesToAddress([]byte{8}): &bn256Pairing{}, }
PrecompiledContractsByzantium chain33平台支持君士坦丁堡版本支持的所有预编译合约指令,并从此版本开始同步支持EVM黄皮书中的新增指令; 保存拜占庭版本支持的所有预编译合约(包括之前版本的合约); 后面如果有硬分叉,需要在此处考虑分叉逻辑,根据区块高度分别处理; 下面的8个预编译指令,直接引用go-ethereum中的EVM实现
Functions ¶
func RunPrecompiledContract ¶
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error)
RunPrecompiledContract 调用预编译的合约逻辑并返回结果
Types ¶
type AccountRef ¶
AccountRef 账户对象引用 (实现了合约对象引用ContractRef接口) 因为在合约调用过程中,调用者有可能是外部账户,也有可能是合约账户,所以两者的结构是互通的
type CanTransferFunc ¶
CanTransferFunc 检查制定账户是否有足够的金额进行转账
type Config ¶
type Config struct { // Debug 调试开关 Debug bool // Tracer 记录操作日志 Tracer Tracer // NoRecursion 不允许使用Call, CallCode, DelegateCall NoRecursion bool // EnablePreimageRecording SHA3/keccak 操作时是否保存数据 EnablePreimageRecording bool // JumpTable 指令跳转表 JumpTable [256]Operation }
Config 解释器的配置模型
type Context ¶
type Context struct { // CanTransfer 是否可转账 CanTransfer CanTransferFunc // Transfer 转账 Transfer TransferFunc // GetHash 获取区块哈希 GetHash GetHashFunc // Origin 指令返回数据, 合约调用者地址 Origin common.Address // GasPrice 指令返回数据 GasPrice uint32 // Coinbase 指令, 区块打包者地址 Coinbase *common.Address // GasLimit 指令,当前交易的GasLimit GasLimit uint64 // BlockNumber NUMBER 指令,当前区块高度 BlockNumber *big.Int // Time 指令, 当前区块打包时间 Time *big.Int // Difficulty 指令,当前区块难度 Difficulty *big.Int }
Context EVM操作辅助上下文 外部在构造EVM实例时传入,EVM实例构造完成后不允许修改
type Contract ¶
type Contract struct { // CallerAddress 调用者地址,应该为外部账户的地址 // 如果是通过合约再调用合约时,会从上级合约中获取调用者地址进行赋值 CallerAddress common.Address // Jumpdests 存储跳转信息,供JUMP和JUMPI指令使用 Jumpdests Destinations // Code合约代码 Code []byte // CodeHash 代码哈希 CodeHash common.Hash // CodeAddr 合约地址 CodeAddr *common.Address // Input 输入参数 Input []byte // Gas 此合约对象的可用Gas(合约执行过程中会修改此值) Gas uint64 // DelegateCall 委托调用时,此属性会被设置为true DelegateCall bool // contains filtered or unexported fields }
Contract 合约对象,它在内存中表示一个合约账户的代码即地址信息实体 每次合约调用都会创建一个新的合约对象
func NewContract ¶
func NewContract(caller ContractRef, object ContractRef, value uint64, gas uint64) *Contract
NewContract 创建一个新的合约调用对象 不管合约是否存在,每次调用时都会新创建一个合约对象交给解释器执行,对象持有合约代码和合约地址
func (*Contract) AsDelegate ¶
AsDelegate 设置当前的合约对象为被委托调用 返回当前合约对象的指针,以便在多层调用链模式下使用
func (*Contract) Caller ¶
Caller 返回合约的调用者 如果当前合约为委托调用,则调用它的不是外部账户,而是合约账户,所以此时的caller为调用此合约的合约的caller 这个关系可以一直递归向上,直到定位到caller为外部账户地址
func (*Contract) SetCallCode ¶
SetCallCode 设置合约代码和代码哈希
type Destinations ¶
Destinations 存储合约以及代码对应的位向量对象 Key为代码哈希,Value为对应的合约代码的位向量 JUMPDEST指令会使用此对象进行跳转位置判断
type EVM ¶
type EVM struct { // Context 链相关的一些辅助属性和操作方法 Context // EVMStateDB 状态数据操作入口 StateDB state.EVMStateDB // VMConfig 虚拟机配置属性信息 VMConfig Config // Interpreter EVM指令解释器,生命周期同EVM Interpreter *Interpreter // CallGasTemp 此属性用于临时存储计算出来的Gas消耗值 // 在指令执行时,会调用指令的gasCost方法,计算出此指令需要消耗的Gas,并存放在此临时属性中 // 然后在执行opCall时,从此属性获取消耗的Gas值 CallGasTemp uint64 // contains filtered or unexported fields }
EVM 结构对象及其提供的操作方法,用于进行满足以太坊EVM黄皮书规范定义的智能合约代码的创建和执行 合约执行过程中会修改外部状态数据(数据操作通过外部注入) 在合约代码执行过程中发生的任何错误,都将会导致对状态数据的修改被回滚,并且依然消耗掉剩余的Gas 此对象为每个交易创建一个实例,其操作非线程安全
func NewEVM ¶
func NewEVM(ctx Context, statedb state.EVMStateDB, vmConfig Config) *EVM
NewEVM 创建一个新的EVM实例对象 在同一个节点中,一个EVM实例对象只服务于一个交易执行的生命周期
func (*EVM) Call ¶
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value uint64) (ret []byte, snapshot int, leftOverGas uint64, err error)
Call 此方法提供合约外部调用入口 根据合约地址调用已经存在的合约,input为合约调用参数 合约调用逻辑支持在合约调用的同时进行向合约转账的操作
func (*EVM) CallCode ¶
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value uint64) (ret []byte, leftOverGas uint64, err error)
CallCode 合约内部调用合约的入口 执行逻辑同Call方法,但是有以下几点不同: 在创建合约对象时,合约对象的上下文地址(合约对象的self属性)被设置为caller的地址
func (*EVM) Create ¶
func (evm *EVM) Create(caller ContractRef, contractAddr common.Address, code []byte, gas uint64, execName, alias, abi string) (ret []byte, snapshot int, leftOverGas uint64, err error)
Create 此方法提供合约外部创建入口; 使用传入的部署代码创建新的合约; 目前chain33为了保证账户安全,不允许合约中涉及到外部账户的转账操作, 所以,本步骤不接收转账金额参数
func (*EVM) DelegateCall ¶
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error)
DelegateCall 合约内部调用合约的入口 不支持向合约转账 和CallCode不同的是,它会把合约的外部调用地址设置成caller的caller
func (*EVM) SetMaxCodeSize ¶
SetMaxCodeSize 设置合约代码的最大支持长度
type ExecutionFunc ¶
type ExecutionFunc func(pc *uint64, env *EVM, contract *Contract, memory *mm.Memory, stack *mm.Stack) ([]byte, error)
ExecutionFunc 指令执行函数,每个操作指令对应一个实现,它实现了指令的具体操作逻辑
type GetHashFunc ¶
GetHashFunc 获取制定高度区块的哈希 给 BLOCKHASH 指令使用
type Interpreter ¶
type Interpreter struct { // IntPool 整数内存池 IntPool *mm.IntPool // 合约执行返回的结果数据 ReturnData []byte // contains filtered or unexported fields }
Interpreter 解释器接结构定义
func NewInterpreter ¶
func NewInterpreter(evm *EVM, cfg Config) *Interpreter
NewInterpreter 新创建一个解释器
type JSONLogger ¶
type JSONLogger struct {
// contains filtered or unexported fields
}
JSONLogger 使用json格式打印日志
func (*JSONLogger) CaptureEnd ¶
func (logger *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error
CaptureEnd 结束记录
func (*JSONLogger) CaptureFault ¶
func (logger *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error
CaptureFault 目前实现为空
type OpCode ¶
type OpCode byte
OpCode EVM操作码定义,本质上就是一个字节,所以操作码最多只支持256个
unofficial opcodes used for parsing
const ( // ADDRESS 0x30 合约数据操作 ADDRESS OpCode = 0x30 + iota // BALANCE op BALANCE // ORIGIN op ORIGIN // CALLER op CALLER // CALLVALUE op CALLVALUE // CALLDATALOAD op CALLDATALOAD // CALLDATASIZE op CALLDATASIZE // CALLDATACOPY op CALLDATACOPY // CODESIZE op CODESIZE // CODECOPY op CODECOPY // GASPRICE op GASPRICE // EXTCODESIZE op EXTCODESIZE // EXTCODECOPY op EXTCODECOPY // RETURNDATASIZE op RETURNDATASIZE // RETURNDATACOPY op RETURNDATACOPY )
const ( // PUSH1 0x60 栈操作 PUSH1 OpCode = 0x60 + iota // PUSH2 op PUSH2 // PUSH3 op PUSH3 // PUSH4 op PUSH4 // PUSH5 op PUSH5 // PUSH6 op PUSH6 // PUSH7 op PUSH7 // PUSH8 op PUSH8 // PUSH9 op PUSH9 // PUSH10 op PUSH10 // PUSH11 op PUSH11 // PUSH12 op PUSH12 // PUSH13 op PUSH13 // PUSH14 op PUSH14 // PUSH15 op PUSH15 // PUSH16 op PUSH16 // PUSH17 op PUSH17 // PUSH18 op PUSH18 // PUSH19 op PUSH19 // PUSH20 op PUSH20 // PUSH21 op PUSH21 // PUSH22 op PUSH22 // PUSH23 op PUSH23 // PUSH24 op PUSH24 // PUSH25 op PUSH25 // PUSH26 op PUSH26 // PUSH27 op PUSH27 // PUSH28 op PUSH28 // PUSH29 op PUSH29 // PUSH30 op PUSH30 // PUSH31 op PUSH31 // PUSH32 op PUSH32 // DUP1 op DUP1 // DUP2 op DUP2 // DUP3 op DUP3 // DUP4 op DUP4 // DUP5 op DUP5 // DUP6 op DUP6 // DUP7 op DUP7 // DUP8 op DUP8 // DUP9 op DUP9 // DUP10 op DUP10 // DUP11 op DUP11 // DUP12 op DUP12 // DUP13 op DUP13 // DUP14 op DUP14 // DUP15 op DUP15 // DUP16 op DUP16 // SWAP1 op SWAP1 // SWAP2 op SWAP2 // SWAP3 op SWAP3 // SWAP4 op SWAP4 // SWAP5 op SWAP5 // SWAP6 op SWAP6 // SWAP7 op SWAP7 // SWAP8 op SWAP8 // SWAP9 op SWAP9 // SWAP10 op SWAP10 // SWAP11 op SWAP11 // SWAP12 op SWAP12 // SWAP13 op SWAP13 // SWAP14 op SWAP14 // SWAP15 op SWAP15 // SWAP16 op SWAP16 )
type Operation ¶
type Operation struct { // Execute 指令的具体操作逻辑 Execute ExecutionFunc // GasCost 计算当前指令执行所需消耗的Gas GasCost gas.CalcGasFunc // ValidateStack 检查内存栈中的数据是否满足本操作执行的要求 ValidateStack mm.StackValidationFunc // MemorySize 计算本次操作所需要的内存大小 MemorySize mm.MemorySizeFunc // Halts 是否需要暂停(将会结束本合约后面操作的执行) Halts bool // Jumps 是否需要执行跳转(此种情况下PC不递增) Jumps bool // Writes 是否涉及到修改状态操作(在合约委托调用的情况下,此操作非法,将会抛异常) Writes bool // Valid 是否为有效操作 Valid bool // Reverts 是否恢复原始状态(强制暂停,将会结束本合约后面操作的执行) Reverts bool // Returns 是否返回 Returns bool }
Operation 定义指令操作的结构提
func NewByzantiumInstructionSet ¶
func NewByzantiumInstructionSet() [256]Operation
NewByzantiumInstructionSet 拜占庭 版本支持的指令集
func NewConstantinopleInstructionSet ¶
func NewConstantinopleInstructionSet() [256]Operation
NewConstantinopleInstructionSet 康士坦丁堡 版本支持的指令集
func NewFrontierInstructionSet ¶
func NewFrontierInstructionSet() [256]Operation
NewFrontierInstructionSet 边境 版本支持的指令集
func NewHomesteadInstructionSet ¶
func NewHomesteadInstructionSet() [256]Operation
NewHomesteadInstructionSet 家园 版本支持的指令集
type PrecompiledContract ¶
type PrecompiledContract interface { // 计算当前合约执行需要消耗的Gas RequiredGas(input []byte) uint64 // 执行预编译的合约固定逻辑,input为入参 Run(input []byte) ([]byte, error) }
PrecompiledContract 系统内置合约实现的接口,只包含两个操作: 1 根据合约自身逻辑和入参,计算所需Gas; 2 执行合约。
type StructLog ¶
type StructLog struct { // Pc pc指针 Pc uint64 `json:"pc"` // Op 操作码 Op string `json:"op"` // Gas gas Gas uint64 `json:"gas"` // GasCost 花费 GasCost uint64 `json:"gasCost"` // Memory 内存对象 Memory []string `json:"memory"` // MemorySize 内存大小 MemorySize int `json:"memSize"` // Stack 栈对象 Stack []string `json:"stack"` // Storage 存储对象 Storage map[common.Hash]common.Hash `json:"-"` // Depth 调用深度 Depth int `json:"depth"` // Err 错误信息 Err error `json:"-"` }
StructLog 指令执行状态信息
type Tracer ¶
type Tracer interface { // CaptureStart 开始记录 CaptureStart(from common.Address, to common.Address, call bool, input []byte, gas uint64, value uint64) error // CaptureState 保存状态 CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error // CaptureFault 保存错误 CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *mm.Memory, stack *mm.Stack, contract *Contract, depth int, err error) error // CaptureEnd 结束记录 CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error }
Tracer 接口用来在合约执行过程中收集跟踪数据。 CaptureState 会在EVM解释每条指令时调用。 需要注意的是,传入的引用参数不允许修改,否则会影响EVM解释执行;如果需要使用其中的数据,请复制后使用。
type TransferFunc ¶
TransferFunc 执行转账逻辑