Documentation ¶
Index ¶
- Constants
- Variables
- func NewMarkdownLogger(cfg *LogConfig, writer io.Writer) *mdLogger
- func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, 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 ErrInvalidOpCode
- type ErrStackOverflow
- type ErrStackUnderflow
- 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 *Memory, stack *Stack, ...) 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 *Memory, stack *Stack, ...) error
- type JumpTable
- type LogConfig
- type Memory
- func (m *Memory) Data() []byte
- func (m *Memory) GetCopy(offset, size int64) (cpy []byte)
- func (m *Memory) GetPtr(offset, size int64) []byte
- func (m *Memory) Len() int
- func (m *Memory) Print()
- func (m *Memory) Resize(size uint64)
- func (m *Memory) Set(offset, size uint64, value []byte)
- func (m *Memory) Set32(offset uint64, val *uint256.Int)
- type OpCode
- type PrecompiledContract
- type Stack
- type Storage
- type StructLog
- type Tracer
- type TransferFunc
Constants ¶
const ( GasQuickStep uint64 = 2 GasFastestStep uint64 = 3 GasFastStep uint64 = 5 GasMidStep uint64 = 8 GasSlowStep uint64 = 10 GasExtStep uint64 = 20 )
Gas costs
const ( EVMDebugOn = int32(1) EVMDebugOff = int32(0) )
Variables ¶
var ( // ErrInvalidSubroutineEntry means that a BEGINSUB was reached via iteration, // as opposed to from a JUMPSUB instruction ErrOutOfGas = errors.New("out of gas") ErrExecutionReverted = errors.New("execution reverted") ErrGasUintOverflow = errors.New("gas uint64 overflow") )
List evm execution errors
var PrecompiledContractsBerlin = map[common.Hash160Address]PrecompiledContract{ common.BytesToHash160Address([]byte{1}): &ecrecover{}, common.BytesToHash160Address([]byte{2}): &sha256hash{}, common.BytesToHash160Address([]byte{3}): &ripemd160hash{}, common.BytesToHash160Address([]byte{4}): &dataCopy{}, common.BytesToHash160Address([]byte{5}): &bigModExp{}, common.BytesToHash160Address([]byte{6}): &bn256AddIstanbul{}, common.BytesToHash160Address([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToHash160Address([]byte{8}): &bn256PairingIstanbul{}, common.BytesToHash160Address([]byte{9}): &blake2F{}, }
因为common.Address结构体中定义的是指针,map中的key值不能使用address作为key值来使用,于是使用Hash160Address作为key来进行索引 PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum contracts used in the Berlin release.
var PrecompiledContractsByzantium = map[common.Hash160Address]PrecompiledContract{ common.BytesToHash160Address([]byte{1}): &ecrecover{}, common.BytesToHash160Address([]byte{2}): &sha256hash{}, common.BytesToHash160Address([]byte{3}): &ripemd160hash{}, common.BytesToHash160Address([]byte{4}): &dataCopy{}, common.BytesToHash160Address([]byte{5}): &bigModExp{}, common.BytesToHash160Address([]byte{6}): &bn256AddByzantium{}, common.BytesToHash160Address([]byte{7}): &bn256ScalarMulByzantium{}, common.BytesToHash160Address([]byte{8}): &bn256PairingByzantium{}, }
PrecompiledContractsByzantium chain33平台支持君士坦丁堡版本支持的所有预编译合约指令,并从此版本开始同步支持EVM黄皮书中的新增指令; 保存拜占庭版本支持的所有预编译合约(包括之前版本的合约); 后面如果有硬分叉,需要在此处考虑分叉逻辑,根据区块高度分别处理; 下面的8个预编译指令,直接引用go-ethereum中的EVM实现
var PrecompiledContractsIstanbul = map[common.Hash160Address]PrecompiledContract{ common.BytesToHash160Address([]byte{1}): &ecrecover{}, common.BytesToHash160Address([]byte{2}): &sha256hash{}, common.BytesToHash160Address([]byte{3}): &ripemd160hash{}, common.BytesToHash160Address([]byte{4}): &dataCopy{}, common.BytesToHash160Address([]byte{5}): &bigModExp{}, common.BytesToHash160Address([]byte{6}): &bn256AddIstanbul{}, common.BytesToHash160Address([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToHash160Address([]byte{8}): &bn256PairingIstanbul{}, common.BytesToHash160Address([]byte{19}): &blake2F{}, }
PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum contracts used in the Istanbul release.
var PrecompiledContractsYoloV1 = map[common.Hash160Address]PrecompiledContract{ common.BytesToHash160Address([]byte{1}): &ecrecover{}, common.BytesToHash160Address([]byte{2}): &sha256hash{}, common.BytesToHash160Address([]byte{3}): &ripemd160hash{}, common.BytesToHash160Address([]byte{4}): &dataCopy{}, common.BytesToHash160Address([]byte{5}): &bigModExp{}, common.BytesToHash160Address([]byte{6}): &bn256AddIstanbul{}, common.BytesToHash160Address([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToHash160Address([]byte{8}): &bn256PairingIstanbul{}, common.BytesToHash160Address([]byte{9}): &blake2F{}, common.BytesToHash160Address([]byte{10}): &bls12381G1Add{}, common.BytesToHash160Address([]byte{11}): &bls12381G1Mul{}, common.BytesToHash160Address([]byte{12}): &bls12381G1MultiExp{}, common.BytesToHash160Address([]byte{13}): &bls12381G2Add{}, common.BytesToHash160Address([]byte{14}): &bls12381G2Mul{}, common.BytesToHash160Address([]byte{15}): &bls12381G2MultiExp{}, common.BytesToHash160Address([]byte{16}): &bls12381Pairing{}, common.BytesToHash160Address([]byte{17}): &bls12381MapG1{}, common.BytesToHash160Address([]byte{18}): &bls12381MapG2{}, }
PrecompiledContractsYoloV1 黄皮书v1版本兼容伊斯坦布尔版本 PrecompiledContractsYoloV1 contains the default set of pre-compiled Ethereum
Functions ¶
func NewMarkdownLogger ¶ added in v1.65.3
NewMarkdownLogger creates a logger which outputs information in a format adapted for human readability, and is also a valid markdown table
func RunPrecompiledContract ¶
func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error)
RunPrecompiledContract 调用预编译的合约逻辑并返回结果 It returns - the returned bytes, - the _remaining_ gas, - any error that occurred
Types ¶
type AccountRef ¶
AccountRef 账户对象引用 (实现了合约对象引用ContractRef接口) 因为在合约调用过程中,调用者有可能是外部账户,也有可能是合约账户,所以两者的结构是互通的
type CanTransferFunc ¶
CanTransferFunc 检查制定账户是否有足够的金额进行转账
type Config ¶
type Config struct { // Debug 调试开关 Debug int32 // 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 // TxHash TxHash []byte // 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 // contains filtered or unexported fields }
EVM 结构对象及其提供的操作方法,用于进行满足以太坊EVM黄皮书规范定义的智能合约代码的创建和执行 合约执行过程中会修改外部状态数据(数据操作通过外部注入) 在合约代码执行过程中发生的任何错误,都将会导致对状态数据的修改被回滚,并且依然消耗掉剩余的Gas 此对象为每个交易创建一个实例,其操作非线程安全
func NewEVM ¶
func NewEVM(ctx Context, statedb state.EVMStateDB, vmConfig Config, cfg *types.Chain33Config) *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 string, value uint64) (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 ErrInvalidOpCode ¶ added in v1.65.3
type ErrInvalidOpCode struct {
// contains filtered or unexported fields
}
ErrInvalidOpCode wraps an evm error when an invalid opcode is encountered.
func (*ErrInvalidOpCode) Error ¶ added in v1.65.3
func (e *ErrInvalidOpCode) Error() string
type ErrStackOverflow ¶ added in v1.65.3
type ErrStackOverflow struct {
// contains filtered or unexported fields
}
ErrStackOverflow wraps an evm error when the items on the stack exceeds the maximum allowance.
func (*ErrStackOverflow) Error ¶ added in v1.65.3
func (e *ErrStackOverflow) Error() string
type ErrStackUnderflow ¶ added in v1.65.3
type ErrStackUnderflow struct {
// contains filtered or unexported fields
}
ErrStackUnderflow wraps an evm error when the items on the stack less than the minimal requirement.
func (*ErrStackUnderflow) Error ¶ added in v1.65.3
func (e *ErrStackUnderflow) Error() string
type GetHashFunc ¶
GetHashFunc 获取制定高度区块的哈希 给 BLOCKHASH 指令使用
type Interpreter ¶
type Interpreter struct {
// contains filtered or unexported fields
}
EVMInterpreter 解释器接结构定义
func NewInterpreter ¶
func NewInterpreter(evm *EVM, cfg Config) *Interpreter
NewInterpreter 新创建一个解释器
func (*Interpreter) CanRun ¶ added in v1.65.3
func (in *Interpreter) CanRun(code []byte) bool
CanRun tells if the contract, passed as an argument, can be run by the current interpreter.
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 *Memory, stack *Stack, contract *Contract, depth int, err error) error
CaptureFault 目前实现为空
type JumpTable ¶ added in v1.65.1
type JumpTable [256]*operation
JumpTable contains the EVM opcodes supported at a given fork.
type LogConfig ¶ added in v1.65.1
type LogConfig struct { DisableMemory bool // disable memory capture DisableStack bool // disable stack capture DisableStorage bool // disable storage capture DisableReturnData bool // disable return data capture Debug bool // print output during capture end Limit int // maximum length of output, but zero means unlimited }
LogConfig are the configuration options for structured logger the EVM
type Memory ¶ added in v1.65.3
type Memory struct {
// contains filtered or unexported fields
}
Memory implements a simple memory model for the ethereum virtual machine.
func (*Memory) Print ¶ added in v1.65.3
func (m *Memory) Print()
Print dumps the content of the memory.
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 // EXTCODEHASH op EXTCODEHASH )
const ( // POP 0x50 存储相关操作 POP OpCode = 0x50 + iota // MLOAD op MLOAD // MSTORE op MSTORE // MSTORE8 op MSTORE8 // SLOAD op SLOAD // SSTORE op SSTORE // JUMP op JUMP // JUMPI op JUMPI // PC op PC // MSIZE op MSIZE // GAS op GAS // JUMPDEST op JUMPDEST // BEGINSUB OP BEGINSUB // RETURNSUB op RETURNSUB // JUMPSUB op JUMPSUB )
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 PrecompiledContract ¶
type PrecompiledContract interface { // 计算当前合约执行需要消耗的Gas RequiredGas(input []byte) uint64 // 执行预编译的合约固定逻辑,input为入参 Run(input []byte) ([]byte, error) }
PrecompiledContract 系统内置合约实现的接口,只包含两个操作: 1 根据合约自身逻辑和入参,计算所需Gas; 2 执行合约。
type Stack ¶ added in v1.65.3
type Stack struct {
// contains filtered or unexported fields
}
Stack is an object for basic stack operations. Items popped to the stack are expected to be changed and modified. stack does not take care of adding newly initialised objects.
type StructLog ¶
type StructLog struct { // Pc pc指针 Pc uint64 `json:"pc"` // Op 操作码 Op OpCode `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 []*big.Int `json:"stack"` // ReturnStack 返回栈 ReturnStack []uint32 `json:"returnStack"` // ReturnData 返回数据 ReturnData []byte `json:"returnData"` // Storage 存储对象 Storage map[common.Hash]common.Hash `json:"-"` // Depth 调用深度 Depth int `json:"depth"` // RefundCounter 退款统计 RefundCounter uint64 `json:"refund"` // 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 *Memory, stack *Stack, rData []byte, contract *Contract, depth int, err error) error // CaptureFault 保存错误 CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *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 执行转账逻辑