From 7ddf539301f32b3e222fdaf6a4d71b15401b65c3 Mon Sep 17 00:00:00 2001 From: Darren Kelly <107671032+darrenvechain@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:41:34 +0000 Subject: [PATCH 01/20] chore(deps): update net package (#932) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0b1fc54ba..9e8869618 100644 --- a/go.mod +++ b/go.mod @@ -55,7 +55,7 @@ require ( github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/rjeczalik/notify v0.9.3 // indirect - golang.org/x/net v0.24.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/go.sum b/go.sum index aded0cd24..668dc9758 100644 --- a/go.sum +++ b/go.sum @@ -178,8 +178,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 1997bcdb962ddea3fcbe571e49bb5107fc2e36ce Mon Sep 17 00:00:00 2001 From: tony Date: Tue, 23 Jan 2024 15:49:18 +0800 Subject: [PATCH 02/20] add new fork ETH_SH --- thor/fork_config.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/thor/fork_config.go b/thor/fork_config.go index 19e0b48b4..3e9fa377b 100644 --- a/thor/fork_config.go +++ b/thor/fork_config.go @@ -20,6 +20,7 @@ type ForkConfig struct { ETH_IST uint32 VIP214 uint32 FINALITY uint32 + ETH_SH uint32 } func (fc ForkConfig) String() string { @@ -36,6 +37,7 @@ func (fc ForkConfig) String() string { push("ETH_IST", fc.ETH_IST) push("VIP214", fc.VIP214) push("FINALITY", fc.FINALITY) + push("ETH_SH", fc.ETH_SH) return strings.Join(strs, ", ") } @@ -48,6 +50,7 @@ var NoFork = ForkConfig{ ETH_IST: math.MaxUint32, VIP214: math.MaxUint32, FINALITY: math.MaxUint32, + ETH_SH: math.MaxUint32, } // for well-known networks @@ -60,6 +63,7 @@ var forkConfigs = map[Bytes32]ForkConfig{ ETH_IST: 9254300, VIP214: 10653500, FINALITY: 13815000, // ~ Thu, 17 Nov 2022 08:09:50 GMT + ETH_SH: math.MaxUint32, }, // testnet MustParseBytes32("0x000000000b2bce3c70bc649a02749e8687721b09ed2e15997f466536b20bb127"): { @@ -69,6 +73,7 @@ var forkConfigs = map[Bytes32]ForkConfig{ ETH_IST: 9146700, VIP214: 10606800, FINALITY: 13086360, // ~ Fri, 19 Aug 2022 08:00:00 GMT + ETH_SH: math.MaxUint32, }, } From ba0523280cd94b56609c63633bf878daea486066 Mon Sep 17 00:00:00 2001 From: tony Date: Tue, 23 Jan 2024 15:53:11 +0800 Subject: [PATCH 03/20] evm: add shanghai to chain config --- runtime/runtime.go | 2 ++ vm/chain_config.go | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/runtime/runtime.go b/runtime/runtime.go index d1af44bb1..b3073e98a 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -60,6 +60,7 @@ var baseChainConfig = vm.ChainConfig{ Clique: nil, }, IstanbulBlock: nil, + ShanghaiBlock: nil, } // Output output of clause execution. @@ -98,6 +99,7 @@ func New( currentChainConfig := baseChainConfig currentChainConfig.ConstantinopleBlock = big.NewInt(int64(forkConfig.ETH_CONST)) currentChainConfig.IstanbulBlock = big.NewInt(int64(forkConfig.ETH_IST)) + currentChainConfig.ShanghaiBlock = big.NewInt(int64(forkConfig.ETH_SH)) if chain != nil { // use genesis id as chain id currentChainConfig.ChainID = new(big.Int).SetBytes(chain.GenesisID().Bytes()) diff --git a/vm/chain_config.go b/vm/chain_config.go index cf84108ae..12e26d48e 100644 --- a/vm/chain_config.go +++ b/vm/chain_config.go @@ -22,7 +22,8 @@ func isForked(s, head *big.Int) bool { // ChainConfig extends eth ChainConfig. type ChainConfig struct { params.ChainConfig - IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul) + IstanbulBlock *big.Int // Istanbul switch block (nil = no fork, 0 = already on istanbul) + ShanghaiBlock *big.Int // Shanghai switch block (nil = no fork, 0 = already on istanbul) } // IsIstanbul returns whether num is either equal to the Istanbul fork block or greater. @@ -30,6 +31,11 @@ func (c *ChainConfig) IsIstanbul(num *big.Int) bool { return isForked(c.IstanbulBlock, num) } +// IsShanghai returns whether num is either equal to the Shanghai fork block or greater. +func (c *ChainConfig) IsShanghai(num *big.Int) bool { + return isForked(c.ShanghaiBlock, num) +} + // Rules wraps ChainConfig and is merely syntatic sugar or can be used for functions // that do not have or require information about the block. // @@ -40,6 +46,7 @@ type Rules struct { IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool IsByzantium bool IsIstanbul bool + IsShanghai bool } // Rules ensures c's ChainID is not nil. @@ -48,5 +55,13 @@ func (c *ChainConfig) Rules(num *big.Int) Rules { if chainID == nil { chainID = new(big.Int) } - return Rules{ChainID: new(big.Int).Set(chainID), IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num), IsByzantium: c.IsByzantium(num), IsIstanbul: c.IsIstanbul((num))} + return Rules{ + ChainID: new(big.Int).Set(chainID), + IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), + IsEIP155: c.IsEIP155(num), + IsEIP158: c.IsEIP158(num), + IsByzantium: c.IsByzantium(num), + IsIstanbul: c.IsIstanbul((num)), + IsShanghai: c.IsShanghai((num)), + } } From e754c4af783212d261b8fac704d423f4b3bc9e0f Mon Sep 17 00:00:00 2001 From: tony Date: Tue, 23 Jan 2024 16:08:36 +0800 Subject: [PATCH 04/20] evm: add two op, BASEFEE and PUSH0 --- runtime/runtime.go | 1 + vm/evm.go | 1 + vm/instructions.go | 13 +++++++++++++ vm/interpreter.go | 2 +- vm/jump_table.go | 37 +++++++++++++++++++++++++++++-------- vm/opcodes.go | 14 ++++++++------ 6 files changed, 53 insertions(+), 15 deletions(-) diff --git a/runtime/runtime.go b/runtime/runtime.go index b3073e98a..8ba6d4974 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -310,6 +310,7 @@ func (rt *Runtime) newEVM(stateDB *statedb.StateDB, clauseIndex uint32, txCtx *x BlockNumber: new(big.Int).SetUint64(uint64(rt.ctx.Number)), Time: new(big.Int).SetUint64(rt.ctx.Time), Difficulty: &big.Int{}, + BaseFee: &big.Int{}, }, stateDB, &rt.chainConfig, rt.vmConfig) } diff --git a/vm/evm.go b/vm/evm.go index dc90009f3..fafe10860 100644 --- a/vm/evm.go +++ b/vm/evm.go @@ -91,6 +91,7 @@ type Context struct { BlockNumber *big.Int // Provides information for NUMBER Time *big.Int // Provides information for TIME Difficulty *big.Int // Provides information for DIFFICULTY + BaseFee *big.Int // Provides information for BASEFEE (0 if vm runs with NoBaseFee flag and 0 gas price) } // EVM is the Ethereum Virtual Machine base object and provides diff --git a/vm/instructions.go b/vm/instructions.go index ac475f9d6..17105f149 100644 --- a/vm/instructions.go +++ b/vm/instructions.go @@ -807,6 +807,19 @@ func opSelfBalance(_ *uint64, evm *EVM, contract *Contract, _ *Memory, stack *St return nil, nil } +// opBaseFee implements BASEFEE opcode +func opBaseFee(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + baseFee, _ := uint256.FromBig(evm.Context.BaseFee) + stack.push(baseFee) + return nil, nil +} + +// opPush0 implements the PUSH0 opcode +func opPush0(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + stack.push(new(uint256.Int)) + return nil, nil +} + // following functions are used by the instruction jump table // make log instruction function diff --git a/vm/interpreter.go b/vm/interpreter.go index 341e5a1f4..932f48b4b 100644 --- a/vm/interpreter.go +++ b/vm/interpreter.go @@ -36,7 +36,7 @@ type Config struct { // JumpTable contains the EVM instruction table. This // may be left uninitialised and will be set to the default // table. - JumpTable JumpTable + JumpTable *JumpTable } // Interpreter is used to run Ethereum based contracts and will utilise the diff --git a/vm/jump_table.go b/vm/jump_table.go index db05d16d1..b2f05cf69 100644 --- a/vm/jump_table.go +++ b/vm/jump_table.go @@ -54,11 +54,31 @@ var ( byzantiumInstructionSet = NewByzantiumInstructionSet() constantinopleInstructionSet = NewConstantinopleInstructionSet() istanbulInstructionSet = NewIstanbulInstructionSet() + shanghaiInstructionSet = NewShanghaiInstructionSet() ) -type JumpTable *[256]*operation +type JumpTable [256]*operation -func NewIstanbulInstructionSet() JumpTable { +// NewIstanbulInstructionSet returns the frontier, homestead +// byzantium, constantinople , istanbul and shanghai instructions. +func NewShanghaiInstructionSet() *JumpTable { + instructionSet := NewIstanbulInstructionSet() + instructionSet[BASEFEE] = &operation{ + execute: opBaseFee, + gasCost: constGasFunc(GasFastStep), + validateStack: makeStackFunc(0, 1), + } + instructionSet[PUSH0] = &operation{ + execute: opPush0, + gasCost: constGasFunc(GasFastStep), + validateStack: makeStackFunc(0, 1), + } + return instructionSet +} + +// NewIstanbulInstructionSet returns the frontier, homestead +// byzantium, constantinople and istanbul instructions. +func NewIstanbulInstructionSet() *JumpTable { instructionSet := NewConstantinopleInstructionSet() // ChainID opcode instructionSet[CHAINID] = &operation{ @@ -78,8 +98,8 @@ func NewIstanbulInstructionSet() JumpTable { } // NewConstantinopleInstructionSet returns the frontier, homestead -// byzantium and contantinople instructions. -func NewConstantinopleInstructionSet() JumpTable { +// byzantium and constantinople instructions. +func NewConstantinopleInstructionSet() *JumpTable { // instructions that can be executed during the byzantium phase. instructionSet := NewByzantiumInstructionSet() instructionSet[SHL] = &operation{ @@ -115,7 +135,7 @@ func NewConstantinopleInstructionSet() JumpTable { // NewByzantiumInstructionSet returns the frontier, homestead and // byzantium instructions. -func NewByzantiumInstructionSet() JumpTable { +func NewByzantiumInstructionSet() *JumpTable { // instructions that can be executed during the homestead phase. instructionSet := NewHomesteadInstructionSet() instructionSet[STATICCALL] = &operation{ @@ -149,7 +169,7 @@ func NewByzantiumInstructionSet() JumpTable { // NewHomesteadInstructionSet returns the frontier and homestead // instructions that can be executed during the homestead phase. -func NewHomesteadInstructionSet() JumpTable { +func NewHomesteadInstructionSet() *JumpTable { instructionSet := NewFrontierInstructionSet() instructionSet[DELEGATECALL] = &operation{ execute: opDelegateCall, @@ -163,8 +183,8 @@ func NewHomesteadInstructionSet() JumpTable { // NewFrontierInstructionSet returns the frontier instructions // that can be executed during the frontier phase. -func NewFrontierInstructionSet() JumpTable { - return &[256]*operation{ +func NewFrontierInstructionSet() *JumpTable { + instructionSet := JumpTable{ STOP: { execute: opStop, gasCost: constGasFunc(0), @@ -843,4 +863,5 @@ func NewFrontierInstructionSet() JumpTable { writes: true, }, } + return &instructionSet } diff --git a/vm/opcodes.go b/vm/opcodes.go index f8ef56734..24436aeab 100644 --- a/vm/opcodes.go +++ b/vm/opcodes.go @@ -25,11 +25,7 @@ type OpCode byte // IsPush specifies if an opcode is a PUSH opcode. func (op OpCode) IsPush() bool { - switch op { - case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32: - return true - } - return false + return PUSH0 <= op && op <= PUSH32 } // IsStaticJump specifies if an opcode is JUMP. @@ -103,6 +99,7 @@ const ( GASLIMIT CHAINID OpCode = 0x46 SELFBALANCE OpCode = 0x47 + BASEFEE OpCode = 0x48 ) // 0x50 range - 'storage' and execution. @@ -118,7 +115,8 @@ const ( PC MSIZE GAS - JUMPDEST + JUMPDEST OpCode = 0x5b + PUSH0 OpCode = 0x5f ) // 0x60 range. @@ -280,6 +278,7 @@ var opCodeToString = map[OpCode]string{ GASLIMIT: "GASLIMIT", CHAINID: "CHAINID", SELFBALANCE: "SELFBALANCE", + BASEFEE: "BASEFEE", // 0x50 range - 'storage' and execution. POP: "POP", @@ -296,6 +295,7 @@ var opCodeToString = map[OpCode]string{ MSIZE: "MSIZE", GAS: "GAS", JUMPDEST: "JUMPDEST", + PUSH0: "PUSH0", // 0x60 range - push. PUSH1: "PUSH1", @@ -432,6 +432,7 @@ var stringToOp = map[string]OpCode{ "CALLDATASIZE": CALLDATASIZE, "CALLDATACOPY": CALLDATACOPY, "CHAINID": CHAINID, + "BASEFEE": BASEFEE, "DELEGATECALL": DELEGATECALL, "STATICCALL": STATICCALL, "CODESIZE": CODESIZE, @@ -461,6 +462,7 @@ var stringToOp = map[string]OpCode{ "MSIZE": MSIZE, "GAS": GAS, "JUMPDEST": JUMPDEST, + "PUSH0": PUSH0, "PUSH1": PUSH1, "PUSH2": PUSH2, "PUSH3": PUSH3, From ece511b188df9c9e50e815076498a33454fb8204 Mon Sep 17 00:00:00 2001 From: tony Date: Mon, 22 Jan 2024 16:35:58 +0800 Subject: [PATCH 05/20] vm: move all evm errors together --- vm/errors.go | 6 ++- vm/evm.go | 2 +- vm/gas.go | 2 +- vm/gas_table.go | 92 +++++++++++++++++++++++----------------------- vm/instructions.go | 11 ++---- vm/interpreter.go | 6 +-- vm/jump_table.go | 4 -- 7 files changed, 60 insertions(+), 63 deletions(-) diff --git a/vm/errors.go b/vm/errors.go index 71abb6ca4..eb231fd18 100644 --- a/vm/errors.go +++ b/vm/errors.go @@ -22,8 +22,12 @@ var ( ErrOutOfGas = errors.New("out of gas") ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas") ErrDepth = errors.New("max call depth exceeded") - ErrTraceLimitReached = errors.New("the number of logs reached the specified limit") ErrInsufficientBalance = errors.New("insufficient balance for transfer") ErrContractAddressCollision = errors.New("contract address collision") ErrExecutionReverted = errors.New("execution reverted") + ErrInvalidJump = errors.New("invalid jump destination") + ErrWriteProtection = errors.New("write protection") + ErrReturnDataOutOfBounds = errors.New("return data out of bounds") + ErrMaxCodeSizeExceeded = errors.New("max code size exceeded") + ErrGasUintOverflow = errors.New("gas uint64 overflow") ) diff --git a/vm/evm.go b/vm/evm.go index fafe10860..a93a06065 100644 --- a/vm/evm.go +++ b/vm/evm.go @@ -496,7 +496,7 @@ func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.I } // Assign err if contract code size exceeds the max while the err is still empty. if maxCodeSizeExceeded && err == nil { - err = errMaxCodeSizeExceeded + err = ErrMaxCodeSizeExceeded } return ret, contractAddr, contract.Gas, err } diff --git a/vm/gas.go b/vm/gas.go index 174ebc78d..964f5b3da 100644 --- a/vm/gas.go +++ b/vm/gas.go @@ -50,7 +50,7 @@ func callGas(gasTable params.GasTable, availableGas, base uint64, callCost *uint } } if !callCost.IsUint64() { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return callCost.Uint64(), nil diff --git a/vm/gas_table.go b/vm/gas_table.go index 67041f2f5..b7d72348e 100644 --- a/vm/gas_table.go +++ b/vm/gas_table.go @@ -36,7 +36,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { // The constant 0xffffffffe0 is the highest number that can be used without // overflowing the gas calculation if newMemSize > 0xffffffffe0 { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } newMemSizeWords := toWordSize(newMemSize) @@ -70,20 +70,20 @@ func gasCallDataCopy(_ params.GasTable, _ *EVM, _ *Contract, stack *Stack, mem * var overflow bool if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } words, overflow := stack.Back(2).Uint64WithOverflow() if overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, words); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -96,20 +96,20 @@ func gasReturnDataCopy(_ params.GasTable, _ *EVM, _ *Contract, stack *Stack, mem var overflow bool if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } words, overflow := stack.Back(2).Uint64WithOverflow() if overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, words); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -140,7 +140,7 @@ func makeGasLog(n uint64) gasFunc { return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { requestedSize, overflow := stack.Back(1).Uint64WithOverflow() if overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } gas, err := memoryGasCost(mem, memorySize) @@ -149,18 +149,18 @@ func makeGasLog(n uint64) gasFunc { } if gas, overflow = math.SafeAdd(gas, params.LogGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, n*params.LogTopicGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } var memorySizeGas uint64 if memorySizeGas, overflow = math.SafeMul(requestedSize, params.LogDataGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, memorySizeGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -174,18 +174,18 @@ func gasSha3(_ params.GasTable, _ *EVM, _ *Contract, stack *Stack, mem *Memory, } if gas, overflow = math.SafeAdd(gas, params.Sha3Gas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } wordGas, overflow := stack.Back(1).Uint64WithOverflow() if overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Sha3WordGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, wordGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -198,18 +198,18 @@ func gasCodeCopy(_ params.GasTable, _ *EVM, _ *Contract, stack *Stack, mem *Memo var overflow bool if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } wordGas, overflow := stack.Back(2).Uint64WithOverflow() if overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, wordGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -222,20 +222,20 @@ func gasExtCodeCopy(gt params.GasTable, _ *EVM, _ *Contract, stack *Stack, mem * var overflow bool if gas, overflow = math.SafeAdd(gas, gt.ExtcodeCopy); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } wordGas, overflow := stack.Back(3).Uint64WithOverflow() if overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, wordGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -248,10 +248,10 @@ func gasMLoad(_ params.GasTable, _ *EVM, _ *Contract, _ *Stack, mem *Memory, mem var overflow bool gas, err := memoryGasCost(mem, memorySize) if err != nil { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -260,10 +260,10 @@ func gasMStore8(_ params.GasTable, _ *EVM, _ *Contract, _ *Stack, mem *Memory, m var overflow bool gas, err := memoryGasCost(mem, memorySize) if err != nil { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -272,10 +272,10 @@ func gasMStore(_ params.GasTable, _ *EVM, _ *Contract, _ *Stack, mem *Memory, me var overflow bool gas, err := memoryGasCost(mem, memorySize) if err != nil { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -287,7 +287,7 @@ func gasCreate(_ params.GasTable, _ *EVM, _ *Contract, _ *Stack, mem *Memory, me return 0, err } if gas, overflow = math.SafeAdd(gas, params.CreateGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -299,17 +299,17 @@ func gasCreate2(_ params.GasTable, _ *EVM, _ *Contract, stack *Stack, mem *Memor return 0, err } if gas, overflow = math.SafeAdd(gas, params.Create2Gas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } wordGas, overflow := stack.Back(2).Uint64WithOverflow() if overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Sha3WordGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, wordGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil @@ -335,7 +335,7 @@ func gasExp(gt params.GasTable, _ *EVM, _ *Contract, stack *Stack, _ *Memory, _ overflow bool ) if gas, overflow = math.SafeAdd(gas, GasSlowStep); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -363,7 +363,7 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem } var overflow bool if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) @@ -371,7 +371,7 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem return 0, err } if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -387,7 +387,7 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, } var overflow bool if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) @@ -395,7 +395,7 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, return 0, err } if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -441,7 +441,7 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *St } var overflow bool if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) @@ -449,7 +449,7 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *St return 0, err } if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } @@ -461,7 +461,7 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stac } var overflow bool if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) @@ -469,7 +469,7 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stac return 0, err } if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { - return 0, errGasUintOverflow + return 0, ErrGasUintOverflow } return gas, nil } diff --git a/vm/instructions.go b/vm/instructions.go index 17105f149..1820594e1 100644 --- a/vm/instructions.go +++ b/vm/instructions.go @@ -18,7 +18,6 @@ package vm import ( "errors" - "fmt" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -328,14 +327,14 @@ func opReturnDataCopy(_ *uint64, evm *EVM, _ *Contract, memory *Memory, stack *S ) offset64, overflow := dataOffset.Uint64WithOverflow() if overflow { - return nil, errReturnDataOutOfBounds + return nil, ErrReturnDataOutOfBounds } // we can reuse dataOffset now (aliasing it for clarity) var end = dataOffset end.Add(dataOffset, length) end64, overflow := end.Uint64WithOverflow() if overflow || uint64(len(evm.interpreter.returnData)) < end64 { - return nil, errReturnDataOutOfBounds + return nil, ErrReturnDataOutOfBounds } memory.Set(memOffset.Uint64(), length.Uint64(), evm.interpreter.returnData[offset64:end64]) return nil, nil @@ -531,8 +530,7 @@ func opSstore(_ *uint64, evm *EVM, contract *Contract, _ *Memory, stack *Stack) func opJump(pc *uint64, _ *EVM, contract *Contract, _ *Memory, stack *Stack) ([]byte, error) { pos := stack.popptr() if !contract.validJumpdest(pos) { - nop := contract.GetOp(pos.Uint64()) - return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos) + return nil, ErrInvalidJump } *pc = pos.Uint64() return nil, nil @@ -542,8 +540,7 @@ func opJumpi(pc *uint64, _ *EVM, contract *Contract, _ *Memory, stack *Stack) ([ pos, cond := stack.popptr(), stack.popptr() if !cond.IsZero() { if !contract.validJumpdest(pos) { - nop := contract.GetOp(pos.Uint64()) - return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos) + return nil, ErrInvalidJump } *pc = pos.Uint64() } else { diff --git a/vm/interpreter.go b/vm/interpreter.go index 932f48b4b..8ea44c148 100644 --- a/vm/interpreter.go +++ b/vm/interpreter.go @@ -88,7 +88,7 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation *operation, stac // account to the others means the state is modified and should also // return with an error. if operation.writes || (op == CALL && stack.Back(2).BitLen() > 0) { - return errWriteProtection + return ErrWriteProtection } } } @@ -186,12 +186,12 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er if operation.memorySize != nil { memSize, overflow := operation.memorySize(stack) if overflow { - return nil, errGasUintOverflow + return nil, ErrGasUintOverflow } // memory is expanded in words of 32 bytes. Gas // is also calculated in words. if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { - return nil, errGasUintOverflow + return nil, ErrGasUintOverflow } } // consume the gas and return an error if not enough gas is available. diff --git a/vm/jump_table.go b/vm/jump_table.go index b2f05cf69..7e437e69c 100644 --- a/vm/jump_table.go +++ b/vm/jump_table.go @@ -17,8 +17,6 @@ package vm import ( - "errors" - "github.com/ethereum/go-ethereum/params" ) @@ -29,8 +27,6 @@ type ( memorySizeFunc func(*Stack) (size uint64, overflow bool) ) -var errGasUintOverflow = errors.New("gas uint64 overflow") - type operation struct { // execute is the operation function execute executionFunc From 262791c3462ad053d963f96780bfadf2e8e281a5 Mon Sep 17 00:00:00 2001 From: tony Date: Tue, 23 Jan 2024 16:53:56 +0800 Subject: [PATCH 06/20] evm: reject code starting with 0xEF(EIP-3541) --- vm/chain_config.go | 3 ++- vm/errors.go | 1 + vm/evm.go | 21 +++++++++++++-------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/vm/chain_config.go b/vm/chain_config.go index 12e26d48e..1d6d28335 100644 --- a/vm/chain_config.go +++ b/vm/chain_config.go @@ -57,7 +57,8 @@ func (c *ChainConfig) Rules(num *big.Int) Rules { } return Rules{ ChainID: new(big.Int).Set(chainID), - IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), + IsHomestead: c.IsHomestead(num), + IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num), IsByzantium: c.IsByzantium(num), diff --git a/vm/errors.go b/vm/errors.go index eb231fd18..ac074c4dc 100644 --- a/vm/errors.go +++ b/vm/errors.go @@ -30,4 +30,5 @@ var ( ErrReturnDataOutOfBounds = errors.New("return data out of bounds") ErrMaxCodeSizeExceeded = errors.New("max code size exceeded") ErrGasUintOverflow = errors.New("gas uint64 overflow") + ErrInvalidCode = errors.New("invalid code: must not begin with 0xef") ) diff --git a/vm/evm.go b/vm/evm.go index a93a06065..87097546e 100644 --- a/vm/evm.go +++ b/vm/evm.go @@ -470,13 +470,21 @@ func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.I ret, err := run(evm, contract, nil) - // check whether the max code size has been exceeded - maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize + // Check whether the max code size has been exceeded, assign err if the case. + if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize { + err = ErrMaxCodeSizeExceeded + } + + // Reject code starting with 0xEF if EIP-3541 is enabled. + if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsShanghai { + err = ErrInvalidCode + } + // if the contract creation ran successfully and no errors were returned // calculate the gas required to store the code. If the code could not // be stored due to not enough gas set an error and let it be handled // by the error checking condition below. - if err == nil && !maxCodeSizeExceeded { + if err == nil { createDataGas := uint64(len(ret)) * params.CreateDataGas if contract.UseGas(createDataGas) { evm.StateDB.SetCode(contractAddr, ret) @@ -488,16 +496,13 @@ func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.I // When an error was returned by the EVM or when setting the creation code // above we revert to the snapshot and consume any gas remaining. Additionally // when we're in homestead this also counts for code storage gas errors. - if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) { + if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) { evm.StateDB.RevertToSnapshot(snapshot) if err != ErrExecutionReverted { contract.UseGas(contract.Gas) } } - // Assign err if contract code size exceeds the max while the err is still empty. - if maxCodeSizeExceeded && err == nil { - err = ErrMaxCodeSizeExceeded - } + return ret, contractAddr, contract.Gas, err } From 776eff3a9a9d217d7a12e4f95d3ed7d07990b8d7 Mon Sep 17 00:00:00 2001 From: tony Date: Thu, 25 Jan 2024 15:26:23 +0800 Subject: [PATCH 07/20] evm: shanghai related precompiles, enable EIP1108 and EIP2565 --- thor/params.go | 18 +++--- vm/contracts.go | 150 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 133 insertions(+), 35 deletions(-) diff --git a/thor/params.go b/thor/params.go index 5912c46c9..5122c5083 100644 --- a/thor/params.go +++ b/thor/params.go @@ -20,13 +20,17 @@ const ( ClauseGas uint64 = params.TxGas - TxGas ClauseGasContractCreation uint64 = params.TxGasContractCreation - TxGas - MinGasLimit uint64 = 1000 * 1000 - InitialGasLimit uint64 = 10 * 1000 * 1000 // InitialGasLimit gas limit value int genesis block. - GasLimitBoundDivisor uint64 = 1024 // from ethereum - GetBalanceGas uint64 = 400 //EIP158 gas table - SloadGas uint64 = 200 // EIP158 gas table - SstoreSetGas uint64 = params.SstoreSetGas - SstoreResetGas uint64 = params.SstoreResetGas + MinGasLimit uint64 = 1000 * 1000 + InitialGasLimit uint64 = 10 * 1000 * 1000 // InitialGasLimit gas limit value int genesis block. + GasLimitBoundDivisor uint64 = 1024 // from ethereum + GetBalanceGas uint64 = 400 // EIP158 gas table + SloadGas uint64 = 200 // EIP158 gas table + SstoreSetGas uint64 = params.SstoreSetGas + SstoreResetGas uint64 = params.SstoreResetGas + Bn256AddGasEIP1108 uint64 = 150 // Gas needed for an elliptic curve addition + Bn256ScalarMulGasEIP1108 uint64 = 6000 // Gas needed for an elliptic curve scalar multiplication + Bn256PairingBaseGasEIP1108 uint64 = 45000 // Base price for an elliptic curve pairing check + Bn256PairingPerPointGasEIP1108 uint64 = 34000 // Per-point price for an elliptic curve pairing check MaxTxWorkDelay uint32 = 30 // (unit: block) if tx delay exceeds this value, no energy can be exchanged. diff --git a/vm/contracts.go b/vm/contracts.go index ac6cd3fc8..8f6dc247c 100644 --- a/vm/contracts.go +++ b/vm/contracts.go @@ -58,9 +58,9 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ 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{}, + common.BytesToAddress([]byte{6}): &bn256Add{eip1108: false}, + common.BytesToAddress([]byte{7}): &bn256ScalarMul{eip1108: false}, + common.BytesToAddress([]byte{8}): &bn256Pairing{eip1108: false}, } // PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum @@ -70,34 +70,62 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ 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{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, + common.BytesToAddress([]byte{6}): &bn256Add{eip1108: false}, + common.BytesToAddress([]byte{7}): &bn256ScalarMul{eip1108: false}, + common.BytesToAddress([]byte{8}): &bn256Pairing{eip1108: false}, + common.BytesToAddress([]byte{9}): &blake2F{}, +} + +// PrecompiledContractsShanghai contains the default set of pre-compiled Ethereum +// contracts used in the Shanghai release. +// NOTE: Shanghai release does not introduce any changes in precompiled contracts. +// We are catching up from Istanbul, so Shanghai in thor includes eip1108 and eip2565. +var PrecompiledContractsShanghai = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &safe_ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, + common.BytesToAddress([]byte{6}): &bn256Add{eip1108: true}, + common.BytesToAddress([]byte{7}): &bn256ScalarMul{eip1108: true}, + common.BytesToAddress([]byte{8}): &bn256Pairing{eip1108: true}, common.BytesToAddress([]byte{9}): &blake2F{}, } var ( + PrecompiledAddressesShanghai []common.Address PrecompiledAddressesIstanbul []common.Address PrecompiledAddressesByzantium []common.Address + PrecompiledAddressesHomestead []common.Address ) func init() { + for k := range PrecompiledContractsHomestead { + PrecompiledAddressesHomestead = append(PrecompiledAddressesHomestead, k) + } for k := range PrecompiledContractsByzantium { PrecompiledAddressesByzantium = append(PrecompiledAddressesByzantium, k) } for k := range PrecompiledContractsIstanbul { PrecompiledAddressesIstanbul = append(PrecompiledAddressesIstanbul, k) } + for k := range PrecompiledContractsShanghai { + PrecompiledAddressesShanghai = append(PrecompiledAddressesShanghai, k) + } } // ActivePrecompiles returns the precompiles enabled with the current configuration. func ActivePrecompiles(rules Rules) []common.Address { switch { + case rules.IsShanghai: + return PrecompiledAddressesShanghai case rules.IsIstanbul: return PrecompiledAddressesIstanbul - default: + case rules.IsByzantium: return PrecompiledAddressesByzantium + default: + return PrecompiledAddressesHomestead } } @@ -227,14 +255,19 @@ func (c *dataCopy) Run(in []byte) ([]byte, error) { } // bigModExp implements a native big integer exponential modular operation. -type bigModExp struct{} +type bigModExp struct { + eip2565 bool +} var ( big0 = big.NewInt(0) big1 = big.NewInt(1) + big3 = big.NewInt(3) big4 = big.NewInt(4) + big7 = big.NewInt(7) big8 = big.NewInt(8) big16 = big.NewInt(16) + big20 = big.NewInt(20) big32 = big.NewInt(32) big64 = big.NewInt(64) big96 = big.NewInt(96) @@ -244,6 +277,34 @@ var ( big199680 = big.NewInt(199680) ) +// modexpMultComplexity implements bigModexp multComplexity formula, as defined in EIP-198 +// +// def mult_complexity(x): +// if x <= 64: return x ** 2 +// elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 +// else: return x ** 2 // 16 + 480 * x - 199680 +// +// where is x is max(length_of_MODULUS, length_of_BASE) +func modexpMultComplexity(x *big.Int) *big.Int { + switch { + case x.Cmp(big64) <= 0: + x.Mul(x, x) // x ** 2 + case x.Cmp(big1024) <= 0: + // (x ** 2 // 4 ) + ( 96 * x - 3072) + x = new(big.Int).Add( + new(big.Int).Div(new(big.Int).Mul(x, x), big4), + new(big.Int).Sub(new(big.Int).Mul(big96, x), big3072), + ) + default: + // (x ** 2 // 16) + (480 * x - 199680) + x = new(big.Int).Add( + new(big.Int).Div(new(big.Int).Mul(x, x), big16), + new(big.Int).Sub(new(big.Int).Mul(big480, x), big199680), + ) + } + return x +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bigModExp) RequiredGas(input []byte) uint64 { var ( @@ -278,25 +339,36 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { adjExpLen.Mul(big8, adjExpLen) } adjExpLen.Add(adjExpLen, big.NewInt(int64(msb))) - // Calculate the gas cost of the operation gas := new(big.Int).Set(math.BigMax(modLen, baseLen)) - switch { - case gas.Cmp(big64) <= 0: + if c.eip2565 { + // EIP-2565 has three changes + // 1. Different multComplexity (inlined here) + // in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565): + // + // def mult_complexity(x): + // ceiling(x/8)^2 + // + //where is x is max(length_of_MODULUS, length_of_BASE) + gas = gas.Add(gas, big7) + gas = gas.Div(gas, big8) gas.Mul(gas, gas) - case gas.Cmp(big1024) <= 0: - gas = new(big.Int).Add( - new(big.Int).Div(new(big.Int).Mul(gas, gas), big4), - new(big.Int).Sub(new(big.Int).Mul(big96, gas), big3072), - ) - default: - gas = new(big.Int).Add( - new(big.Int).Div(new(big.Int).Mul(gas, gas), big16), - new(big.Int).Sub(new(big.Int).Mul(big480, gas), big199680), - ) + + gas.Mul(gas, math.BigMax(adjExpLen, big1)) + // 2. Different divisor (`GQUADDIVISOR`) (3) + gas.Div(gas, big3) + if gas.BitLen() > 64 { + return math.MaxUint64 + } + // 3. Minimum price of 200 gas + if gas.Uint64() < 200 { + return 200 + } + return gas.Uint64() } + gas = modexpMultComplexity(gas) gas.Mul(gas, math.BigMax(adjExpLen, big1)) - gas.Div(gas, new(big.Int).SetUint64(params.ModExpQuadCoeffDiv)) + gas.Div(gas, big20) if gas.BitLen() > 64 { return math.MaxUint64 @@ -324,12 +396,19 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) { base = new(big.Int).SetBytes(getData(input, 0, baseLen)) exp = new(big.Int).SetBytes(getData(input, baseLen, expLen)) mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen)) + v []byte ) - if mod.BitLen() == 0 { + switch { + case mod.BitLen() == 0: // Modulo 0 is undefined, return zero return common.LeftPadBytes([]byte{}, int(modLen)), nil + case base.BitLen() == 1: // a bit length of 1 means it's 1 (or -1). + //If base == 1, then we can just return base % mod (if mod >= 1, which it is) + v = base.Mod(base, mod).Bytes() + default: + v = base.Exp(base, exp, mod).Bytes() } - return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil + return common.LeftPadBytes(v, int(modLen)), nil } // newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point, @@ -353,10 +432,15 @@ func newTwistPoint(blob []byte) (*bn256.G2, error) { } // bn256Add implements a native elliptic curve point addition. -type bn256Add struct{} +type bn256Add struct { + eip1108 bool +} // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256Add) RequiredGas(input []byte) uint64 { + if c.eip1108 { + return thor.Bn256AddGasEIP1108 + } return params.Bn256AddGas } @@ -375,10 +459,15 @@ func (c *bn256Add) Run(input []byte) ([]byte, error) { } // bn256ScalarMul implements a native elliptic curve scalar multiplication. -type bn256ScalarMul struct{} +type bn256ScalarMul struct { + eip1108 bool +} // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 { + if c.eip1108 { + return thor.Bn256ScalarMulGasEIP1108 + } return params.Bn256ScalarMulGas } @@ -404,10 +493,15 @@ var ( ) // bn256Pairing implements a pairing pre-compile for the bn256 curve -type bn256Pairing struct{} +type bn256Pairing struct { + eip1108 bool +} // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256Pairing) RequiredGas(input []byte) uint64 { + if c.eip1108 { + return thor.Bn256PairingBaseGasEIP1108 + uint64(len(input)/192)*thor.Bn256PairingPerPointGasEIP1108 + } return params.Bn256PairingBaseGas + uint64(len(input)/192)*params.Bn256PairingPerPointGas } From 4e9d9834669daf6b02b5a970f3c6589bdc25ba92 Mon Sep 17 00:00:00 2001 From: tony Date: Thu, 25 Jan 2024 15:34:44 +0800 Subject: [PATCH 08/20] evm: enable new instruction and precompile in ETH_SH --- runtime/runtime.go | 8 ++++- vm/evm.go | 90 +++++++++++++++++++++++++++------------------- vm/interpreter.go | 2 ++ 3 files changed, 62 insertions(+), 38 deletions(-) diff --git a/runtime/runtime.go b/runtime/runtime.go index 8ba6d4974..884fe6a83 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -106,7 +106,13 @@ func New( } // alloc precompiled contracts - if forkConfig.ETH_IST == ctx.Number { + if forkConfig.ETH_SH == ctx.Number { + for addr := range vm.PrecompiledContractsShanghai { + if err := state.SetCode(thor.Address(addr), EmptyRuntimeBytecode); err != nil { + panic(err) + } + } + } else if forkConfig.ETH_IST == ctx.Number { for addr := range vm.PrecompiledContractsIstanbul { if err := state.SetCode(thor.Address(addr), EmptyRuntimeBytecode); err != nil { panic(err) diff --git a/vm/evm.go b/vm/evm.go index 87097546e..fcba8ed32 100644 --- a/vm/evm.go +++ b/vm/evm.go @@ -49,20 +49,20 @@ type ( OnSuicideContractFunc func(evm *EVM, contractAddr common.Address, tokenReceiver common.Address) ) -// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. -func run(evm *EVM, contract *Contract, input []byte) ([]byte, error) { - if contract.CodeAddr != nil { - precompiles := PrecompiledContractsHomestead - if evm.ChainConfig().IsIstanbul(evm.BlockNumber) { - precompiles = PrecompiledContractsIstanbul - } else if evm.ChainConfig().IsByzantium(evm.BlockNumber) { - precompiles = PrecompiledContractsByzantium - } - if p := precompiles[*contract.CodeAddr]; p != nil { - return RunPrecompiledContract(p, input, contract) - } - } - return evm.interpreter.Run(contract, input) +func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { + var precompiles map[common.Address]PrecompiledContract + switch { + case evm.chainRules.IsShanghai: + precompiles = PrecompiledContractsShanghai + case evm.chainRules.IsIstanbul: + precompiles = PrecompiledContractsIstanbul + case evm.chainRules.IsByzantium: + precompiles = PrecompiledContractsByzantium + default: + precompiles = PrecompiledContractsHomestead + } + p, ok := precompiles[addr] + return p, ok } // Context provides the EVM with auxiliary information. Once provided @@ -185,7 +185,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return evm.call(caller, addr, input, gas, value) } -func (evm *EVM) call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) ([]byte, uint64, error) { +func (evm *EVM) call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { if evm.vmConfig.NoRecursion && evm.depth > 0 { return nil, gas, nil } @@ -195,22 +195,17 @@ func (evm *EVM) call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrDepth } // Fail if we're trying to transfer more than the available balance - if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { + if value.Sign() != 0 && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { return nil, gas, ErrInsufficientBalance } var ( - to = AccountRef(addr) - snapshot = evm.StateDB.Snapshot() + to = AccountRef(addr) + snapshot = evm.StateDB.Snapshot() + p, isPrecompile = evm.precompile(addr) ) if !evm.StateDB.Exist(addr) { - precompiles := PrecompiledContractsHomestead - if evm.ChainConfig().IsIstanbul(evm.BlockNumber) { - precompiles = PrecompiledContractsIstanbul - } else if evm.ChainConfig().IsByzantium(evm.BlockNumber) { - precompiles = PrecompiledContractsByzantium - } - if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 { + if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { return nil, gas, nil } evm.StateDB.CreateAccount(addr) @@ -222,7 +217,11 @@ func (evm *EVM) call(caller ContractRef, addr common.Address, input []byte, gas contract := NewContract(caller, to, value, gas) contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) - ret, err := run(evm, contract, input) + if isPrecompile { + ret, err = RunPrecompiledContract(p, input, contract) + } else { + ret, err = evm.interpreter.Run(contract, input) + } // When an error was returned by the EVM or when setting the creation code // above we revert to the snapshot and consume any gas remaining. Additionally @@ -266,8 +265,9 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } var ( - snapshot = evm.StateDB.Snapshot() - to = AccountRef(caller.Address()) + snapshot = evm.StateDB.Snapshot() + to = AccountRef(caller.Address()) + p, isPrecompile = evm.precompile(addr) ) // initialise a new contract and set the code that is to be used by the // EVM. The contract is a scoped environment for this execution context @@ -275,7 +275,12 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, contract := NewContract(caller, to, value, gas) contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) - ret, err = run(evm, contract, input) + if isPrecompile { + ret, err = RunPrecompiledContract(p, input, contract) + } else { + ret, err = evm.interpreter.Run(contract, input) + } + if err != nil { evm.StateDB.RevertToSnapshot(snapshot) if err != ErrExecutionReverted { @@ -308,15 +313,20 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } var ( - snapshot = evm.StateDB.Snapshot() - to = AccountRef(caller.Address()) + snapshot = evm.StateDB.Snapshot() + to = AccountRef(caller.Address()) + p, isPrecompile = evm.precompile(addr) ) // Initialise a new contract and make initialise the delegate values contract := NewContract(caller, to, nil, gas).AsDelegate() contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) - ret, err = run(evm, contract, input) + if isPrecompile { + ret, err = RunPrecompiledContract(p, input, contract) + } else { + ret, err = evm.interpreter.Run(contract, input) + } if err != nil { evm.StateDB.RevertToSnapshot(snapshot) if err != ErrExecutionReverted { @@ -355,8 +365,9 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte } var ( - to = AccountRef(addr) - snapshot = evm.StateDB.Snapshot() + to = AccountRef(addr) + snapshot = evm.StateDB.Snapshot() + p, isPrecompile = evm.precompile(addr) ) // Initialise a new contract and set the code that is to be used by the // EVM. The contract is a scoped environment for this execution context @@ -364,10 +375,15 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte contract := NewContract(caller, to, new(big.Int), gas) contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) + if isPrecompile { + ret, err = RunPrecompiledContract(p, input, contract) + } else { + ret, err = evm.interpreter.Run(contract, input) + } + // When an error was returned by the EVM or when setting the creation code // above we revert to the snapshot and consume any gas remaining. Additionally // when we're in Homestead this also counts for code storage gas errors. - ret, err = run(evm, contract, input) if err != nil { evm.StateDB.RevertToSnapshot(snapshot) if err != ErrExecutionReverted { @@ -447,7 +463,7 @@ func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.I // Create a new account on the state snapshot := evm.StateDB.Snapshot() evm.StateDB.CreateAccount(contractAddr) - if evm.ChainConfig().IsEIP158(evm.BlockNumber) { + if evm.chainRules.IsEIP158 { evm.StateDB.SetNonce(contractAddr, 1) } @@ -468,7 +484,7 @@ func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.I return nil, contractAddr, gas, nil } - ret, err := run(evm, contract, nil) + ret, err := evm.interpreter.Run(contract, nil) // Check whether the max code size has been exceeded, assign err if the case. if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize { diff --git a/vm/interpreter.go b/vm/interpreter.go index 8ea44c148..f4ff5cf7e 100644 --- a/vm/interpreter.go +++ b/vm/interpreter.go @@ -59,6 +59,8 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter { // we'll set the default jump table. if cfg.JumpTable == nil { switch { + case evm.ChainConfig().IsShanghai(evm.BlockNumber): + cfg.JumpTable = shanghaiInstructionSet case evm.ChainConfig().IsIstanbul(evm.BlockNumber): cfg.JumpTable = istanbulInstructionSet case evm.ChainConfig().IsConstantinople(evm.BlockNumber): From 64ca3bbebac727fcbb4ad78891762b058f7a4a47 Mon Sep 17 00:00:00 2001 From: tony Date: Mon, 26 Feb 2024 16:40:14 +0800 Subject: [PATCH 09/20] add testcases for eth_shang precompiles --- vm/contracts.go | 2 +- vm/contracts_test.go | 91 +++++++----- vm/interpreter_test.go | 2 +- vm/testdata/precompiles/bn256Add_eip1108.json | 114 +++++++++++++++ .../precompiles/bn256Pairing_eip1108.json | 100 +++++++++++++ vm/testdata/precompiles/bn256ScalarMul.json | 7 + .../precompiles/bn256ScalarMul_eip1108.json | 135 ++++++++++++++++++ 7 files changed, 410 insertions(+), 41 deletions(-) create mode 100644 vm/testdata/precompiles/bn256Add_eip1108.json create mode 100644 vm/testdata/precompiles/bn256Pairing_eip1108.json create mode 100644 vm/testdata/precompiles/bn256ScalarMul_eip1108.json diff --git a/vm/contracts.go b/vm/contracts.go index 8f6dc247c..2768e0d17 100644 --- a/vm/contracts.go +++ b/vm/contracts.go @@ -82,7 +82,7 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ // NOTE: Shanghai release does not introduce any changes in precompiled contracts. // We are catching up from Istanbul, so Shanghai in thor includes eip1108 and eip2565. var PrecompiledContractsShanghai = map[common.Address]PrecompiledContract{ - common.BytesToAddress([]byte{1}): &safe_ecrecover{}, + common.BytesToAddress([]byte{1}): &safeEcrecover{}, common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{}, common.BytesToAddress([]byte{4}): &dataCopy{}, diff --git a/vm/contracts_test.go b/vm/contracts_test.go index 9ab0a7a92..b9ad7b8a0 100644 --- a/vm/contracts_test.go +++ b/vm/contracts_test.go @@ -49,39 +49,19 @@ type precompiledFailureTest struct { // allPrecompiles does not map to the actual set of precompiles, as it also contains // repriced versions of precompiles at certain slots var allPrecompiles = map[common.Address]PrecompiledContract{ - common.BytesToAddress([]byte{1}): &safeEcrecover{}, - 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{}, - common.BytesToAddress([]byte{9}): &blake2F{}, -} - -// EIP-152 test vectors -var blake2FMalformedInputTests = []precompiledFailureTest{ - { - Input: "", - ExpectedError: errBlake2FInvalidInputLength.Error(), - Name: "vector 0: empty input", - }, - { - Input: "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - ExpectedError: errBlake2FInvalidInputLength.Error(), - Name: "vector 1: less than 213 bytes input", - }, - { - Input: "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - ExpectedError: errBlake2FInvalidInputLength.Error(), - Name: "vector 2: more than 213 bytes input", - }, - { - Input: "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002", - ExpectedError: errBlake2FInvalidFinalFlag.Error(), - Name: "vector 3: malformed final block indicator flag", - }, + common.BytesToAddress([]byte{1}): &safeEcrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, + common.BytesToAddress([]byte{0xf5}): &bigModExp{eip2565: true}, + common.BytesToAddress([]byte{6}): &bn256Add{eip1108: false}, + common.BytesToAddress([]byte{0xf6}): &bn256Add{eip1108: true}, + common.BytesToAddress([]byte{7}): &bn256ScalarMul{eip1108: false}, + common.BytesToAddress([]byte{0xf7}): &bn256ScalarMul{eip1108: true}, + common.BytesToAddress([]byte{8}): &bn256Pairing{eip1108: false}, + common.BytesToAddress([]byte{0xf8}): &bn256Pairing{eip1108: true}, + common.BytesToAddress([]byte{9}): &blake2F{}, } func testPrecompiled(addr string, test precompiledTest, t *testing.T) { @@ -236,10 +216,16 @@ func BenchmarkPrecompiledIdentity(bench *testing.B) { func TestPrecompiledModExp(t *testing.T) { testJSON("modexp", "05", t) } func BenchmarkPrecompiledModExp(b *testing.B) { benchJSON("modexp", "05", b) } +func TestPrecompiledModExpEip2565(t *testing.T) { testJSON("modexp_eip2565", "f5", t) } +func BenchmarkPrecompiledModExpEip2565(b *testing.B) { benchJSON("modexp_eip2565", "f5", b) } + // Tests the sample inputs from the elliptic curve addition EIP 213. func TestPrecompiledBn256Add(t *testing.T) { testJSON("bn256Add", "06", t) } func BenchmarkPrecompiledBn256Add(b *testing.B) { benchJSON("bn256Add", "06", b) } +func TestPrecompiledBn256AddEip1108(t *testing.T) { testJSON("bn256Add_eip1108", "f6", t) } +func BenchmarkPrecompiledBn256AddEip1108(b *testing.B) { benchJSON("bn256Add_eip1108", "f6", b) } + // Tests OOG func TestPrecompiledModExpOOG(t *testing.T) { modexpTests, err := loadJSON("modexp") @@ -255,21 +241,28 @@ func TestPrecompiledModExpOOG(t *testing.T) { func TestPrecompiledBn256ScalarMul(t *testing.T) { testJSON("bn256ScalarMul", "07", t) } func BenchmarkPrecompiledBn256ScalarMul(b *testing.B) { benchJSON("bn256ScalarMul", "07", b) } +func TestPrecompiledBn256ScalarMulEip1108(t *testing.T) { testJSON("bn256ScalarMul_eip1108", "f7", t) } +func BenchmarkPrecompiledBn256ScalarMulEip1108(b *testing.B) { + benchJSON("bn256ScalarMul_eip1108", "f7", b) +} + // Tests the sample inputs from the elliptic curve pairing check EIP 197. func TestPrecompiledBn256Pairing(t *testing.T) { testJSON("bn256Pairing", "08", t) } func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJSON("bn256Pairing", "08", b) } +func TestPrecompiledBn256PairingEip1108(t *testing.T) { testJSON("bn256Pairing_eip1108", "f8", t) } +func BenchmarkPrecompiledBn256PairingEip1108(b *testing.B) { + benchJSON("bn256Pairing_eip1108", "f8", b) +} + func TestPrecompiledBlake2F(t *testing.T) { testJSON("blake2F", "09", t) } func BenchmarkPrecompiledBlake2F(b *testing.B) { benchJSON("blake2F", "09", b) } -func TestPrecompileBlake2FMalformedInput(t *testing.T) { - for _, test := range blake2FMalformedInputTests { - testPrecompiledFailure("09", test, t) - } -} - func TestPrecompiledEcrecover(t *testing.T) { testJSON("ecRecover", "01", t) } +// Failure tests +func TestPrecompiledBlake2FFailure(t *testing.T) { testJSONFail("blake2F", "09", t) } + func testJSON(name, addr string, t *testing.T) { tests, err := loadJSON(name) if err != nil { @@ -280,6 +273,16 @@ func testJSON(name, addr string, t *testing.T) { } } +func testJSONFail(name, addr string, t *testing.T) { + tests, err := loadJSONFail(name) + if err != nil { + t.Fatal(err) + } + for _, test := range tests { + testPrecompiledFailure(addr, test, t) + } +} + func benchJSON(name, addr string, b *testing.B) { tests, err := loadJSON(name) if err != nil { @@ -300,6 +303,16 @@ func loadJSON(name string) ([]precompiledTest, error) { return testcases, err } +func loadJSONFail(name string) ([]precompiledFailureTest, error) { + data, err := os.ReadFile(fmt.Sprintf("testdata/precompiles/fail-%v.json", name)) + if err != nil { + return nil, err + } + var testcases []precompiledFailureTest + err = json.Unmarshal(data, &testcases) + return testcases, err +} + func TestAsDelegate(t *testing.T) { // Mock addresses parentCallerAddress := common.HexToAddress("0x01") diff --git a/vm/interpreter_test.go b/vm/interpreter_test.go index 8aa22df2e..f0962cbc9 100644 --- a/vm/interpreter_test.go +++ b/vm/interpreter_test.go @@ -14,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" ) -func GetNewInterpreter(jumpTable JumpTable) *Interpreter { +func GetNewInterpreter(jumpTable *JumpTable) *Interpreter { statedb := NoopStateDB{} evmConfig := Config{ diff --git a/vm/testdata/precompiles/bn256Add_eip1108.json b/vm/testdata/precompiles/bn256Add_eip1108.json new file mode 100644 index 000000000..b6fcd550e --- /dev/null +++ b/vm/testdata/precompiles/bn256Add_eip1108.json @@ -0,0 +1,114 @@ +[ + { + "Input": "18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7", + "Expected": "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915", + "Name": "chfast1", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c91518b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266", + "Expected": "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204", + "Name": "chfast2", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "cdetrio1", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "cdetrio2", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "cdetrio3", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "cdetrio4", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "cdetrio5", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "Name": "cdetrio6", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "Name": "cdetrio7", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "Name": "cdetrio8", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "Gas": 150, + "Name": "cdetrio9", + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "Gas": 150, + "Name": "cdetrio10", + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "Expected": "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4", + "Name": "cdetrio11", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4", + "Name": "cdetrio12", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98", + "Expected": "15bf2bb17880144b5d1cd2b1f46eff9d617bffd1ca57c37fb5a49bd84e53cf66049c797f9ce0d17083deb32b5e36f2ea2a212ee036598dd7624c168993d1355f", + "Name": "cdetrio13", + "Gas": 150, + "NoBenchmark": false + }, + { + "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "cdetrio14", + "Gas": 150, + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/vm/testdata/precompiles/bn256Pairing_eip1108.json b/vm/testdata/precompiles/bn256Pairing_eip1108.json new file mode 100644 index 000000000..3fbed6b87 --- /dev/null +++ b/vm/testdata/precompiles/bn256Pairing_eip1108.json @@ -0,0 +1,100 @@ +[ + { + "Input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "jeff1", + "Gas": 113000, + "NoBenchmark": false + }, + { + "Input": "2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "jeff2", + "Gas": 113000, + "NoBenchmark": false + }, + { + "Input": "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "jeff3", + "Gas": 113000, + "NoBenchmark": false + }, + { + "Input": "2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "jeff4", + "Gas": 147000, + "NoBenchmark": false + }, + { + "Input": "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "jeff5", + "Gas": 147000, + "NoBenchmark": false + }, + { + "Input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000", + "Name": "jeff6", + "Gas": 113000, + "NoBenchmark": false + }, + { + "Input": "", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "empty_data", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000", + "Name": "one_point", + "Gas": 79000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "two_point_match_2", + "Gas": 113000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "two_point_match_3", + "Gas": 113000, + "NoBenchmark": false + }, + { + "Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "two_point_match_4", + "Gas": 113000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "ten_point_match_1", + "Gas": 385000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "ten_point_match_2", + "Gas": 385000, + "NoBenchmark": false + }, + { + "Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Name": "ten_point_match_3", + "Gas": 113000, + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/vm/testdata/precompiles/bn256ScalarMul.json b/vm/testdata/precompiles/bn256ScalarMul.json index b70932470..1f91b9884 100644 --- a/vm/testdata/precompiles/bn256ScalarMul.json +++ b/vm/testdata/precompiles/bn256ScalarMul.json @@ -124,5 +124,12 @@ "Name": "cdetrio15", "Gas": 40000, "NoBenchmark": true + }, + { + "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "zeroScalar", + "Gas": 40000, + "NoBenchmark": true } ] \ No newline at end of file diff --git a/vm/testdata/precompiles/bn256ScalarMul_eip1108.json b/vm/testdata/precompiles/bn256ScalarMul_eip1108.json new file mode 100644 index 000000000..b0427fcc0 --- /dev/null +++ b/vm/testdata/precompiles/bn256ScalarMul_eip1108.json @@ -0,0 +1,135 @@ +[ + { + "Input": "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2", + "Expected": "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc", + "Name": "chfast1", + "Gas": 6000, + "NoBenchmark": false + }, + { + "Input": "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46", + "Expected": "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e", + "Name": "chfast2", + "Gas": 6000, + "NoBenchmark": false + }, + { + "Input": "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3", + "Expected": "14789d0d4a730b354403b5fac948113739e276c23e0258d8596ee72f9cd9d3230af18a63153e0ec25ff9f2951dd3fa90ed0197bfef6e2a1a62b5095b9d2b4a27", + "Name": "chfast3", + "Gas": 6000, + "NoBenchmark": false + }, + { + "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "Expected": "2cde5879ba6f13c0b5aa4ef627f159a3347df9722efce88a9afbb20b763b4c411aa7e43076f6aee272755a7f9b84832e71559ba0d2e0b17d5f9f01755e5b0d11", + "Name": "cdetrio1", + "Gas": 6000, + "NoBenchmark": false + }, + { + "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "Expected": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe3163511ddc1c3f25d396745388200081287b3fd1472d8339d5fecb2eae0830451", + "Name": "cdetrio2", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000100000000000000000000000000000000", + "Expected": "1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b", + "Name": "cdetrio3", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000009", + "Expected": "1dbad7d39dbc56379f78fac1bca147dc8e66de1b9d183c7b167351bfe0aeab742cd757d51289cd8dbd0acf9e673ad67d0f0a89f912af47ed1be53664f5692575", + "Name": "cdetrio4", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000001", + "Expected": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6", + "Name": "cdetrio5", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "Expected": "29e587aadd7c06722aabba753017c093f70ba7eb1f1c0104ec0564e7e3e21f6022b1143f6a41008e7755c71c3d00b6b915d386de21783ef590486d8afa8453b1", + "Name": "cdetrio6", + "Gas": 6000, + "NoBenchmark": false + }, + { + "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "Expected": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb", + "Name": "cdetrio7", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000100000000000000000000000000000000", + "Expected": "221a3577763877920d0d14a91cd59b9479f83b87a653bb41f82a3f6f120cea7c2752c7f64cdd7f0e494bff7b60419f242210f2026ed2ec70f89f78a4c56a1f15", + "Name": "cdetrio8", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000009", + "Expected": "228e687a379ba154554040f8821f4e41ee2be287c201aa9c3bc02c9dd12f1e691e0fd6ee672d04cfd924ed8fdc7ba5f2d06c53c1edc30f65f2af5a5b97f0a76a", + "Name": "cdetrio9", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000001", + "Expected": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c", + "Name": "cdetrio10", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "Expected": "00a1a234d08efaa2616607e31eca1980128b00b415c845ff25bba3afcb81dc00242077290ed33906aeb8e42fd98c41bcb9057ba03421af3f2d08cfc441186024", + "Name": "cdetrio11", + "Gas": 6000, + "NoBenchmark": false + }, + { + "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d9830644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "Expected": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b8692929ee761a352600f54921df9bf472e66217e7bb0cee9032e00acc86b3c8bfaf", + "Name": "cdetrio12", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000100000000000000000000000000000000", + "Expected": "1071b63011e8c222c5a771dfa03c2e11aac9666dd097f2c620852c3951a4376a2f46fe2f73e1cf310a168d56baa5575a8319389d7bfa6b29ee2d908305791434", + "Name": "cdetrio13", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000009", + "Expected": "19f75b9dd68c080a688774a6213f131e3052bd353a304a189d7a2ee367e3c2582612f545fb9fc89fde80fd81c68fc7dcb27fea5fc124eeda69433cf5c46d2d7f", + "Name": "cdetrio14", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000001", + "Expected": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98", + "Name": "cdetrio15", + "Gas": 6000, + "NoBenchmark": true + }, + { + "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000000", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "zeroScalar", + "Gas": 6000, + "NoBenchmark": true + } +] \ No newline at end of file From be00f13a54ea36234b2a24bc3ab4d2a010db2385 Mon Sep 17 00:00:00 2001 From: tony Date: Thu, 29 Feb 2024 16:55:26 +0800 Subject: [PATCH 10/20] runtime: add ETH_SH tests --- runtime/runtime_test.go | 813 ++++++++++++------ vm/chain_config.go | 2 +- vm/contracts.go | 2 +- .../{fail-blake2f.json => fail-blake2F.json} | 0 4 files changed, 534 insertions(+), 283 deletions(-) rename vm/testdata/precompiles/{fail-blake2f.json => fail-blake2F.json} (100%) diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index b86366e11..77dc6c8ab 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -30,314 +30,565 @@ func M(a ...interface{}) []interface{} { return a } -func TestContractSuicide(t *testing.T) { - db := muxdb.NewMem() - - g := genesis.NewDevnet() - stater := state.NewStater(db) - b0, _, _, err := g.Build(stater) - assert.Nil(t, err) - - repo, _ := chain.NewRepository(db, b0) - - // contract: - // - // pragma solidity ^0.4.18; - - // contract TestSuicide { - // function testSuicide() public { - // selfdestruct(msg.sender); - // } - // } - data, _ := hex.DecodeString("608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063085da1b3146044575b600080fd5b348015604f57600080fd5b5060566058565b005b3373ffffffffffffffffffffffffffffffffffffffff16ff00a165627a7a723058204cb70b653a3d1821e00e6ade869638e80fa99719931c9fa045cec2189d94086f0029") - time := b0.Header().Timestamp() - addr := thor.BytesToAddress([]byte("acc01")) - state := stater.NewState(b0.Header().StateRoot(), 0, 0, 0) - state.SetCode(addr, data) - state.SetEnergy(addr, big.NewInt(100), time) - state.SetBalance(addr, big.NewInt(200)) - - abi, _ := abi.New([]byte(`[{ - "constant": false, - "inputs": [], - "name": "testSuicide", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ]`)) - suicide, _ := abi.MethodByName("testSuicide") - methodData, err := suicide.EncodeInput() - if err != nil { - t.Fatal(err) - } +func TestEVMFunction(t *testing.T) { + target := thor.BytesToAddress([]byte("acc01")) - origin := genesis.DevAccounts()[0].Address - exec, _ := runtime.New(repo.NewChain(b0.Header().ID()), state, &xenv.BlockContext{Time: time}, thor.NoFork). - PrepareClause(tx.NewClause(&addr).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{Origin: origin}) - out, _, err := exec() - assert.Nil(t, err) - assert.Nil(t, out.VMErr) - - expectedTransfer := &tx.Transfer{ - Sender: addr, - Recipient: origin, - Amount: big.NewInt(200), + type context struct { + chain *chain.Chain + state *state.State + method *abi.Method } - assert.Equal(t, 1, len(out.Transfers)) - assert.Equal(t, expectedTransfer, out.Transfers[0]) - - event, _ := builtin.Energy.ABI.EventByName("Transfer") - expectedEvent := &tx.Event{ - Address: builtin.Energy.Address, - Topics: []thor.Bytes32{event.ID(), thor.BytesToBytes32(addr.Bytes()), thor.BytesToBytes32(origin.Bytes())}, - Data: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}, - } - assert.Equal(t, 1, len(out.Events)) - assert.Equal(t, expectedEvent, out.Events[0]) - - assert.Equal(t, M(big.NewInt(0), nil), M(state.GetBalance(addr))) - assert.Equal(t, M(big.NewInt(0), nil), M(state.GetEnergy(addr, time))) - bal, _ := new(big.Int).SetString("1000000000000000000000000000", 10) - assert.Equal(t, M(new(big.Int).Add(bal, big.NewInt(200)), nil), M(state.GetBalance(origin))) - assert.Equal(t, M(new(big.Int).Add(bal, big.NewInt(100)), nil), M(state.GetEnergy(origin, time))) -} - -func TestChainID(t *testing.T) { - db := muxdb.NewMem() - - g := genesis.NewDevnet() - - stater := state.NewStater(db) - b0, _, _, err := g.Build(stater) - assert.Nil(t, err) - - repo, _ := chain.NewRepository(db, b0) - - // pragma solidity >=0.7.0 <0.9.0; - // contract TestChainID { - - // function chainID() public view returns (uint256) { - // return block.chainid; - // } - // } - data, _ := hex.DecodeString("6080604052348015600f57600080fd5b506004361060285760003560e01c8063adc879e914602d575b600080fd5b60336047565b604051603e9190605c565b60405180910390f35b600046905090565b6056816075565b82525050565b6000602082019050606f6000830184604f565b92915050565b600081905091905056fea264697066735822122060b67d944ffa8f0c5ee69f2f47decc3dc175ea2e4341a4de3705d72b868ce2b864736f6c63430008010033") - addr := thor.BytesToAddress([]byte("acc01")) - state := stater.NewState(b0.Header().StateRoot(), 0, 0, 0) - state.SetCode(addr, data) - - abi, _ := abi.New([]byte(`[{ - "inputs": [], - "name": "chainID", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" + tests := []struct { + name string + code string + abi string + methodName string + testFunc func(*context, *testing.T) + }{ + { + name: "Contract Suicide", + code: "608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063085da1b3146044575b600080fd5b348015604f57600080fd5b5060566058565b005b3373ffffffffffffffffffffffffffffffffffffffff16ff00a165627a7a723058204cb70b653a3d1821e00e6ade869638e80fa99719931c9fa045cec2189d94086f0029", + abi: `[{"constant":false,"inputs":[],"name":"testSuicide","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]`, + methodName: "testSuicide", + testFunc: func(ctx *context, t *testing.T) { + // contract: + // + // pragma solidity ^0.4.18; + + // contract TestSuicide { + // function testSuicide() public { + // selfdestruct(msg.sender); + // } + // } + + // time := ctx.chain.GetBlockSummary() + // .Header().Timestamp() + + head, _ := ctx.chain.GetBlockSummary(0) + time := head.Header.Timestamp() + + ctx.state.SetEnergy(target, big.NewInt(100), time) + ctx.state.SetBalance(target, big.NewInt(200)) + + methodData, err := ctx.method.EncodeInput() + if err != nil { + t.Fatal(err) } - ], - "stateMutability": "view", - "type": "function" - } - ]`)) - chainIDMethod, _ := abi.MethodByName("chainID") - methodData, err := chainIDMethod.EncodeInput() - if err != nil { - t.Fatal(err) - } - - exec, _ := runtime.New(repo.NewChain(b0.Header().ID()), state, &xenv.BlockContext{}, thor.ForkConfig{ETH_IST: 0}). - PrepareClause(tx.NewClause(&addr).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) - out, _, err := exec() - assert.Nil(t, err) - assert.Nil(t, out.VMErr) - assert.Equal(t, g.ID(), thor.BytesToBytes32(out.Data)) -} - -func TestSelfBalance(t *testing.T) { - db := muxdb.NewMem() - - g := genesis.NewDevnet() - - stater := state.NewStater(db) - b0, _, _, err := g.Build(stater) - assert.Nil(t, err) - - repo, _ := chain.NewRepository(db, b0) + origin := genesis.DevAccounts()[0].Address + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{Time: time}, thor.NoFork). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{Origin: origin}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + expectedTransfer := &tx.Transfer{ + Sender: target, + Recipient: origin, + Amount: big.NewInt(200), + } + assert.Equal(t, 1, len(out.Transfers)) + assert.Equal(t, expectedTransfer, out.Transfers[0]) + + event, _ := builtin.Energy.ABI.EventByName("Transfer") + expectedEvent := &tx.Event{ + Address: builtin.Energy.Address, + Topics: []thor.Bytes32{event.ID(), thor.BytesToBytes32(target.Bytes()), thor.BytesToBytes32(origin.Bytes())}, + Data: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}, + } + assert.Equal(t, 1, len(out.Events)) + assert.Equal(t, expectedEvent, out.Events[0]) - // pragma solidity >=0.7.0 <0.9.0; - // contract TestSelfBalance { + assert.Equal(t, M(big.NewInt(0), nil), M(ctx.state.GetBalance(target))) + assert.Equal(t, M(big.NewInt(0), nil), M(ctx.state.GetEnergy(target, time))) - // function selfBalance() public view returns (uint256) { - // return address(this).balance; - // } - // } + bal, _ := new(big.Int).SetString("1000000000000000000000000000", 10) + assert.Equal(t, M(new(big.Int).Add(bal, big.NewInt(200)), nil), M(ctx.state.GetBalance(origin))) + assert.Equal(t, M(new(big.Int).Add(bal, big.NewInt(100)), nil), M(ctx.state.GetEnergy(origin, time))) - data, _ := hex.DecodeString("6080604052348015600f57600080fd5b506004361060285760003560e01c8063b0bed0ba14602d575b600080fd5b60336047565b604051603e9190605c565b60405180910390f35b600047905090565b6056816075565b82525050565b6000602082019050606f6000830184604f565b92915050565b600081905091905056fea2646970667358221220eeac1b7322c414db88987af09d3c8bdfde83bb378be9ac0e9ebe3fe34ecbcf2564736f6c63430008010033") - addr := thor.BytesToAddress([]byte("acc01")) - state := stater.NewState(b0.Header().StateRoot(), 0, 0, 0) - state.SetCode(addr, data) - state.SetBalance(addr, big.NewInt(100)) - - abi, _ := abi.New([]byte(`[{ - "inputs": [], - "name": "selfBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" + }, + }, + { + name: "ChainID", + code: "6080604052348015600f57600080fd5b506004361060285760003560e01c8063adc879e914602d575b600080fd5b60336047565b604051603e9190605c565b60405180910390f35b600046905090565b6056816075565b82525050565b6000602082019050606f6000830184604f565b92915050565b600081905091905056fea264697066735822122060b67d944ffa8f0c5ee69f2f47decc3dc175ea2e4341a4de3705d72b868ce2b864736f6c63430008010033", + abi: `[{"inputs":[],"name":"chainID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]`, + methodName: "chainID", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract TestChainID { + + // function chainID() public view returns (uint256) { + // return block.chainid; + // } + // } + + methodData, err := ctx.method.EncodeInput() + if err != nil { + t.Fatal(err) } - ], - "stateMutability": "view", - "type": "function" - } - ]`)) - selfBalanceMethod, _ := abi.MethodByName("selfBalance") - methodData, err := selfBalanceMethod.EncodeInput() - if err != nil { - t.Fatal(err) - } - exec, _ := runtime.New(repo.NewChain(b0.Header().ID()), state, &xenv.BlockContext{}, thor.ForkConfig{ETH_IST: 0}). - PrepareClause(tx.NewClause(&addr).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) - out, _, err := exec() - assert.Nil(t, err) - assert.Nil(t, out.VMErr) + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + assert.Equal(t, ctx.chain.GenesisID(), thor.BytesToBytes32(out.Data)) + }, + }, { + name: "Self Balance", + code: "6080604052348015600f57600080fd5b506004361060285760003560e01c8063b0bed0ba14602d575b600080fd5b60336047565b604051603e9190605c565b60405180910390f35b600047905090565b6056816075565b82525050565b6000602082019050606f6000830184604f565b92915050565b600081905091905056fea2646970667358221220eeac1b7322c414db88987af09d3c8bdfde83bb378be9ac0e9ebe3fe34ecbcf2564736f6c63430008010033", + abi: `[{"inputs":[],"name":"selfBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]`, + methodName: "selfBalance", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract TestSelfBalance { + + // function selfBalance() public view returns (uint256) { + // return address(this).balance; + // } + // } + + ctx.state.SetBalance(target, big.NewInt(100)) + + methodData, err := ctx.method.EncodeInput() + if err != nil { + t.Fatal(err) + } - assert.True(t, new(big.Int).SetBytes(out.Data).Cmp(big.NewInt(100)) == 0) -} + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + assert.True(t, new(big.Int).SetBytes(out.Data).Cmp(big.NewInt(100)) == 0) + }, + }, { + name: "Blake2F", + code: "608060405234801561001057600080fd5b50600436106100365760003560e01c806372de3cbd1461003b578063fc75ac471461006b575b600080fd5b61005560048036038101906100509190610894565b610089565b6040516100629190610a9b565b60405180910390f35b6100736102e5565b6040516100809190610a9b565b60405180910390f35b61009161063c565b61009961063c565b600087876000600281106100d6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015188600160028110610115577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015188600060048110610154577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015189600160048110610193577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518a6002600481106101d2577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518b600360048110610211577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518b600060028110610250577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518c60016002811061028f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518c6040516020016102ae9a999897969594939291906109e7565b604051602081830303815290604052905060408260d5602084016009600019fa6102d757600080fd5b819250505095945050505050565b6102ed61063c565b6000600c90506102fb61063c565b7f48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa581600060028110610356577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250507fd182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b816001600281106103ba577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250506103cb61065e565b7f616263000000000000000000000000000000000000000000000000000000000081600060048110610426577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201818152505060008160016004811061046b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250506000816002600481106104b0577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250506000816003600481106104f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002018181525050610506610680565b7f030000000000000000000000000000000000000000000000000000000000000081600060028110610561577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002019077ffffffffffffffffffffffffffffffffffffffffffffffff1916908177ffffffffffffffffffffffffffffffffffffffffffffffff1916815250506000816001600281106105de577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002019077ffffffffffffffffffffffffffffffffffffffffffffffff1916908177ffffffffffffffffffffffffffffffffffffffffffffffff1916815250506000600190506106328585858585610089565b9550505050505090565b6040518060400160405280600290602082028036833780820191505090505090565b6040518060800160405280600490602082028036833780820191505090505090565b6040518060400160405280600290602082028036833780820191505090505090565b60006106b56106b084610adb565b610ab6565b905080828560208602820111156106cb57600080fd5b60005b858110156106fb57816106e18882610855565b8452602084019350602083019250506001810190506106ce565b5050509392505050565b600061071861071384610b01565b610ab6565b9050808285602086028201111561072e57600080fd5b60005b8581101561075e57816107448882610855565b845260208401935060208301925050600181019050610731565b5050509392505050565b600061077b61077684610b27565b610ab6565b9050808285602086028201111561079157600080fd5b60005b858110156107c157816107a7888261086a565b845260208401935060208301925050600181019050610794565b5050509392505050565b600082601f8301126107dc57600080fd5b60026107e98482856106a2565b91505092915050565b600082601f83011261080357600080fd5b6004610810848285610705565b91505092915050565b600082601f83011261082a57600080fd5b6002610837848285610768565b91505092915050565b60008135905061084f81610ca1565b92915050565b60008135905061086481610cb8565b92915050565b60008135905061087981610ccf565b92915050565b60008135905061088e81610ce6565b92915050565b600080600080600061014086880312156108ad57600080fd5b60006108bb8882890161087f565b95505060206108cc888289016107cb565b94505060606108dd888289016107f2565b93505060e06108ee88828901610819565b92505061012061090088828901610840565b9150509295509295909350565b60006109198383610993565b60208301905092915050565b61092e81610b57565b6109388184610b6f565b925061094382610b4d565b8060005b8381101561097457815161095b878261090d565b965061096683610b62565b925050600181019050610947565b505050505050565b61098d61098882610b7a565b610bfd565b82525050565b61099c81610b86565b82525050565b6109b36109ae82610b86565b610c0f565b82525050565b6109ca6109c582610b90565b610c19565b82525050565b6109e16109dc82610bbc565b610c23565b82525050565b60006109f3828d6109d0565b600482019150610a03828c6109a2565b602082019150610a13828b6109a2565b602082019150610a23828a6109a2565b602082019150610a3382896109a2565b602082019150610a4382886109a2565b602082019150610a5382876109a2565b602082019150610a6382866109b9565b600882019150610a7382856109b9565b600882019150610a83828461097c565b6001820191508190509b9a5050505050505050505050565b6000604082019050610ab06000830184610925565b92915050565b6000610ac0610ad1565b9050610acc8282610bcc565b919050565b6000604051905090565b600067ffffffffffffffff821115610af657610af5610c47565b5b602082029050919050565b600067ffffffffffffffff821115610b1c57610b1b610c47565b5b602082029050919050565b600067ffffffffffffffff821115610b4257610b41610c47565b5b602082029050919050565b6000819050919050565b600060029050919050565b6000602082019050919050565b600081905092915050565b60008115159050919050565b6000819050919050565b60007fffffffffffffffff00000000000000000000000000000000000000000000000082169050919050565b600063ffffffff82169050919050565b610bd582610c76565b810181811067ffffffffffffffff82111715610bf457610bf3610c47565b5b80604052505050565b6000610c0882610c35565b9050919050565b6000819050919050565b6000819050919050565b6000610c2e82610c87565b9050919050565b6000610c4082610c94565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160e01b9050919050565b60008160f81b9050919050565b610caa81610b7a565b8114610cb557600080fd5b50565b610cc181610b86565b8114610ccc57600080fd5b50565b610cd881610b90565b8114610ce357600080fd5b50565b610cef81610bbc565b8114610cfa57600080fd5b5056fea2646970667358221220d54d4583b224c049d80665ae690afd0e7e998bf883c6b97472d292d1e2e5fa3e64736f6c63430008010033", + abi: `[{"inputs":[{"internalType":"uint32","name":"rounds","type":"uint32"},{"internalType":"bytes32[2]","name":"h","type":"bytes32[2]"},{"internalType":"bytes32[4]","name":"m","type":"bytes32[4]"},{"internalType":"bytes8[2]","name":"t","type":"bytes8[2]"},{"internalType":"bool","name":"f","type":"bool"}],"name":"F","outputs":[{"internalType":"bytes32[2]","name":"","type":"bytes32[2]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callF","outputs":[{"internalType":"bytes32[2]","name":"","type":"bytes32[2]"}],"stateMutability":"view","type":"function"}]`, + methodName: "callF", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract TestBlake2 { + // function F(uint32 rounds, bytes32[2] memory h, bytes32[4] memory m, bytes8[2] memory t, bool f) public view returns (bytes32[2] memory) { + // bytes32[2] memory output; + + // bytes memory args = abi.encodePacked(rounds, h[0], h[1], m[0], m[1], m[2], m[3], t[0], t[1], f); + + // assembly { + // if iszero(staticcall(not(0), 0x09, add(args, 32), 0xd5, output, 0x40)) { + // revert(0, 0) + // } + // } + + // return output; + // } + + // function callF() public view returns (bytes32[2] memory) { + // uint32 rounds = 12; + + // bytes32[2] memory h; + // h[0] = hex"48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5"; + // h[1] = hex"d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b"; + + // bytes32[4] memory m; + // m[0] = hex"6162630000000000000000000000000000000000000000000000000000000000"; + // m[1] = hex"0000000000000000000000000000000000000000000000000000000000000000"; + // m[2] = hex"0000000000000000000000000000000000000000000000000000000000000000"; + // m[3] = hex"0000000000000000000000000000000000000000000000000000000000000000"; + + // bytes8[2] memory t; + // t[0] = hex"03000000"; + // t[1] = hex"00000000"; + + // bool f = true; + + // // Expected output: + // // ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1 + // // 7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923 + // return F(rounds, h, m, t, f); + // } + // } + + methodData, err := ctx.method.EncodeInput() + if err != nil { + t.Fatal(err) + } -func TestBlake2(t *testing.T) { - db := muxdb.NewMem() + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) - g := genesis.NewDevnet() + var hashes [2][32]uint8 + ctx.method.DecodeOutput(out.Data, &hashes) - stater := state.NewStater(db) - b0, _, _, err := g.Build(stater) - assert.Nil(t, err) + assert.Equal(t, thor.MustParseBytes32("ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"), thor.Bytes32(hashes[0])) + assert.Equal(t, thor.MustParseBytes32("7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"), thor.Bytes32(hashes[1])) - repo, _ := chain.NewRepository(db, b0) + }, + }, + { + name: "pre ETH_SH deploy 0xEF started contract code", + code: "", + abi: "", + methodName: "", + testFunc: func(ctx *context, t *testing.T) { + code, _ := hex.DecodeString("60ef60005360016000f3") + + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.NoFork). + PrepareClause(tx.NewClause(nil).WithData(code), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + }, + }, + { + name: "ETH_SH deploy 0xEF started contract code", + code: "", + abi: "", + methodName: "", + testFunc: func(ctx *context, t *testing.T) { + code, _ := hex.DecodeString("60ef60005360016000f3") + + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(nil).WithData(code), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + + assert.Nil(t, err) + assert.NotNil(t, out.VMErr) + assert.Equal(t, out.VMErr.Error(), "invalid code: must not begin with 0xef") + }, + }, + { + name: "ETH_SH deploy None 0xEF started contract code", + code: "", + abi: "", + methodName: "", + testFunc: func(ctx *context, t *testing.T) { + code, _ := hex.DecodeString("60ee60005360016000f3") + + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(nil).WithData(code), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + }, + }, + { + name: "pre ETH_SH PUSH0", + code: "", + abi: "", + methodName: "", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract Simple { + // constructor() {} + // } + code, _ := hex.DecodeString("6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea2646970667358221220268d147b82c3959e7339f440b5861d98384629b096f1eac3e2ce7c55ebdc2daf64736f6c63430008180033") + + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.NoFork). + PrepareClause(tx.NewClause(nil).WithData(code), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + + assert.Nil(t, err) + assert.NotNil(t, out.VMErr) + assert.Equal(t, out.VMErr.Error(), "invalid opcode 0x5f") + }, + }, + { + name: "ETH_SH PUSH0", + code: "", + abi: "", + methodName: "", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract Simple { + // constructor() {} + // } + code, _ := hex.DecodeString("6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea2646970667358221220268d147b82c3959e7339f440b5861d98384629b096f1eac3e2ce7c55ebdc2daf64736f6c63430008180033") + + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(nil).WithData(code), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + }, + }, + { + name: "pre ETH_SH basefee", + code: "6080604052348015600e575f80fd5b50600436106026575f3560e01c80635cf2496914602a575b5f80fd5b60306044565b604051603b91906061565b60405180910390f35b5f48905090565b5f819050919050565b605b81604b565b82525050565b5f60208201905060725f8301846054565b9291505056fea2646970667358221220cbae2729fc31c76b30a14b2a0f61fdad920cb3c0ef1f7f5166e48d836d91cc6a64736f6c63430008180033", + abi: `[{"inputs":[],"name":"basefee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]`, + methodName: "basefee", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract TestBaseFee { + // function basefee() public view returns (uint256) { + // return block.basefee; + // } + // } + methodData, err := ctx.method.EncodeInput() + if err != nil { + t.Fatal(err) + } - // pragma solidity >=0.7.0 <0.9.0; - // contract TestBlake2 { - // function F(uint32 rounds, bytes32[2] memory h, bytes32[4] memory m, bytes8[2] memory t, bool f) public view returns (bytes32[2] memory) { - // bytes32[2] memory output; + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.NoFork). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.NotNil(t, out.VMErr) + assert.Equal(t, out.VMErr.Error(), "invalid opcode 0x5f") + }, + }, + { + name: "ETH_SH basefee", + code: "6080604052348015600e575f80fd5b50600436106026575f3560e01c80635cf2496914602a575b5f80fd5b60306044565b604051603b91906061565b60405180910390f35b5f48905090565b5f819050919050565b605b81604b565b82525050565b5f60208201905060725f8301846054565b9291505056fea2646970667358221220cbae2729fc31c76b30a14b2a0f61fdad920cb3c0ef1f7f5166e48d836d91cc6a64736f6c63430008180033", + abi: `[{"inputs":[],"name":"basefee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]`, + methodName: "basefee", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract TestBaseFee { + // function basefee() public view returns (uint256) { + // return block.basefee; + // } + // } + methodData, err := ctx.method.EncodeInput() + if err != nil { + t.Fatal(err) + } - // bytes memory args = abi.encodePacked(rounds, h[0], h[1], m[0], m[1], m[2], m[3], t[0], t[1], f); + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) - // assembly { - // if iszero(staticcall(not(0), 0x09, add(args, 32), 0xd5, output, 0x40)) { - // revert(0, 0) - // } - // } + assert.True(t, new(big.Int).SetBytes(out.Data).Cmp(big.NewInt(0)) == 0) + }, + }, + { + name: "Precompile modexp", + code: "608060405234801561001057600080fd5b506004361061002b5760003560e01c8063577b75b914610030575b600080fd5b61004a60048036038101906100459190610287565b610060565b60405161005791906102e9565b60405180910390f35b6000806000600573ffffffffffffffffffffffffffffffffffffffff168460405161008b9190610375565b600060405180830381855afa9150503d80600081146100c6576040519150601f19603f3d011682016040523d82523d6000602084013e6100cb565b606091505b509150915081610110576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101079061040f565b60405180910390fd5b80806020019051810190610124919061045b565b92505050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6101948261014b565b810181811067ffffffffffffffff821117156101b3576101b261015c565b5b80604052505050565b60006101c661012d565b90506101d2828261018b565b919050565b600067ffffffffffffffff8211156101f2576101f161015c565b5b6101fb8261014b565b9050602081019050919050565b82818337600083830152505050565b600061022a610225846101d7565b6101bc565b90508281526020810184848401111561024657610245610146565b5b610251848285610208565b509392505050565b600082601f83011261026e5761026d610141565b5b813561027e848260208601610217565b91505092915050565b60006020828403121561029d5761029c610137565b5b600082013567ffffffffffffffff8111156102bb576102ba61013c565b5b6102c784828501610259565b91505092915050565b6000819050919050565b6102e3816102d0565b82525050565b60006020820190506102fe60008301846102da565b92915050565b600081519050919050565b600081905092915050565b60005b8381101561033857808201518184015260208101905061031d565b60008484015250505050565b600061034f82610304565b610359818561030f565b935061036981856020860161031a565b80840191505092915050565b60006103818284610344565b915081905092915050565b600082825260208201905092915050565b7f4d6f64756c61724578706f6e656e74696174696f6e3a204661696c656420617460008201527f2063616c63756c6174696e672074686520726573756c74000000000000000000602082015250565b60006103f960378361038c565b91506104048261039d565b604082019050919050565b60006020820190508181036000830152610428816103ec565b9050919050565b610438816102d0565b811461044357600080fd5b50565b6000815190506104558161042f565b92915050565b60006020828403121561047157610470610137565b5b600061047f84828501610446565b9150509291505056fea2646970667358221220d362967bdc1ba52fd086eee3092f6a9a77f6993dd89c74e0718dfa791bc4794e64736f6c63430008180033", + abi: `[{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"}],"name":"modExpBytes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]`, + methodName: "modExpBytes", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract Math{ + // function modExpBytes(bytes memory input) public view returns (uint256) { + // (bool success, bytes memory result) = (address(5).staticcall(input)); + // require(success, "ModularExponentiation: Failed at calculating the result"); + // return abi.decode(result, (uint256)); + // } + // } + + // test case picked from vm/testdata/precompiles + input := common.FromHex("000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f") + methodData, err := ctx.method.EncodeInput(input) + if err != nil { + t.Fatal(err) + } - // return output; - // } - - // function callF() public view returns (bytes32[2] memory) { - // uint32 rounds = 12; - - // bytes32[2] memory h; - // h[0] = hex"48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5"; - // h[1] = hex"d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b"; - - // bytes32[4] memory m; - // m[0] = hex"6162630000000000000000000000000000000000000000000000000000000000"; - // m[1] = hex"0000000000000000000000000000000000000000000000000000000000000000"; - // m[2] = hex"0000000000000000000000000000000000000000000000000000000000000000"; - // m[3] = hex"0000000000000000000000000000000000000000000000000000000000000000"; - - // bytes8[2] memory t; - // t[0] = hex"03000000"; - // t[1] = hex"00000000"; - - // bool f = true; - - // // Expected output: - // // ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1 - // // 7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923 - // return F(rounds, h, m, t, f); - // } - // } - data, _ := hex.DecodeString("608060405234801561001057600080fd5b50600436106100365760003560e01c806372de3cbd1461003b578063fc75ac471461006b575b600080fd5b61005560048036038101906100509190610894565b610089565b6040516100629190610a9b565b60405180910390f35b6100736102e5565b6040516100809190610a9b565b60405180910390f35b61009161063c565b61009961063c565b600087876000600281106100d6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015188600160028110610115577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015188600060048110610154577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002015189600160048110610193577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518a6002600481106101d2577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518b600360048110610211577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518b600060028110610250577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518c60016002811061028f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201518c6040516020016102ae9a999897969594939291906109e7565b604051602081830303815290604052905060408260d5602084016009600019fa6102d757600080fd5b819250505095945050505050565b6102ed61063c565b6000600c90506102fb61063c565b7f48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa581600060028110610356577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250507fd182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b816001600281106103ba577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250506103cb61065e565b7f616263000000000000000000000000000000000000000000000000000000000081600060048110610426577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200201818152505060008160016004811061046b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250506000816002600481106104b0577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020020181815250506000816003600481106104f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002018181525050610506610680565b7f030000000000000000000000000000000000000000000000000000000000000081600060028110610561577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002019077ffffffffffffffffffffffffffffffffffffffffffffffff1916908177ffffffffffffffffffffffffffffffffffffffffffffffff1916815250506000816001600281106105de577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002019077ffffffffffffffffffffffffffffffffffffffffffffffff1916908177ffffffffffffffffffffffffffffffffffffffffffffffff1916815250506000600190506106328585858585610089565b9550505050505090565b6040518060400160405280600290602082028036833780820191505090505090565b6040518060800160405280600490602082028036833780820191505090505090565b6040518060400160405280600290602082028036833780820191505090505090565b60006106b56106b084610adb565b610ab6565b905080828560208602820111156106cb57600080fd5b60005b858110156106fb57816106e18882610855565b8452602084019350602083019250506001810190506106ce565b5050509392505050565b600061071861071384610b01565b610ab6565b9050808285602086028201111561072e57600080fd5b60005b8581101561075e57816107448882610855565b845260208401935060208301925050600181019050610731565b5050509392505050565b600061077b61077684610b27565b610ab6565b9050808285602086028201111561079157600080fd5b60005b858110156107c157816107a7888261086a565b845260208401935060208301925050600181019050610794565b5050509392505050565b600082601f8301126107dc57600080fd5b60026107e98482856106a2565b91505092915050565b600082601f83011261080357600080fd5b6004610810848285610705565b91505092915050565b600082601f83011261082a57600080fd5b6002610837848285610768565b91505092915050565b60008135905061084f81610ca1565b92915050565b60008135905061086481610cb8565b92915050565b60008135905061087981610ccf565b92915050565b60008135905061088e81610ce6565b92915050565b600080600080600061014086880312156108ad57600080fd5b60006108bb8882890161087f565b95505060206108cc888289016107cb565b94505060606108dd888289016107f2565b93505060e06108ee88828901610819565b92505061012061090088828901610840565b9150509295509295909350565b60006109198383610993565b60208301905092915050565b61092e81610b57565b6109388184610b6f565b925061094382610b4d565b8060005b8381101561097457815161095b878261090d565b965061096683610b62565b925050600181019050610947565b505050505050565b61098d61098882610b7a565b610bfd565b82525050565b61099c81610b86565b82525050565b6109b36109ae82610b86565b610c0f565b82525050565b6109ca6109c582610b90565b610c19565b82525050565b6109e16109dc82610bbc565b610c23565b82525050565b60006109f3828d6109d0565b600482019150610a03828c6109a2565b602082019150610a13828b6109a2565b602082019150610a23828a6109a2565b602082019150610a3382896109a2565b602082019150610a4382886109a2565b602082019150610a5382876109a2565b602082019150610a6382866109b9565b600882019150610a7382856109b9565b600882019150610a83828461097c565b6001820191508190509b9a5050505050505050505050565b6000604082019050610ab06000830184610925565b92915050565b6000610ac0610ad1565b9050610acc8282610bcc565b919050565b6000604051905090565b600067ffffffffffffffff821115610af657610af5610c47565b5b602082029050919050565b600067ffffffffffffffff821115610b1c57610b1b610c47565b5b602082029050919050565b600067ffffffffffffffff821115610b4257610b41610c47565b5b602082029050919050565b6000819050919050565b600060029050919050565b6000602082019050919050565b600081905092915050565b60008115159050919050565b6000819050919050565b60007fffffffffffffffff00000000000000000000000000000000000000000000000082169050919050565b600063ffffffff82169050919050565b610bd582610c76565b810181811067ffffffffffffffff82111715610bf457610bf3610c47565b5b80604052505050565b6000610c0882610c35565b9050919050565b6000819050919050565b6000819050919050565b6000610c2e82610c87565b9050919050565b6000610c4082610c94565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160e01b9050919050565b60008160f81b9050919050565b610caa81610b7a565b8114610cb557600080fd5b50565b610cc181610b86565b8114610ccc57600080fd5b50565b610cd881610b90565b8114610ce357600080fd5b50565b610cef81610bbc565b8114610cfa57600080fd5b5056fea2646970667358221220d54d4583b224c049d80665ae690afd0e7e998bf883c6b97472d292d1e2e5fa3e64736f6c63430008010033") - addr := thor.BytesToAddress([]byte("acc01")) - state := stater.NewState(b0.Header().StateRoot(), 0, 0, 0) - state.SetCode(addr, data) - - abi, _ := abi.New([]byte(`[{ - "inputs": [ - { - "internalType": "uint32", - "name": "rounds", - "type": "uint32" - }, - { - "internalType": "bytes32[2]", - "name": "h", - "type": "bytes32[2]" - }, - { - "internalType": "bytes32[4]", - "name": "m", - "type": "bytes32[4]" - }, - { - "internalType": "bytes8[2]", - "name": "t", - "type": "bytes8[2]" - }, - { - "internalType": "bool", - "name": "f", - "type": "bool" + forkConfig := thor.NoFork + forkConfig.ETH_IST = 0 + + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, forkConfig). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + gasBefore := math.MaxUint64 - out.LeftOverGas + + forkConfig.ETH_SH = 0 + exec, _ = runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, forkConfig). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err = exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + gasAfter := math.MaxUint64 - out.LeftOverGas + assert.True(t, gasBefore > gasAfter) + // test case picked from vm/testdata/precompiles, 5580-1365 + assert.Zero(t, gasBefore-gasAfter-4215) + }, + }, + { + name: "Precompile bn256Add", + code: "608060405234801561001057600080fd5b506004361061002b5760003560e01c806383304e8a14610030575b600080fd5b61004a60048036038101906100459190610287565b610060565b60405161005791906102e9565b60405180910390f35b6000806000600673ffffffffffffffffffffffffffffffffffffffff168460405161008b9190610375565b600060405180830381855afa9150503d80600081146100c6576040519150601f19603f3d011682016040523d82523d6000602084013e6100cb565b606091505b509150915081610110576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101079061040f565b60405180910390fd5b80806020019051810190610124919061045b565b92505050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6101948261014b565b810181811067ffffffffffffffff821117156101b3576101b261015c565b5b80604052505050565b60006101c661012d565b90506101d2828261018b565b919050565b600067ffffffffffffffff8211156101f2576101f161015c565b5b6101fb8261014b565b9050602081019050919050565b82818337600083830152505050565b600061022a610225846101d7565b6101bc565b90508281526020810184848401111561024657610245610146565b5b610251848285610208565b509392505050565b600082601f83011261026e5761026d610141565b5b813561027e848260208601610217565b91505092915050565b60006020828403121561029d5761029c610137565b5b600082013567ffffffffffffffff8111156102bb576102ba61013c565b5b6102c784828501610259565b91505092915050565b6000819050919050565b6102e3816102d0565b82525050565b60006020820190506102fe60008301846102da565b92915050565b600081519050919050565b600081905092915050565b60005b8381101561033857808201518184015260208101905061031d565b60008484015250505050565b600061034f82610304565b610359818561030f565b935061036981856020860161031a565b80840191505092915050565b60006103818284610344565b915081905092915050565b600082825260208201905092915050565b7f626e3235364164643a204661696c65642061742063616c63756c6174696e672060008201527f74686520726573756c7400000000000000000000000000000000000000000000602082015250565b60006103f9602a8361038c565b91506104048261039d565b604082019050919050565b60006020820190508181036000830152610428816103ec565b9050919050565b610438816102d0565b811461044357600080fd5b50565b6000815190506104558161042f565b92915050565b60006020828403121561047157610470610137565b5b600061047f84828501610446565b9150509291505056fea26469706673582212203fcccf78a18856182dd27cee0e3011ad18f00a9a29feb40bbcf800cdeb29a75a64736f6c63430008180033", + abi: `[{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"}],"name":"bn256AddBytes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]`, + methodName: "bn256AddBytes", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract Math{ + // function bn256AddBytes(bytes memory input) public view returns (uint256) { + // (bool success, bytes memory result) = (address(6).staticcall(input)); + // require(success, "bn256Add: Failed at calculating the result"); + // return abi.decode(result, (uint256)); + // } + // } + // test case picked from vm/testdata/precompiles + input := common.FromHex("18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7") + methodData, err := ctx.method.EncodeInput(input) + if err != nil { + t.Fatal(err) } - ], - "name": "F", - "outputs": [ - { - "internalType": "bytes32[2]", - "name": "", - "type": "bytes32[2]" + + forkConfig := thor.NoFork + forkConfig.ETH_IST = 0 + + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, forkConfig). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + gasBefore := math.MaxUint64 - out.LeftOverGas + + forkConfig.ETH_SH = 0 + exec, _ = runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, forkConfig). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err = exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + gasAfter := math.MaxUint64 - out.LeftOverGas + assert.True(t, gasBefore > gasAfter) + // test case picked from vm/testdata/precompiles, 500-150 + assert.Zero(t, gasBefore-gasAfter-350) + }, + }, + { + name: "Precompile bn256ScalarMul", + code: "608060405234801561001057600080fd5b506004361061002b5760003560e01c8063701961aa14610030575b600080fd5b61004a60048036038101906100459190610274565b610060565b604051610057919061033c565b60405180910390f35b6060600080600773ffffffffffffffffffffffffffffffffffffffff168460405161008b919061039a565b600060405180830381855afa9150503d80600081146100c6576040519150601f19603f3d011682016040523d82523d6000602084013e6100cb565b606091505b509150915081610110576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161010790610434565b60405180910390fd5b8092505050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61018182610138565b810181811067ffffffffffffffff821117156101a05761019f610149565b5b80604052505050565b60006101b361011a565b90506101bf8282610178565b919050565b600067ffffffffffffffff8211156101df576101de610149565b5b6101e882610138565b9050602081019050919050565b82818337600083830152505050565b6000610217610212846101c4565b6101a9565b90508281526020810184848401111561023357610232610133565b5b61023e8482856101f5565b509392505050565b600082601f83011261025b5761025a61012e565b5b813561026b848260208601610204565b91505092915050565b60006020828403121561028a57610289610124565b5b600082013567ffffffffffffffff8111156102a8576102a7610129565b5b6102b484828501610246565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156102f75780820151818401526020810190506102dc565b60008484015250505050565b600061030e826102bd565b61031881856102c8565b93506103288185602086016102d9565b61033181610138565b840191505092915050565b600060208201905081810360008301526103568184610303565b905092915050565b600081905092915050565b6000610374826102bd565b61037e818561035e565b935061038e8185602086016102d9565b80840191505092915050565b60006103a68284610369565b915081905092915050565b600082825260208201905092915050565b7f626e3235364164643a204661696c65642061742063616c63756c6174696e672060008201527f74686520726573756c7400000000000000000000000000000000000000000000602082015250565b600061041e602a836103b1565b9150610429826103c2565b604082019050919050565b6000602082019050818103600083015261044d81610411565b905091905056fea2646970667358221220469c90049edd24983926f66efd6ae8e5ca288ad0b2b206fde2e8a5fb6875a81764736f6c63430008180033", + abi: `[{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"}],"name":"bn256ScalarMulBytes","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}]`, + methodName: "bn256ScalarMulBytes", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract Math{ + // function bn256ScalarMulBytes(bytes memory input) public view returns (bytes memory) { + // (bool success, bytes memory result) = (address(7).staticcall(input)); + // require(success, "bn256ScalarMul: Failed at calculating the result"); + // return result; + // } + // } + // test case picked from vm/testdata/precompiles + input := common.FromHex("2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2") + methodData, err := ctx.method.EncodeInput(input) + if err != nil { + t.Fatal(err) } - ], - "stateMutability": "view", - "type": "function" + + forkConfig := thor.NoFork + forkConfig.ETH_IST = 0 + + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, forkConfig). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + gasBefore := math.MaxUint64 - out.LeftOverGas + + forkConfig.ETH_SH = 0 + exec, _ = runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, forkConfig). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err = exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + gasAfter := math.MaxUint64 - out.LeftOverGas + assert.True(t, gasBefore > gasAfter) + // test case picked from vm/testdata/precompiles, 40000-6000 + assert.Zero(t, gasBefore-gasAfter-34000) + }, }, { - "inputs": [], - "name": "callF", - "outputs": [ - { - "internalType": "bytes32[2]", - "name": "", - "type": "bytes32[2]" + name: "Precompile bn256Pairing", + code: "608060405234801561001057600080fd5b506004361061002b5760003560e01c806382b72bfd14610030575b600080fd5b61004a60048036038101906100459190610287565b610060565b60405161005791906102e9565b60405180910390f35b6000806000600873ffffffffffffffffffffffffffffffffffffffff168460405161008b9190610375565b600060405180830381855afa9150503d80600081146100c6576040519150601f19603f3d011682016040523d82523d6000602084013e6100cb565b606091505b509150915081610110576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101079061040f565b60405180910390fd5b80806020019051810190610124919061045b565b92505050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6101948261014b565b810181811067ffffffffffffffff821117156101b3576101b261015c565b5b80604052505050565b60006101c661012d565b90506101d2828261018b565b919050565b600067ffffffffffffffff8211156101f2576101f161015c565b5b6101fb8261014b565b9050602081019050919050565b82818337600083830152505050565b600061022a610225846101d7565b6101bc565b90508281526020810184848401111561024657610245610146565b5b610251848285610208565b509392505050565b600082601f83011261026e5761026d610141565b5b813561027e848260208601610217565b91505092915050565b60006020828403121561029d5761029c610137565b5b600082013567ffffffffffffffff8111156102bb576102ba61013c565b5b6102c784828501610259565b91505092915050565b6000819050919050565b6102e3816102d0565b82525050565b60006020820190506102fe60008301846102da565b92915050565b600081519050919050565b600081905092915050565b60005b8381101561033857808201518184015260208101905061031d565b60008484015250505050565b600061034f82610304565b610359818561030f565b935061036981856020860161031a565b80840191505092915050565b60006103818284610344565b915081905092915050565b600082825260208201905092915050565b7f626e32353650616972696e673a204661696c65642061742063616c63756c617460008201527f696e672074686520726573756c74000000000000000000000000000000000000602082015250565b60006103f9602e8361038c565b91506104048261039d565b604082019050919050565b60006020820190508181036000830152610428816103ec565b9050919050565b610438816102d0565b811461044357600080fd5b50565b6000815190506104558161042f565b92915050565b60006020828403121561047157610470610137565b5b600061047f84828501610446565b9150509291505056fea26469706673582212203f7c1d2240693474593d78d55b56a6b10de6fb80fd59956aea8108863cc779b064736f6c63430008180033", + abi: `[{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"}],"name":"bn256PairingBytes","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}]`, + methodName: "bn256PairingBytes", + testFunc: func(ctx *context, t *testing.T) { + // pragma solidity >=0.7.0 <0.9.0; + // contract Math{ + // contract Math{ + // function bn256PairingBytes(bytes memory input) public view returns (uint256) { + // (bool success, bytes memory result) = (address(8).staticcall(input)); + // require(success, "bn256Pairing: Failed at calculating the result"); + // return abi.decode(result, (uint256)); + // } + // } + // test case picked from vm/testdata/precompiles + input := common.FromHex("1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa") + methodData, err := ctx.method.EncodeInput(input) + if err != nil { + t.Fatal(err) } - ], - "stateMutability": "view", - "type": "function" - } - ]`)) - callFMethod, _ := abi.MethodByName("callF") - methodData, err := callFMethod.EncodeInput() - if err != nil { - t.Fatal(err) - } - exec, _ := runtime.New(repo.NewChain(b0.Header().ID()), state, &xenv.BlockContext{}, thor.ForkConfig{ETH_IST: 0}). - PrepareClause(tx.NewClause(&addr).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) - out, _, err := exec() - assert.Nil(t, err) - assert.Nil(t, out.VMErr) + forkConfig := thor.NoFork + forkConfig.ETH_IST = 0 + + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, forkConfig). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + gasBefore := math.MaxUint64 - out.LeftOverGas + + forkConfig.ETH_SH = 0 + exec, _ = runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, forkConfig). + PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err = exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + + gasAfter := math.MaxUint64 - out.LeftOverGas + assert.True(t, gasBefore > gasAfter) + // test case picked from vm/testdata/precompiles, 260000-113000 + assert.Zero(t, gasBefore-gasAfter-147000) + }, + }, + } - var hashes [2][32]uint8 - callFMethod.DecodeOutput(out.Data, &hashes) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + db := muxdb.NewMem() + g := genesis.NewDevnet() + stater := state.NewStater(db) + b0, _, _, _ := g.Build(stater) + repo, _ := chain.NewRepository(db, b0) + + ctx := &context{ + repo.NewChain(b0.Header().ID()), + stater.NewState(b0.Header().StateRoot(), 0, 0, 0), + nil, + } + + if len(tt.methodName) > 0 { + abi, _ := abi.New([]byte(tt.abi)) + method, _ := abi.MethodByName(tt.methodName) + + ctx.method = method + } + + if len(tt.code) > 0 { + code, err := hex.DecodeString(tt.code) + if err != nil { + t.Fatal(err) + } + ctx.state.SetCode(target, code) + } - assert.Equal(t, thor.MustParseBytes32("ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"), thor.Bytes32(hashes[0])) - assert.Equal(t, thor.MustParseBytes32("7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"), thor.Bytes32(hashes[1])) + tt.testFunc(ctx, t) + }) + } } func TestCall(t *testing.T) { diff --git a/vm/chain_config.go b/vm/chain_config.go index 1d6d28335..62cd17837 100644 --- a/vm/chain_config.go +++ b/vm/chain_config.go @@ -23,7 +23,7 @@ func isForked(s, head *big.Int) bool { type ChainConfig struct { params.ChainConfig IstanbulBlock *big.Int // Istanbul switch block (nil = no fork, 0 = already on istanbul) - ShanghaiBlock *big.Int // Shanghai switch block (nil = no fork, 0 = already on istanbul) + ShanghaiBlock *big.Int // Shanghai switch block (nil = no fork, 0 = already on shanghai) } // IsIstanbul returns whether num is either equal to the Istanbul fork block or greater. diff --git a/vm/contracts.go b/vm/contracts.go index 2768e0d17..e235c7197 100644 --- a/vm/contracts.go +++ b/vm/contracts.go @@ -57,7 +57,7 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{}, common.BytesToAddress([]byte{4}): &dataCopy{}, - common.BytesToAddress([]byte{5}): &bigModExp{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, common.BytesToAddress([]byte{6}): &bn256Add{eip1108: false}, common.BytesToAddress([]byte{7}): &bn256ScalarMul{eip1108: false}, common.BytesToAddress([]byte{8}): &bn256Pairing{eip1108: false}, diff --git a/vm/testdata/precompiles/fail-blake2f.json b/vm/testdata/precompiles/fail-blake2F.json similarity index 100% rename from vm/testdata/precompiles/fail-blake2f.json rename to vm/testdata/precompiles/fail-blake2F.json From 442b3462999d27bfcc277043293caccc62a58119 Mon Sep 17 00:00:00 2001 From: tony Date: Fri, 12 Apr 2024 10:44:59 +0100 Subject: [PATCH 11/20] evm: fix gas cost for basefee and push0 --- vm/jump_table.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/jump_table.go b/vm/jump_table.go index 7e437e69c..f31ce377b 100644 --- a/vm/jump_table.go +++ b/vm/jump_table.go @@ -61,12 +61,12 @@ func NewShanghaiInstructionSet() *JumpTable { instructionSet := NewIstanbulInstructionSet() instructionSet[BASEFEE] = &operation{ execute: opBaseFee, - gasCost: constGasFunc(GasFastStep), + gasCost: constGasFunc(GasQuickStep), validateStack: makeStackFunc(0, 1), } instructionSet[PUSH0] = &operation{ execute: opPush0, - gasCost: constGasFunc(GasFastStep), + gasCost: constGasFunc(GasQuickStep), validateStack: makeStackFunc(0, 1), } return instructionSet From 09375e37b097c5f8f401f8cdf28c23a233a5e558 Mon Sep 17 00:00:00 2001 From: Paolo Galli Date: Fri, 26 Apr 2024 09:52:06 +0200 Subject: [PATCH 12/20] test: add tests for shanghai new opcodes --- runtime/runtime_test.go | 83 ++++++++++++++++++++-------------------- thor/fork_config_test.go | 1 + vm/jump_table_test.go | 33 ++++++++++++++++ 3 files changed, 76 insertions(+), 41 deletions(-) create mode 100644 vm/jump_table_test.go diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index 77dc6c8ab..43a691503 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -106,7 +106,6 @@ func TestEVMFunction(t *testing.T) { bal, _ := new(big.Int).SetString("1000000000000000000000000000", 10) assert.Equal(t, M(new(big.Int).Add(bal, big.NewInt(200)), nil), M(ctx.state.GetBalance(origin))) assert.Equal(t, M(new(big.Int).Add(bal, big.NewInt(100)), nil), M(ctx.state.GetEnergy(origin, time))) - }, }, { @@ -229,7 +228,6 @@ func TestEVMFunction(t *testing.T) { assert.Equal(t, thor.MustParseBytes32("ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"), thor.Bytes32(hashes[0])) assert.Equal(t, thor.MustParseBytes32("7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"), thor.Bytes32(hashes[1])) - }, }, { @@ -254,15 +252,18 @@ func TestEVMFunction(t *testing.T) { abi: "", methodName: "", testFunc: func(ctx *context, t *testing.T) { - code, _ := hex.DecodeString("60ef60005360016000f3") + failingCalldata := []string{"60ef60005360016000f3", "60ef60005360026000f3", "60ef60005360036000f3", "60ef60005360206000f3"} + for _, calldata := range failingCalldata { + code, _ := hex.DecodeString(calldata) - exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). - PrepareClause(tx.NewClause(nil).WithData(code), 0, math.MaxUint64, &xenv.TransactionContext{}) - out, _, err := exec() + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(nil).WithData(code), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() - assert.Nil(t, err) - assert.NotNil(t, out.VMErr) - assert.Equal(t, out.VMErr.Error(), "invalid code: must not begin with 0xef") + assert.Nil(t, err) + assert.NotNil(t, out.VMErr) + assert.Equal(t, "invalid code: must not begin with 0xef", out.VMErr.Error()) + } }, }, { @@ -299,7 +300,7 @@ func TestEVMFunction(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, out.VMErr) - assert.Equal(t, out.VMErr.Error(), "invalid opcode 0x5f") + assert.Equal(t, "invalid opcode 0x5f", out.VMErr.Error()) }, }, { @@ -323,54 +324,54 @@ func TestEVMFunction(t *testing.T) { }, }, { - name: "pre ETH_SH basefee", - code: "6080604052348015600e575f80fd5b50600436106026575f3560e01c80635cf2496914602a575b5f80fd5b60306044565b604051603b91906061565b60405180910390f35b5f48905090565b5f819050919050565b605b81604b565b82525050565b5f60208201905060725f8301846054565b9291505056fea2646970667358221220cbae2729fc31c76b30a14b2a0f61fdad920cb3c0ef1f7f5166e48d836d91cc6a64736f6c63430008180033", - abi: `[{"inputs":[],"name":"basefee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]`, - methodName: "basefee", + name: "ETH_SH PUSH0 gas cost", + code: "", + abi: "", + methodName: "", testFunc: func(ctx *context, t *testing.T) { - // pragma solidity >=0.7.0 <0.9.0; - // contract TestBaseFee { - // function basefee() public view returns (uint256) { - // return block.basefee; - // } - // } - methodData, err := ctx.method.EncodeInput() - if err != nil { - t.Fatal(err) - } + // 0x5f is PUSH0 opCode + codeData := []byte{0x5f, 0x00} + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(nil).WithData(codeData), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr) + assert.Equal(t, uint64(2), math.MaxUint64-out.LeftOverGas) + }, + }, + { + name: "pre ETH_SH basefee", + code: "4800", + abi: "", + methodName: "", + testFunc: func(ctx *context, t *testing.T) { + // 0x48 is BASEFEE opCode + codeData := []byte{0x48, 0x00} exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.NoFork). - PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + PrepareClause(tx.NewClause(&target).WithData(codeData), 0, math.MaxUint64, &xenv.TransactionContext{}) out, _, err := exec() assert.Nil(t, err) assert.NotNil(t, out.VMErr) - assert.Equal(t, out.VMErr.Error(), "invalid opcode 0x5f") + assert.Equal(t, "invalid opcode 0x48", out.VMErr.Error()) }, }, { name: "ETH_SH basefee", - code: "6080604052348015600e575f80fd5b50600436106026575f3560e01c80635cf2496914602a575b5f80fd5b60306044565b604051603b91906061565b60405180910390f35b5f48905090565b5f819050919050565b605b81604b565b82525050565b5f60208201905060725f8301846054565b9291505056fea2646970667358221220cbae2729fc31c76b30a14b2a0f61fdad920cb3c0ef1f7f5166e48d836d91cc6a64736f6c63430008180033", - abi: `[{"inputs":[],"name":"basefee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]`, - methodName: "basefee", + code: "4800", + abi: "", + methodName: "", testFunc: func(ctx *context, t *testing.T) { - // pragma solidity >=0.7.0 <0.9.0; - // contract TestBaseFee { - // function basefee() public view returns (uint256) { - // return block.basefee; - // } - // } - methodData, err := ctx.method.EncodeInput() - if err != nil { - t.Fatal(err) - } - + // 0x48 is BASEFEE opCode + codeData := []byte{0x48, 0x00} exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). - PrepareClause(tx.NewClause(&target).WithData(methodData), 0, math.MaxUint64, &xenv.TransactionContext{}) + PrepareClause(tx.NewClause(&target).WithData(codeData), 0, math.MaxUint64, &xenv.TransactionContext{}) out, _, err := exec() assert.Nil(t, err) assert.Nil(t, out.VMErr) assert.True(t, new(big.Int).SetBytes(out.Data).Cmp(big.NewInt(0)) == 0) + assert.Equal(t, uint64(2), math.MaxUint64-out.LeftOverGas) }, }, { diff --git a/thor/fork_config_test.go b/thor/fork_config_test.go index fd4916c28..c05c959f5 100644 --- a/thor/fork_config_test.go +++ b/thor/fork_config_test.go @@ -19,6 +19,7 @@ func TestForkConfigString(t *testing.T) { ETH_IST: math.MaxUint32, VIP214: math.MaxUint32, FINALITY: math.MaxUint32, + ETH_SH: math.MaxUint32, } expectedStr := "VIP191: #1, BLOCKLIST: #2" diff --git a/vm/jump_table_test.go b/vm/jump_table_test.go new file mode 100644 index 000000000..5e1c64415 --- /dev/null +++ b/vm/jump_table_test.go @@ -0,0 +1,33 @@ +// Copyright (c) 2024 The VeChainThor developers + +// Distributed under the GNU Lesser General Public License v3.0 software license, see the accompanying +// file LICENSE or + +package vm + +import ( + "testing" + + "github.com/holiman/uint256" + "github.com/stretchr/testify/assert" +) + +func TestPush0OpCode(t *testing.T) { + // Arrange + mockStack := newstack() + jt := NewShanghaiInstructionSet() + push0 := jt[PUSH0] + + // Check the stack is empty before executing PUSH0 + assert.Equal(t, 0, mockStack.len()) + + // Act + push0.execute(nil, nil, nil, nil, mockStack) + + // Assert + // Check the stack has one zero element after executing PUSH0 + assert.Equal(t, 1, mockStack.len()) + + expectedValueOnStack := new(uint256.Int) + assert.Equal(t, expectedValueOnStack, mockStack.peek()) +} From 023ca4c1c40aa07a919aae73cfff776f8a79c940 Mon Sep 17 00:00:00 2001 From: Paolo Galli Date: Mon, 29 Apr 2024 11:36:51 +0200 Subject: [PATCH 13/20] refactor: remove unnecessary codeData for basefee runtime_test.go --- runtime/runtime_test.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index 43a691503..46d128675 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -346,10 +346,8 @@ func TestEVMFunction(t *testing.T) { abi: "", methodName: "", testFunc: func(ctx *context, t *testing.T) { - // 0x48 is BASEFEE opCode - codeData := []byte{0x48, 0x00} exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.NoFork). - PrepareClause(tx.NewClause(&target).WithData(codeData), 0, math.MaxUint64, &xenv.TransactionContext{}) + PrepareClause(tx.NewClause(&target), 0, math.MaxUint64, &xenv.TransactionContext{}) out, _, err := exec() assert.Nil(t, err) assert.NotNil(t, out.VMErr) @@ -362,10 +360,8 @@ func TestEVMFunction(t *testing.T) { abi: "", methodName: "", testFunc: func(ctx *context, t *testing.T) { - // 0x48 is BASEFEE opCode - codeData := []byte{0x48, 0x00} exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). - PrepareClause(tx.NewClause(&target).WithData(codeData), 0, math.MaxUint64, &xenv.TransactionContext{}) + PrepareClause(tx.NewClause(&target), 0, math.MaxUint64, &xenv.TransactionContext{}) out, _, err := exec() assert.Nil(t, err) assert.Nil(t, out.VMErr) From 5317eb7a97ece4e99e4ef4964155916b05edf7e3 Mon Sep 17 00:00:00 2001 From: Paolo Galli Date: Thu, 25 Jul 2024 14:46:07 +0200 Subject: [PATCH 14/20] fix: add the new ETH_SH fork param in custom genesis test --- genesis/customnet_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genesis/customnet_test.go b/genesis/customnet_test.go index 27d8d0461..c2707f22c 100644 --- a/genesis/customnet_test.go +++ b/genesis/customnet_test.go @@ -136,7 +136,7 @@ func TestNewCustomGenesisMarshalUnmarshal(t *testing.T) { marshalVal, err := json.Marshal(customGenesis) assert.NoError(t, err, "Marshaling should not produce an error") - expectedMarshal := `{"launchTime":1526400000,"gaslimit":0,"extraData":"","accounts":[{"address":"0x0000000000000000000000000000000000000000","balance":"0x0","energy":"0x0","code":"0x608060405234801561001057600080fd5b50606460008190555061017f806100286000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80632f5f3b3c14610046578063a32a3ee414610064578063acfee28314610082575b600080fd5b61004e61009e565b60405161005b91906100d0565b60405180910390f35b61006c6100a4565b60405161007991906100d0565b60405180910390f35b61009c6004803603810190610097919061011c565b6100ad565b005b60005481565b60008054905090565b8060008190555050565b6000819050919050565b6100ca816100b7565b82525050565b60006020820190506100e560008301846100c1565b92915050565b600080fd5b6100f9816100b7565b811461010457600080fd5b50565b600081359050610116816100f0565b92915050565b600060208284031215610132576101316100eb565b5b600061014084828501610107565b9150509291505056fea2646970667358221220a1012465f7be855f040e95566de3bbd50542ba31a7730d7fea2ef9de563a9ac164736f6c63430008110033","storage":{"0x0000000000000000000000000000000000000000000000000000000000000001":"0x0000000000000000000000000000000000000000000000000000000000000002"}},{"address":"0x0000000000000000000000000000000000000000","balance":null,"energy":null,"code":"","storage":null}],"authority":[{"masterAddress":"0xf077b491b355e64048ce21e3a6fc4751eeea77fa","endorsorAddress":"0xf077b491b355e64048ce21e3a6fc4751eeea77fa","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x435933c8064b4ae76be665428e0307ef2ccfbd68","endorsorAddress":"0x435933c8064b4ae76be665428e0307ef2ccfbd68","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x0f872421dc479f3c11edd89512731814d0598db5","endorsorAddress":"0x0f872421dc479f3c11edd89512731814d0598db5","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0xf370940abdbd2583bc80bfc19d19bc216c88ccf0","endorsorAddress":"0xf370940abdbd2583bc80bfc19d19bc216c88ccf0","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x99602e4bbc0503b8ff4432bb1857f916c3653b85","endorsorAddress":"0x99602e4bbc0503b8ff4432bb1857f916c3653b85","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x61e7d0c2b25706be3485980f39a3a994a8207acf","endorsorAddress":"0x61e7d0c2b25706be3485980f39a3a994a8207acf","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x361277d1b27504f36a3b33d3a52d1f8270331b8c","endorsorAddress":"0x361277d1b27504f36a3b33d3a52d1f8270331b8c","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0xd7f75a0a1287ab2916848909c8531a0ea9412800","endorsorAddress":"0xd7f75a0a1287ab2916848909c8531a0ea9412800","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0xabef6032b9176c186f6bf984f548bda53349f70a","endorsorAddress":"0xabef6032b9176c186f6bf984f548bda53349f70a","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x865306084235bf804c8bba8a8d56890940ca8f0b","endorsorAddress":"0x865306084235bf804c8bba8a8d56890940ca8f0b","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"}],"params":{"rewardRatio":"-0x64","baseGasPrice":"0x0","proposerEndorsement":"0x0","executorAddress":null,"maxBlockProposers":10000},"executor":{"approvers":null},"forkConfig":{"VIP191":4294967295,"ETH_CONST":4294967295,"BLOCKLIST":4294967295,"ETH_IST":4294967295,"VIP214":4294967295,"FINALITY":0}}` + expectedMarshal := `{"launchTime":1526400000,"gaslimit":0,"extraData":"","accounts":[{"address":"0x0000000000000000000000000000000000000000","balance":"0x0","energy":"0x0","code":"0x608060405234801561001057600080fd5b50606460008190555061017f806100286000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80632f5f3b3c14610046578063a32a3ee414610064578063acfee28314610082575b600080fd5b61004e61009e565b60405161005b91906100d0565b60405180910390f35b61006c6100a4565b60405161007991906100d0565b60405180910390f35b61009c6004803603810190610097919061011c565b6100ad565b005b60005481565b60008054905090565b8060008190555050565b6000819050919050565b6100ca816100b7565b82525050565b60006020820190506100e560008301846100c1565b92915050565b600080fd5b6100f9816100b7565b811461010457600080fd5b50565b600081359050610116816100f0565b92915050565b600060208284031215610132576101316100eb565b5b600061014084828501610107565b9150509291505056fea2646970667358221220a1012465f7be855f040e95566de3bbd50542ba31a7730d7fea2ef9de563a9ac164736f6c63430008110033","storage":{"0x0000000000000000000000000000000000000000000000000000000000000001":"0x0000000000000000000000000000000000000000000000000000000000000002"}},{"address":"0x0000000000000000000000000000000000000000","balance":null,"energy":null,"code":"","storage":null}],"authority":[{"masterAddress":"0xf077b491b355e64048ce21e3a6fc4751eeea77fa","endorsorAddress":"0xf077b491b355e64048ce21e3a6fc4751eeea77fa","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x435933c8064b4ae76be665428e0307ef2ccfbd68","endorsorAddress":"0x435933c8064b4ae76be665428e0307ef2ccfbd68","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x0f872421dc479f3c11edd89512731814d0598db5","endorsorAddress":"0x0f872421dc479f3c11edd89512731814d0598db5","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0xf370940abdbd2583bc80bfc19d19bc216c88ccf0","endorsorAddress":"0xf370940abdbd2583bc80bfc19d19bc216c88ccf0","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x99602e4bbc0503b8ff4432bb1857f916c3653b85","endorsorAddress":"0x99602e4bbc0503b8ff4432bb1857f916c3653b85","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x61e7d0c2b25706be3485980f39a3a994a8207acf","endorsorAddress":"0x61e7d0c2b25706be3485980f39a3a994a8207acf","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x361277d1b27504f36a3b33d3a52d1f8270331b8c","endorsorAddress":"0x361277d1b27504f36a3b33d3a52d1f8270331b8c","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0xd7f75a0a1287ab2916848909c8531a0ea9412800","endorsorAddress":"0xd7f75a0a1287ab2916848909c8531a0ea9412800","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0xabef6032b9176c186f6bf984f548bda53349f70a","endorsorAddress":"0xabef6032b9176c186f6bf984f548bda53349f70a","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"},{"masterAddress":"0x865306084235bf804c8bba8a8d56890940ca8f0b","endorsorAddress":"0x865306084235bf804c8bba8a8d56890940ca8f0b","identity":"0x00000000000000000000000000000000000000000000000000006d6173746572"}],"params":{"rewardRatio":"-0x64","baseGasPrice":"0x0","proposerEndorsement":"0x0","executorAddress":null,"maxBlockProposers":10000},"executor":{"approvers":null},"forkConfig":{"VIP191":4294967295,"ETH_CONST":4294967295,"BLOCKLIST":4294967295,"ETH_IST":4294967295,"VIP214":4294967295,"FINALITY":0,"ETH_SH":0}}` assert.Equal(t, expectedMarshal, string(marshalVal)) } From 638d44542e8c255390e91977e89bccbfdcf9b135 Mon Sep 17 00:00:00 2001 From: tony Date: Fri, 26 Jul 2024 14:57:32 +0800 Subject: [PATCH 15/20] fix typo --- vm/jump_table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/jump_table.go b/vm/jump_table.go index f31ce377b..886831fb9 100644 --- a/vm/jump_table.go +++ b/vm/jump_table.go @@ -55,7 +55,7 @@ var ( type JumpTable [256]*operation -// NewIstanbulInstructionSet returns the frontier, homestead +// NewShanghaiInstructionSet returns the frontier, homestead // byzantium, constantinople , istanbul and shanghai instructions. func NewShanghaiInstructionSet() *JumpTable { instructionSet := NewIstanbulInstructionSet() From 49b7af52b8692014553d59b701c91877e31d1abc Mon Sep 17 00:00:00 2001 From: tony Date: Wed, 31 Jul 2024 13:05:13 +0800 Subject: [PATCH 16/20] move gas param to vm package --- thor/params.go | 18 +++++++----------- vm/contracts.go | 6 +++--- vm/gas.go | 5 +++++ 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/thor/params.go b/thor/params.go index 5122c5083..d65041e06 100644 --- a/thor/params.go +++ b/thor/params.go @@ -20,17 +20,13 @@ const ( ClauseGas uint64 = params.TxGas - TxGas ClauseGasContractCreation uint64 = params.TxGasContractCreation - TxGas - MinGasLimit uint64 = 1000 * 1000 - InitialGasLimit uint64 = 10 * 1000 * 1000 // InitialGasLimit gas limit value int genesis block. - GasLimitBoundDivisor uint64 = 1024 // from ethereum - GetBalanceGas uint64 = 400 // EIP158 gas table - SloadGas uint64 = 200 // EIP158 gas table - SstoreSetGas uint64 = params.SstoreSetGas - SstoreResetGas uint64 = params.SstoreResetGas - Bn256AddGasEIP1108 uint64 = 150 // Gas needed for an elliptic curve addition - Bn256ScalarMulGasEIP1108 uint64 = 6000 // Gas needed for an elliptic curve scalar multiplication - Bn256PairingBaseGasEIP1108 uint64 = 45000 // Base price for an elliptic curve pairing check - Bn256PairingPerPointGasEIP1108 uint64 = 34000 // Per-point price for an elliptic curve pairing check + MinGasLimit uint64 = 1000 * 1000 + InitialGasLimit uint64 = 10 * 1000 * 1000 // InitialGasLimit gas limit value int genesis block. + GasLimitBoundDivisor uint64 = 1024 // from ethereum + GetBalanceGas uint64 = 400 // EIP158 gas table + SloadGas uint64 = 200 // EIP158 gas table + SstoreSetGas uint64 = params.SstoreSetGas + SstoreResetGas uint64 = params.SstoreResetGas MaxTxWorkDelay uint32 = 30 // (unit: block) if tx delay exceeds this value, no energy can be exchanged. diff --git a/vm/contracts.go b/vm/contracts.go index e235c7197..46c3a6381 100644 --- a/vm/contracts.go +++ b/vm/contracts.go @@ -439,7 +439,7 @@ type bn256Add struct { // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256Add) RequiredGas(input []byte) uint64 { if c.eip1108 { - return thor.Bn256AddGasEIP1108 + return Bn256AddGasEIP1108 } return params.Bn256AddGas } @@ -466,7 +466,7 @@ type bn256ScalarMul struct { // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 { if c.eip1108 { - return thor.Bn256ScalarMulGasEIP1108 + return Bn256ScalarMulGasEIP1108 } return params.Bn256ScalarMulGas } @@ -500,7 +500,7 @@ type bn256Pairing struct { // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256Pairing) RequiredGas(input []byte) uint64 { if c.eip1108 { - return thor.Bn256PairingBaseGasEIP1108 + uint64(len(input)/192)*thor.Bn256PairingPerPointGasEIP1108 + return Bn256PairingBaseGasEIP1108 + uint64(len(input)/192)*Bn256PairingPerPointGasEIP1108 } return params.Bn256PairingBaseGas + uint64(len(input)/192)*params.Bn256PairingPerPointGas } diff --git a/vm/gas.go b/vm/gas.go index 964f5b3da..b420697bd 100644 --- a/vm/gas.go +++ b/vm/gas.go @@ -32,6 +32,11 @@ const ( GasReturn uint64 = 0 GasStop uint64 = 0 GasContractByte uint64 = 200 + + Bn256AddGasEIP1108 uint64 = 150 // Gas needed for an elliptic curve addition + Bn256ScalarMulGasEIP1108 uint64 = 6000 // Gas needed for an elliptic curve scalar multiplication + Bn256PairingBaseGasEIP1108 uint64 = 45000 // Base price for an elliptic curve pairing check + Bn256PairingPerPointGasEIP1108 uint64 = 34000 // Per-point price for an elliptic curve pairing check ) // callGas returns the actual gas cost of the call. From 9c0b05d87261ebf9d0a254f3fb9c48c71b6e0ed6 Mon Sep 17 00:00:00 2001 From: tony Date: Thu, 1 Aug 2024 17:51:54 +0800 Subject: [PATCH 17/20] improve basefee tests --- runtime/runtime_test.go | 122 +++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 52 deletions(-) diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index 46d128675..e92f6e9c9 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -7,6 +7,7 @@ package runtime_test import ( "encoding/hex" + "fmt" "math" "math/big" "testing" @@ -23,6 +24,7 @@ import ( "github.com/vechain/thor/v2/state" "github.com/vechain/thor/v2/thor" "github.com/vechain/thor/v2/tx" + "github.com/vechain/thor/v2/vm" "github.com/vechain/thor/v2/xenv" ) @@ -39,13 +41,15 @@ func TestEVMFunction(t *testing.T) { method *abi.Method } - tests := []struct { + type testcase = struct { name string code string abi string methodName string testFunc func(*context, *testing.T) - }{ + } + + baseTests := []testcase{ { name: "Contract Suicide", code: "608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063085da1b3146044575b600080fd5b348015604f57600080fd5b5060566058565b005b3373ffffffffffffffffffffffffffffffffffffffff16ff00a165627a7a723058204cb70b653a3d1821e00e6ade869638e80fa99719931c9fa045cec2189d94086f0029", @@ -230,6 +234,9 @@ func TestEVMFunction(t *testing.T) { assert.Equal(t, thor.MustParseBytes32("7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"), thor.Bytes32(hashes[1])) }, }, + } + + shanghaiTests := []testcase{ { name: "pre ETH_SH deploy 0xEF started contract code", code: "", @@ -282,47 +289,6 @@ func TestEVMFunction(t *testing.T) { assert.Nil(t, out.VMErr) }, }, - { - name: "pre ETH_SH PUSH0", - code: "", - abi: "", - methodName: "", - testFunc: func(ctx *context, t *testing.T) { - // pragma solidity >=0.7.0 <0.9.0; - // contract Simple { - // constructor() {} - // } - code, _ := hex.DecodeString("6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea2646970667358221220268d147b82c3959e7339f440b5861d98384629b096f1eac3e2ce7c55ebdc2daf64736f6c63430008180033") - - exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.NoFork). - PrepareClause(tx.NewClause(nil).WithData(code), 0, math.MaxUint64, &xenv.TransactionContext{}) - out, _, err := exec() - - assert.Nil(t, err) - assert.NotNil(t, out.VMErr) - assert.Equal(t, "invalid opcode 0x5f", out.VMErr.Error()) - }, - }, - { - name: "ETH_SH PUSH0", - code: "", - abi: "", - methodName: "", - testFunc: func(ctx *context, t *testing.T) { - // pragma solidity >=0.7.0 <0.9.0; - // contract Simple { - // constructor() {} - // } - code, _ := hex.DecodeString("6080604052348015600e575f80fd5b50603e80601a5f395ff3fe60806040525f80fdfea2646970667358221220268d147b82c3959e7339f440b5861d98384629b096f1eac3e2ce7c55ebdc2daf64736f6c63430008180033") - - exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). - PrepareClause(tx.NewClause(nil).WithData(code), 0, math.MaxUint64, &xenv.TransactionContext{}) - out, _, err := exec() - - assert.Nil(t, err) - assert.Nil(t, out.VMErr) - }, - }, { name: "ETH_SH PUSH0 gas cost", code: "", @@ -330,7 +296,7 @@ func TestEVMFunction(t *testing.T) { methodName: "", testFunc: func(ctx *context, t *testing.T) { // 0x5f is PUSH0 opCode - codeData := []byte{0x5f, 0x00} + codeData := []byte{0x5f} exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). PrepareClause(tx.NewClause(nil).WithData(codeData), 0, math.MaxUint64, &xenv.TransactionContext{}) out, _, err := exec() @@ -341,22 +307,24 @@ func TestEVMFunction(t *testing.T) { }, }, { - name: "pre ETH_SH basefee", - code: "4800", + name: "ETH_SH BASEFEE output gas cost", + code: hex.EncodeToString([]byte{byte(vm.BASEFEE)}), abi: "", methodName: "", testFunc: func(ctx *context, t *testing.T) { - exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.NoFork). + exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). PrepareClause(tx.NewClause(&target), 0, math.MaxUint64, &xenv.TransactionContext{}) out, _, err := exec() assert.Nil(t, err) - assert.NotNil(t, out.VMErr) - assert.Equal(t, "invalid opcode 0x48", out.VMErr.Error()) + assert.Nil(t, out.VMErr) + + assert.True(t, new(big.Int).SetBytes(out.Data).Cmp(big.NewInt(0)) == 0) + assert.Equal(t, uint64(2), math.MaxUint64-out.LeftOverGas) }, }, { - name: "ETH_SH basefee", - code: "4800", + name: "ETH_SH BASEFEE", + code: hex.EncodeToString([]byte{byte(vm.BASEFEE), byte(vm.PUSH1), 0x80, byte(vm.MSTORE), byte(vm.PUSH1), 0x20, byte(vm.PUSH1), 0x80, byte(vm.RETURN)}), abi: "", methodName: "", testFunc: func(ctx *context, t *testing.T) { @@ -367,7 +335,6 @@ func TestEVMFunction(t *testing.T) { assert.Nil(t, out.VMErr) assert.True(t, new(big.Int).SetBytes(out.Data).Cmp(big.NewInt(0)) == 0) - assert.Equal(t, uint64(2), math.MaxUint64-out.LeftOverGas) }, }, { @@ -554,6 +521,11 @@ func TestEVMFunction(t *testing.T) { }, } + var tests = []testcase{} + + tests = append(tests, baseTests...) + tests = append(tests, shanghaiTests...) + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { db := muxdb.NewMem() @@ -588,6 +560,52 @@ func TestEVMFunction(t *testing.T) { } } +func TestPreForkOpCode(t *testing.T) { + db := muxdb.NewMem() + g := genesis.NewDevnet() + stater := state.NewStater(db) + b0, _, _, _ := g.Build(stater) + repo, _ := chain.NewRepository(db, b0) + + chain := repo.NewChain(b0.Header().ID()) + state := stater.NewState(b0.Header().StateRoot(), 0, 0, 0) + + tests := []struct { + name string + code []byte + op vm.OpCode + }{ + { + name: "BASEFEE", + code: []byte{byte(vm.BASEFEE)}, + op: vm.BASEFEE, + }, + { + name: "PUSH0", + code: []byte{byte(vm.PUSH0)}, + op: vm.PUSH0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + exec, _ := runtime.New(chain, state, &xenv.BlockContext{}, thor.NoFork). + PrepareClause(tx.NewClause(nil).WithData(tt.code), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err := exec() + assert.Nil(t, err) + assert.NotNil(t, out.VMErr) + assert.Equal(t, fmt.Sprintf("invalid opcode 0x%x", int(tt.op)), out.VMErr.Error()) + + // this one applies a fork config that forks from the start + exec, _ = runtime.New(chain, state, &xenv.BlockContext{}, thor.ForkConfig{}). + PrepareClause(tx.NewClause(nil).WithData(tt.code), 0, math.MaxUint64, &xenv.TransactionContext{}) + out, _, err = exec() + assert.Nil(t, err) + assert.Nil(t, out.VMErr, "after fork should not return error") + }) + } +} + func TestCall(t *testing.T) { db := muxdb.NewMem() From 4a56e8265fef58645e8cc26c53e87ec2586851b2 Mon Sep 17 00:00:00 2001 From: tony Date: Mon, 12 Aug 2024 16:46:45 +0800 Subject: [PATCH 18/20] fix vm tests --- vm/evm_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/evm_test.go b/vm/evm_test.go index 55b958ce6..554664af9 100644 --- a/vm/evm_test.go +++ b/vm/evm_test.go @@ -176,7 +176,7 @@ func TestMaxCodeSize(t *testing.T) { { name: "Code size greater than max code size", input: bytecodeLimitPlusOne, - expectedErr: errMaxCodeSizeExceeded, + expectedErr: ErrMaxCodeSizeExceeded, }, } From 455d12630ec94f773f03ca5e2caf66b1d1ec930e Mon Sep 17 00:00:00 2001 From: tony Date: Wed, 14 Aug 2024 11:34:46 +0800 Subject: [PATCH 19/20] make byzantium as default precompile contracts --- runtime/runtime_test.go | 2 +- vm/contracts.go | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index e92f6e9c9..e05b258c8 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -296,7 +296,7 @@ func TestEVMFunction(t *testing.T) { methodName: "", testFunc: func(ctx *context, t *testing.T) { // 0x5f is PUSH0 opCode - codeData := []byte{0x5f} + codeData := []byte{byte(vm.PUSH0)} exec, _ := runtime.New(ctx.chain, ctx.state, &xenv.BlockContext{}, thor.ForkConfig{}). PrepareClause(tx.NewClause(nil).WithData(codeData), 0, math.MaxUint64, &xenv.TransactionContext{}) out, _, err := exec() diff --git a/vm/contracts.go b/vm/contracts.go index 46c3a6381..8b1a98c73 100644 --- a/vm/contracts.go +++ b/vm/contracts.go @@ -122,10 +122,8 @@ func ActivePrecompiles(rules Rules) []common.Address { return PrecompiledAddressesShanghai case rules.IsIstanbul: return PrecompiledAddressesIstanbul - case rules.IsByzantium: - return PrecompiledAddressesByzantium default: - return PrecompiledAddressesHomestead + return PrecompiledAddressesByzantium } } From 334f0d816a0f30cd42e5f30b289866e4e0e978d3 Mon Sep 17 00:00:00 2001 From: tony Date: Wed, 14 Aug 2024 17:33:30 +0800 Subject: [PATCH 20/20] update customnet test regarding pr comments --- genesis/customnet_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/genesis/customnet_test.go b/genesis/customnet_test.go index c2707f22c..fa69ae989 100644 --- a/genesis/customnet_test.go +++ b/genesis/customnet_test.go @@ -24,6 +24,7 @@ func CustomNetWithParams(t *testing.T, executor genesis.Executor, baseGasPrice g ETH_IST: math.MaxUint32, VIP214: math.MaxUint32, FINALITY: 0, + ETH_SH: 0, } devAccounts := genesis.DevAccounts()