diff --git a/core/state/statedb.go b/core/state/statedb.go index 905944cbb5..8639f180ab 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -684,7 +685,7 @@ func (s *StateDB) CreateAccount(addr common.Address) { // Copy creates a deep, independent copy of the state. // Snapshots of the copied state cannot be applied to the copy. -func (s *StateDB) Copy() *StateDB { +func (s *StateDB) Copy() vm.StateDB { // Copy all the basic fields, initialize the memory ones state := &StateDB{ db: s.db, diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index df1cd5547d..79548d8114 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -181,16 +181,16 @@ func TestCopy(t *testing.T) { // modify all in memory for i := byte(0); i < 255; i++ { origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) - copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) - ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) + copyObj := copy.(*StateDB).GetOrNewStateObject(common.BytesToAddress([]byte{i})) + ccopyObj := ccopy.(*StateDB).GetOrNewStateObject(common.BytesToAddress([]byte{i})) origObj.AddBalance(big.NewInt(2 * int64(i))) copyObj.AddBalance(big.NewInt(3 * int64(i))) ccopyObj.AddBalance(big.NewInt(4 * int64(i))) orig.updateStateObject(origObj) - copy.updateStateObject(copyObj) - ccopy.updateStateObject(copyObj) + copy.(*StateDB).updateStateObject(copyObj) + ccopy.(*StateDB).updateStateObject(copyObj) } // Finalise the changes on all concurrently @@ -202,15 +202,15 @@ func TestCopy(t *testing.T) { var wg sync.WaitGroup wg.Add(3) go finalise(&wg, orig) - go finalise(&wg, copy) - go finalise(&wg, ccopy) + go finalise(&wg, copy.(*StateDB)) + go finalise(&wg, ccopy.(*StateDB)) wg.Wait() // Verify that the three states have been updated independently for i := byte(0); i < 255; i++ { origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) - copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) - ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i})) + copyObj := copy.(*StateDB).GetOrNewStateObject(common.BytesToAddress([]byte{i})) + ccopyObj := ccopy.(*StateDB).GetOrNewStateObject(common.BytesToAddress([]byte{i})) if want := big.NewInt(3 * int64(i)); origObj.Balance().Cmp(want) != 0 { t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want) @@ -1016,7 +1016,7 @@ func TestStateDBAccessList(t *testing.T) { } // Check the copy // Make a copy - state = stateCopy1 + state = stateCopy1.(*StateDB) verifyAddrs("aa", "bb") verifySlots("bb", "01", "02") if got, exp := len(state.accessList.addresses), 2; got != exp { diff --git a/core/vm/analysis.go b/core/vm/analysis.go index 38af9084ac..1146347556 100644 --- a/core/vm/analysis.go +++ b/core/vm/analysis.go @@ -25,16 +25,16 @@ const ( set7BitsMask = uint16(0b111_1111) ) -// bitvec is a bit vector which maps bytes in a program. +// Bitvec is a bit vector which maps bytes in a program. // An unset bit means the byte is an opcode, a set bit means // it's data (i.e. argument of PUSHxx). -type bitvec []byte +type Bitvec []byte -func (bits bitvec) set1(pos uint64) { +func (bits Bitvec) set1(pos uint64) { bits[pos/8] |= 1 << (pos % 8) } -func (bits bitvec) setN(flag uint16, pos uint64) { +func (bits Bitvec) setN(flag uint16, pos uint64) { a := flag << (pos % 8) bits[pos/8] |= byte(a) if b := byte(a >> 8); b != 0 { @@ -42,13 +42,13 @@ func (bits bitvec) setN(flag uint16, pos uint64) { } } -func (bits bitvec) set8(pos uint64) { +func (bits Bitvec) set8(pos uint64) { a := byte(0xFF << (pos % 8)) bits[pos/8] |= a bits[pos/8+1] = ^a } -func (bits bitvec) set16(pos uint64) { +func (bits Bitvec) set16(pos uint64) { a := byte(0xFF << (pos % 8)) bits[pos/8] |= a bits[pos/8+1] = 0xFF @@ -56,23 +56,23 @@ func (bits bitvec) set16(pos uint64) { } // codeSegment checks if the position is in a code segment. -func (bits *bitvec) codeSegment(pos uint64) bool { +func (bits *Bitvec) codeSegment(pos uint64) bool { return (((*bits)[pos/8] >> (pos % 8)) & 1) == 0 } -// codeBitmap collects data locations in code. -func codeBitmap(code []byte) bitvec { +// CodeBitmap collects data locations in code. +func CodeBitmap(code []byte) Bitvec { // The bitmap is 4 bytes longer than necessary, in case the code // ends with a PUSH32, the algorithm will set bits on the - // bitvector outside the bounds of the actual code. - bits := make(bitvec, len(code)/8+1+4) - return codeBitmapInternal(code, bits) + // Bitvector outside the bounds of the actual code. + bits := make(Bitvec, len(code)/8+1+4) + return CodeBitmapInternal(code, bits) } -// codeBitmapInternal is the internal implementation of codeBitmap. +// CodeBitmapInternal is the internal implementation of CodeBitmap. // It exists for the purpose of being able to run benchmark tests // without dynamic allocations affecting the results. -func codeBitmapInternal(code, bits bitvec) bitvec { +func CodeBitmapInternal(code, bits Bitvec) Bitvec { for pc := uint64(0); pc < uint64(len(code)); { op := OpCode(code[pc]) pc++ diff --git a/core/vm/analysis_test.go b/core/vm/analysis_test.go index 398861f8ae..dbf09a4ab7 100644 --- a/core/vm/analysis_test.go +++ b/core/vm/analysis_test.go @@ -14,12 +14,13 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package vm +package vm_test import ( "math/bits" "testing" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" ) @@ -29,30 +30,30 @@ func TestJumpDestAnalysis(t *testing.T) { exp byte which int }{ - {[]byte{byte(PUSH1), 0x01, 0x01, 0x01}, 0b0000_0010, 0}, - {[]byte{byte(PUSH1), byte(PUSH1), byte(PUSH1), byte(PUSH1)}, 0b0000_1010, 0}, - {[]byte{0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1)}, 0b0101_0100, 0}, - {[]byte{byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), 0x01, 0x01, 0x01}, bits.Reverse8(0x7F), 0}, - {[]byte{byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 1}, - {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(PUSH2), byte(PUSH2), byte(PUSH2), 0x01, 0x01, 0x01}, 0b1100_0000, 0}, - {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(PUSH2), 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1}, - {[]byte{byte(PUSH3), 0x01, 0x01, 0x01, byte(PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0010_1110, 0}, - {[]byte{byte(PUSH3), 0x01, 0x01, 0x01, byte(PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1}, - {[]byte{0x01, byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1100, 0}, - {[]byte{0x01, byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0011, 1}, - {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1110, 0}, - {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1111, 1}, - {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 2}, - {[]byte{byte(PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(PUSH1), 0x01}, 0b1111_1110, 0}, - {[]byte{byte(PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(PUSH1), 0x01}, 0b0000_0101, 1}, - {[]byte{byte(PUSH32)}, 0b1111_1110, 0}, - {[]byte{byte(PUSH32)}, 0b1111_1111, 1}, - {[]byte{byte(PUSH32)}, 0b1111_1111, 2}, - {[]byte{byte(PUSH32)}, 0b1111_1111, 3}, - {[]byte{byte(PUSH32)}, 0b0000_0001, 4}, + {[]byte{byte(vm.PUSH1), 0x01, 0x01, 0x01}, 0b0000_0010, 0}, + {[]byte{byte(vm.PUSH1), byte(vm.PUSH1), byte(vm.PUSH1), byte(vm.PUSH1)}, 0b0000_1010, 0}, + {[]byte{0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1)}, 0b0101_0100, 0}, + {[]byte{byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), 0x01, 0x01, 0x01}, bits.Reverse8(0x7F), 0}, + {[]byte{byte(vm.PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 1}, + {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(vm.PUSH2), byte(vm.PUSH2), byte(vm.PUSH2), 0x01, 0x01, 0x01}, 0b1100_0000, 0}, + {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(vm.PUSH2), 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1}, + {[]byte{byte(vm.PUSH3), 0x01, 0x01, 0x01, byte(vm.PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0010_1110, 0}, + {[]byte{byte(vm.PUSH3), 0x01, 0x01, 0x01, byte(vm.PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1}, + {[]byte{0x01, byte(vm.PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1100, 0}, + {[]byte{0x01, byte(vm.PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0011, 1}, + {[]byte{byte(vm.PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1110, 0}, + {[]byte{byte(vm.PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1111, 1}, + {[]byte{byte(vm.PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 2}, + {[]byte{byte(vm.PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(vm.PUSH1), 0x01}, 0b1111_1110, 0}, + {[]byte{byte(vm.PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(vm.PUSH1), 0x01}, 0b0000_0101, 1}, + {[]byte{byte(vm.PUSH32)}, 0b1111_1110, 0}, + {[]byte{byte(vm.PUSH32)}, 0b1111_1111, 1}, + {[]byte{byte(vm.PUSH32)}, 0b1111_1111, 2}, + {[]byte{byte(vm.PUSH32)}, 0b1111_1111, 3}, + {[]byte{byte(vm.PUSH32)}, 0b0000_0001, 4}, } for i, test := range tests { - ret := codeBitmap(test.code) + ret := vm.CodeBitmap(test.code) if ret[test.which] != test.exp { t.Fatalf("test %d: expected %x, got %02x", i, test.exp, ret[test.which]) } @@ -67,7 +68,7 @@ func BenchmarkJumpdestAnalysis_1200k(bench *testing.B) { bench.SetBytes(analysisCodeSize) bench.ResetTimer() for i := 0; i < bench.N; i++ { - codeBitmap(code) + vm.CodeBitmap(code) } bench.StopTimer() } @@ -83,27 +84,27 @@ func BenchmarkJumpdestHashing_1200k(bench *testing.B) { } func BenchmarkJumpdestOpAnalysis(bench *testing.B) { - var op OpCode + var op vm.OpCode bencher := func(b *testing.B) { code := make([]byte, analysisCodeSize) b.SetBytes(analysisCodeSize) for i := range code { code[i] = byte(op) } - bits := make(bitvec, len(code)/8+1+4) + bits := make(vm.Bitvec, len(code)/8+1+4) b.ResetTimer() for i := 0; i < b.N; i++ { for j := range bits { bits[j] = 0 } - codeBitmapInternal(code, bits) + vm.CodeBitmapInternal(code, bits) } } - for op = PUSH1; op <= PUSH32; op++ { + for op = vm.PUSH1; op <= vm.PUSH32; op++ { bench.Run(op.String(), bencher) } - op = JUMPDEST + op = vm.JUMPDEST bench.Run(op.String(), bencher) - op = STOP + op = vm.STOP bench.Run(op.String(), bencher) } diff --git a/core/vm/common.go b/core/vm/common.go index 90ba4a4ad1..e17d75b3e2 100644 --- a/core/vm/common.go +++ b/core/vm/common.go @@ -63,8 +63,8 @@ func getData(data []byte, start uint64, size uint64) []byte { return common.RightPadBytes(data[start:end], int(size)) } -// toWordSize returns the ceiled word size required for memory expansion. -func toWordSize(size uint64) uint64 { +// ToWordSize returns the ceiled word size required for memory expansion. +func ToWordSize(size uint64) uint64 { if size > math.MaxUint64-31 { return math.MaxUint64/32 + 1 } diff --git a/core/vm/contract.go b/core/vm/contract.go index e4b03bd74f..20ee146eb0 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -50,8 +50,8 @@ type Contract struct { caller ContractRef self ContractRef - jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis. - analysis bitvec // Locally cached result of JUMPDEST analysis + jumpdests map[common.Hash]Bitvec // Aggregated result of JUMPDEST analysis. + analysis Bitvec // Locally cached result of JUMPDEST analysis Code []byte CodeHash common.Hash @@ -70,7 +70,7 @@ func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uin // Reuse JUMPDEST analysis from parent context if available. c.jumpdests = parent.jumpdests } else { - c.jumpdests = make(map[common.Hash]bitvec) + c.jumpdests = make(map[common.Hash]Bitvec) } // Gas should be a pointer so it can safely be reduced through the run @@ -112,7 +112,7 @@ func (c *Contract) isCode(udest uint64) bool { if !exist { // Do the analysis and save in parent context // We do not need to store it in c.analysis - analysis = codeBitmap(c.Code) + analysis = CodeBitmap(c.Code) c.jumpdests[c.CodeHash] = analysis } // Also stash it in current contract for faster access @@ -124,7 +124,7 @@ func (c *Contract) isCode(udest uint64) bool { // we don't have to recalculate it for every JUMP instruction in the execution // However, we don't save it within the parent context if c.analysis == nil { - c.analysis = codeBitmap(c.Code) + c.analysis = CodeBitmap(c.Code) } return c.analysis.codeSegment(udest) } diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 1960d1f057..517cf35cfd 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -26,8 +26,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" + bls12381 "github.com/ethereum/go-ethereum/crypto/Bls12381" "github.com/ethereum/go-ethereum/crypto/blake2b" - "github.com/ethereum/go-ethereum/crypto/bls12381" "github.com/ethereum/go-ethereum/crypto/bn256" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/params" @@ -45,20 +45,20 @@ type PrecompiledContract interface { // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum // contracts used in the Frontier and Homestead releases. var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{ - common.BytesToAddress([]byte{1}): &ecrecover{}, - common.BytesToAddress([]byte{2}): &sha256hash{}, - common.BytesToAddress([]byte{3}): &ripemd160hash{}, - common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{1}): &Ecrecover{}, + common.BytesToAddress([]byte{2}): &Sha256hash{}, + common.BytesToAddress([]byte{3}): &Ripemd160hash{}, + common.BytesToAddress([]byte{4}): &DataCopy{}, } // PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum // contracts used in the Byzantium release. var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ - common.BytesToAddress([]byte{1}): &ecrecover{}, - common.BytesToAddress([]byte{2}): &sha256hash{}, - common.BytesToAddress([]byte{3}): &ripemd160hash{}, - common.BytesToAddress([]byte{4}): &dataCopy{}, - common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, + common.BytesToAddress([]byte{1}): &Ecrecover{}, + common.BytesToAddress([]byte{2}): &Sha256hash{}, + common.BytesToAddress([]byte{3}): &Ripemd160hash{}, + common.BytesToAddress([]byte{4}): &DataCopy{}, + common.BytesToAddress([]byte{5}): &BigModExp{Eip2565: false}, common.BytesToAddress([]byte{6}): &bn256AddByzantium{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{}, common.BytesToAddress([]byte{8}): &bn256PairingByzantium{}, @@ -67,58 +67,58 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ // PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum // contracts used in the Istanbul release. var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ - common.BytesToAddress([]byte{1}): &ecrecover{}, - common.BytesToAddress([]byte{2}): &sha256hash{}, - common.BytesToAddress([]byte{3}): &ripemd160hash{}, - common.BytesToAddress([]byte{4}): &dataCopy{}, - common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, - common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, - common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - common.BytesToAddress([]byte{9}): &blake2F{}, + common.BytesToAddress([]byte{1}): &Ecrecover{}, + common.BytesToAddress([]byte{2}): &Sha256hash{}, + common.BytesToAddress([]byte{3}): &Ripemd160hash{}, + common.BytesToAddress([]byte{4}): &DataCopy{}, + common.BytesToAddress([]byte{5}): &BigModExp{Eip2565: false}, + common.BytesToAddress([]byte{6}): &Bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &Bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &Bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &Blake2F{}, } // PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum // contracts used in the Berlin release. var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{ - common.BytesToAddress([]byte{1}): &ecrecover{}, - common.BytesToAddress([]byte{2}): &sha256hash{}, - common.BytesToAddress([]byte{3}): &ripemd160hash{}, - common.BytesToAddress([]byte{4}): &dataCopy{}, - common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, - common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, - common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - common.BytesToAddress([]byte{9}): &blake2F{}, + common.BytesToAddress([]byte{1}): &Ecrecover{}, + common.BytesToAddress([]byte{2}): &Sha256hash{}, + common.BytesToAddress([]byte{3}): &Ripemd160hash{}, + common.BytesToAddress([]byte{4}): &DataCopy{}, + common.BytesToAddress([]byte{5}): &BigModExp{Eip2565: true}, + common.BytesToAddress([]byte{6}): &Bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &Bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &Bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &Blake2F{}, } // PrecompiledContractsCancun contains the default set of pre-compiled Ethereum // contracts used in the Cancun release. var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{ - common.BytesToAddress([]byte{1}): &ecrecover{}, - common.BytesToAddress([]byte{2}): &sha256hash{}, - common.BytesToAddress([]byte{3}): &ripemd160hash{}, - common.BytesToAddress([]byte{4}): &dataCopy{}, - common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, - common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, - common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - common.BytesToAddress([]byte{9}): &blake2F{}, - common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{}, + common.BytesToAddress([]byte{1}): &Ecrecover{}, + common.BytesToAddress([]byte{2}): &Sha256hash{}, + common.BytesToAddress([]byte{3}): &Ripemd160hash{}, + common.BytesToAddress([]byte{4}): &DataCopy{}, + common.BytesToAddress([]byte{5}): &BigModExp{Eip2565: true}, + common.BytesToAddress([]byte{6}): &Bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &Bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &Bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &Blake2F{}, + common.BytesToAddress([]byte{0x0a}): &KzgPointEvaluation{}, } // PrecompiledContractsBLS contains the set of pre-compiled Ethereum // contracts specified in EIP-2537. These are exported for testing purposes. var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ - common.BytesToAddress([]byte{10}): &bls12381G1Add{}, - common.BytesToAddress([]byte{11}): &bls12381G1Mul{}, - common.BytesToAddress([]byte{12}): &bls12381G1MultiExp{}, - common.BytesToAddress([]byte{13}): &bls12381G2Add{}, - common.BytesToAddress([]byte{14}): &bls12381G2Mul{}, - common.BytesToAddress([]byte{15}): &bls12381G2MultiExp{}, - common.BytesToAddress([]byte{16}): &bls12381Pairing{}, - common.BytesToAddress([]byte{17}): &bls12381MapG1{}, - common.BytesToAddress([]byte{18}): &bls12381MapG2{}, + common.BytesToAddress([]byte{10}): &Bls12381G1Add{}, + common.BytesToAddress([]byte{11}): &Bls12381G1Mul{}, + common.BytesToAddress([]byte{12}): &Bls12381G1MultiExp{}, + common.BytesToAddress([]byte{13}): &Bls12381G2Add{}, + common.BytesToAddress([]byte{14}): &Bls12381G2Mul{}, + common.BytesToAddress([]byte{15}): &Bls12381G2MultiExp{}, + common.BytesToAddress([]byte{16}): &Bls12381Pairing{}, + common.BytesToAddress([]byte{17}): &Bls12381MapG1{}, + common.BytesToAddress([]byte{18}): &Bls12381MapG2{}, } var ( @@ -179,18 +179,18 @@ func RunPrecompiledContract(p PrecompiledContract, evm *EVM, input []byte, suppl } // ECRECOVER implemented as a native contract. -type ecrecover struct{} +type Ecrecover struct{} -func (c *ecrecover) RequiredGas(input []byte) uint64 { +func (c *Ecrecover) RequiredGas(input []byte) uint64 { return params.EcrecoverGas } -func (c *ecrecover) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Ecrecover) Run(_ *EVM, input []byte) ([]byte, error) { const ecRecoverInputLength = 128 input = common.RightPadBytes(input, ecRecoverInputLength) // "input" is (hash, v, r, s), each 32 bytes - // but for ecrecover we want (r, s, v) + // but for Ecrecover we want (r, s, v) r := new(big.Int).SetBytes(input[64:96]) s := new(big.Int).SetBytes(input[96:128]) @@ -217,53 +217,53 @@ func (c *ecrecover) Run(_ *EVM, input []byte) ([]byte, error) { } // SHA256 implemented as a native contract. -type sha256hash struct{} +type Sha256hash struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. // // This method does not require any overflow checking as the input size gas costs // required for anything significant is so high it's impossible to pay for. -func (c *sha256hash) RequiredGas(input []byte) uint64 { +func (c *Sha256hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas } -func (c *sha256hash) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Sha256hash) Run(_ *EVM, input []byte) ([]byte, error) { h := sha256.Sum256(input) return h[:], nil } // RIPEMD160 implemented as a native contract. -type ripemd160hash struct{} +type Ripemd160hash struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. // // This method does not require any overflow checking as the input size gas costs // required for anything significant is so high it's impossible to pay for. -func (c *ripemd160hash) RequiredGas(input []byte) uint64 { +func (c *Ripemd160hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas } -func (c *ripemd160hash) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Ripemd160hash) Run(_ *EVM, input []byte) ([]byte, error) { ripemd := ripemd160.New() ripemd.Write(input) return common.LeftPadBytes(ripemd.Sum(nil), 32), nil } // data copy implemented as a native contract. -type dataCopy struct{} +type DataCopy struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. // // This method does not require any overflow checking as the input size gas costs // required for anything significant is so high it's impossible to pay for. -func (c *dataCopy) RequiredGas(input []byte) uint64 { +func (c *DataCopy) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas } -func (c *dataCopy) Run(_ *EVM, in []byte) ([]byte, error) { +func (c *DataCopy) Run(_ *EVM, in []byte) ([]byte, error) { return common.CopyBytes(in), nil } -// bigModExp implements a native big integer exponential modular operation. -type bigModExp struct { - eip2565 bool +// BigModExp implements a native big integer exponential modular operation. +type BigModExp struct { + Eip2565 bool } var ( @@ -313,7 +313,7 @@ func modexpMultComplexity(x *big.Int) *big.Int { } // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bigModExp) RequiredGas(input []byte) uint64 { +func (c *BigModExp) RequiredGas(input []byte) uint64 { var ( baseLen = new(big.Int).SetBytes(getData(input, 0, 32)) expLen = new(big.Int).SetBytes(getData(input, 32, 32)) @@ -348,7 +348,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { adjExpLen.Add(adjExpLen, big.NewInt(int64(msb))) // Calculate the gas cost of the operation gas := new(big.Int).Set(math.BigMax(modLen, baseLen)) - if c.eip2565 { + if c.Eip2565 { // EIP-2565 has three changes // 1. Different multComplexity (inlined here) // in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565): @@ -383,7 +383,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { return gas.Uint64() } -func (c *bigModExp) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *BigModExp) Run(_ *EVM, input []byte) ([]byte, error) { var ( baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() @@ -456,14 +456,14 @@ func runBn256Add(input []byte) ([]byte, error) { // bn256Add implements a native elliptic curve point addition conforming to // Istanbul consensus rules. -type bn256AddIstanbul struct{} +type Bn256AddIstanbul struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { +func (c *Bn256AddIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256AddGasIstanbul } -func (c *bn256AddIstanbul) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bn256AddIstanbul) Run(_ *EVM, input []byte) ([]byte, error) { return runBn256Add(input) } @@ -492,16 +492,16 @@ func runBn256ScalarMul(input []byte) ([]byte, error) { return res.Marshal(), nil } -// bn256ScalarMulIstanbul implements a native elliptic curve scalar +// Bn256ScalarMulIstanbul implements a native elliptic curve scalar // multiplication conforming to Istanbul consensus rules. -type bn256ScalarMulIstanbul struct{} +type Bn256ScalarMulIstanbul struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { +func (c *Bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasIstanbul } -func (c *bn256ScalarMulIstanbul) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bn256ScalarMulIstanbul) Run(_ *EVM, input []byte) ([]byte, error) { return runBn256ScalarMul(input) } @@ -560,16 +560,16 @@ func runBn256Pairing(input []byte) ([]byte, error) { return false32Byte, nil } -// bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve +// Bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve // conforming to Istanbul consensus rules. -type bn256PairingIstanbul struct{} +type Bn256PairingIstanbul struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { +func (c *Bn256PairingIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul } -func (c *bn256PairingIstanbul) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bn256PairingIstanbul) Run(_ *EVM, input []byte) ([]byte, error) { return runBn256Pairing(input) } @@ -586,40 +586,40 @@ func (c *bn256PairingByzantium) Run(_ *EVM, input []byte) ([]byte, error) { return runBn256Pairing(input) } -type blake2F struct{} +type Blake2F struct{} -func (c *blake2F) RequiredGas(input []byte) uint64 { +func (c *Blake2F) RequiredGas(input []byte) uint64 { // If the input is malformed, we can't calculate the gas, return 0 and let the // actual call choke and fault. - if len(input) != blake2FInputLength { + if len(input) != Blake2FInputLength { return 0 } return uint64(binary.BigEndian.Uint32(input[0:4])) } const ( - blake2FInputLength = 213 - blake2FFinalBlockBytes = byte(1) - blake2FNonFinalBlockBytes = byte(0) + Blake2FInputLength = 213 + Blake2FFinalBlockBytes = byte(1) + Blake2FNonFinalBlockBytes = byte(0) ) var ( - errBlake2FInvalidInputLength = errors.New("invalid input length") - errBlake2FInvalidFinalFlag = errors.New("invalid final flag") + ErrBlake2FInvalidInputLength = errors.New("invalid input length") + ErrBlake2FInvalidFinalFlag = errors.New("invalid final flag") ) -func (c *blake2F) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Blake2F) Run(_ *EVM, input []byte) ([]byte, error) { // Make sure the input is valid (correct length and final flag) - if len(input) != blake2FInputLength { - return nil, errBlake2FInvalidInputLength + if len(input) != Blake2FInputLength { + return nil, ErrBlake2FInvalidInputLength } - if input[212] != blake2FNonFinalBlockBytes && input[212] != blake2FFinalBlockBytes { - return nil, errBlake2FInvalidFinalFlag + if input[212] != Blake2FNonFinalBlockBytes && input[212] != Blake2FFinalBlockBytes { + return nil, ErrBlake2FInvalidFinalFlag } // Parse the input into the Blake2b call parameters var ( rounds = binary.BigEndian.Uint32(input[0:4]) - final = input[212] == blake2FFinalBlockBytes + final = input[212] == Blake2FFinalBlockBytes h [8]uint64 m [16]uint64 @@ -649,20 +649,20 @@ func (c *blake2F) Run(_ *EVM, input []byte) ([]byte, error) { var ( errBLS12381InvalidInputLength = errors.New("invalid input length") - errBLS12381InvalidFieldElementTopBytes = errors.New("invalid field element top bytes") + errBLS12381InvalidFieldElementTOpBytes = errors.New("invalid field element top bytes") errBLS12381G1PointSubgroup = errors.New("g1 point is not on correct subgroup") errBLS12381G2PointSubgroup = errors.New("g2 point is not on correct subgroup") ) -// bls12381G1Add implements EIP-2537 G1Add precompile. -type bls12381G1Add struct{} +// Bls12381G1Add implements EIP-2537 G1Add precompile. +type Bls12381G1Add struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bls12381G1Add) RequiredGas(input []byte) uint64 { +func (c *Bls12381G1Add) RequiredGas(input []byte) uint64 { return params.Bls12381G1AddGas } -func (c *bls12381G1Add) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bls12381G1Add) Run(_ *EVM, input []byte) ([]byte, error) { // Implements EIP-2537 G1Add precompile. // > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). // > Output is an encoding of addition operation result - single G1 point (`128` bytes). @@ -692,15 +692,15 @@ func (c *bls12381G1Add) Run(_ *EVM, input []byte) ([]byte, error) { return g.EncodePoint(r), nil } -// bls12381G1Mul implements EIP-2537 G1Mul precompile. -type bls12381G1Mul struct{} +// Bls12381G1Mul implements EIP-2537 G1Mul precompile. +type Bls12381G1Mul struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 { +func (c *Bls12381G1Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G1MulGas } -func (c *bls12381G1Mul) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bls12381G1Mul) Run(_ *EVM, input []byte) ([]byte, error) { // Implements EIP-2537 G1Mul precompile. // > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G1 point (`128` bytes). @@ -728,11 +728,11 @@ func (c *bls12381G1Mul) Run(_ *EVM, input []byte) ([]byte, error) { return g.EncodePoint(r), nil } -// bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile. -type bls12381G1MultiExp struct{} +// Bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile. +type Bls12381G1MultiExp struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { +func (c *Bls12381G1MultiExp) RequiredGas(input []byte) uint64 { // Calculate G1 point, scalar value pair length k := len(input) / 160 if k == 0 { @@ -750,7 +750,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000 } -func (c *bls12381G1MultiExp) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bls12381G1MultiExp) Run(_ *EVM, input []byte) ([]byte, error) { // Implements EIP-2537 G1MultiExp precompile. // G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes). @@ -785,15 +785,15 @@ func (c *bls12381G1MultiExp) Run(_ *EVM, input []byte) ([]byte, error) { return g.EncodePoint(r), nil } -// bls12381G2Add implements EIP-2537 G2Add precompile. -type bls12381G2Add struct{} +// Bls12381G2Add implements EIP-2537 G2Add precompile. +type Bls12381G2Add struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bls12381G2Add) RequiredGas(input []byte) uint64 { +func (c *Bls12381G2Add) RequiredGas(input []byte) uint64 { return params.Bls12381G2AddGas } -func (c *bls12381G2Add) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bls12381G2Add) Run(_ *EVM, input []byte) ([]byte, error) { // Implements EIP-2537 G2Add precompile. // > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). // > Output is an encoding of addition operation result - single G2 point (`256` bytes). @@ -823,15 +823,15 @@ func (c *bls12381G2Add) Run(_ *EVM, input []byte) ([]byte, error) { return g.EncodePoint(r), nil } -// bls12381G2Mul implements EIP-2537 G2Mul precompile. -type bls12381G2Mul struct{} +// Bls12381G2Mul implements EIP-2537 G2Mul precompile. +type Bls12381G2Mul struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 { +func (c *Bls12381G2Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G2MulGas } -func (c *bls12381G2Mul) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bls12381G2Mul) Run(_ *EVM, input []byte) ([]byte, error) { // Implements EIP-2537 G2MUL precompile logic. // > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G2 point (`256` bytes). @@ -859,11 +859,11 @@ func (c *bls12381G2Mul) Run(_ *EVM, input []byte) ([]byte, error) { return g.EncodePoint(r), nil } -// bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile. -type bls12381G2MultiExp struct{} +// Bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile. +type Bls12381G2MultiExp struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { +func (c *Bls12381G2MultiExp) RequiredGas(input []byte) uint64 { // Calculate G2 point, scalar value pair length k := len(input) / 288 if k == 0 { @@ -881,7 +881,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000 } -func (c *bls12381G2MultiExp) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bls12381G2MultiExp) Run(_ *EVM, input []byte) ([]byte, error) { // Implements EIP-2537 G2MultiExp precompile logic // > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes). @@ -916,15 +916,15 @@ func (c *bls12381G2MultiExp) Run(_ *EVM, input []byte) ([]byte, error) { return g.EncodePoint(r), nil } -// bls12381Pairing implements EIP-2537 Pairing precompile. -type bls12381Pairing struct{} +// Bls12381Pairing implements EIP-2537 Pairing precompile. +type Bls12381Pairing struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bls12381Pairing) RequiredGas(input []byte) uint64 { +func (c *Bls12381Pairing) RequiredGas(input []byte) uint64 { return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas } -func (c *bls12381Pairing) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bls12381Pairing) Run(_ *EVM, input []byte) ([]byte, error) { // Implements EIP-2537 Pairing precompile logic. // > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure: // > - `128` bytes of G1 point encoding @@ -987,7 +987,7 @@ func decodeBLS12381FieldElement(in []byte) ([]byte, error) { // check top bytes for i := 0; i < 16; i++ { if in[i] != byte(0x00) { - return nil, errBLS12381InvalidFieldElementTopBytes + return nil, errBLS12381InvalidFieldElementTOpBytes } } out := make([]byte, 48) @@ -995,15 +995,15 @@ func decodeBLS12381FieldElement(in []byte) ([]byte, error) { return out, nil } -// bls12381MapG1 implements EIP-2537 MapG1 precompile. -type bls12381MapG1 struct{} +// Bls12381MapG1 implements EIP-2537 MapG1 precompile. +type Bls12381MapG1 struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bls12381MapG1) RequiredGas(input []byte) uint64 { +func (c *Bls12381MapG1) RequiredGas(input []byte) uint64 { return params.Bls12381MapG1Gas } -func (c *bls12381MapG1) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bls12381MapG1) Run(_ *EVM, input []byte) ([]byte, error) { // Implements EIP-2537 Map_To_G1 precompile. // > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field. // > Output of this call is `128` bytes and is G1 point following respective encoding rules. @@ -1030,15 +1030,15 @@ func (c *bls12381MapG1) Run(_ *EVM, input []byte) ([]byte, error) { return g.EncodePoint(r), nil } -// bls12381MapG2 implements EIP-2537 MapG2 precompile. -type bls12381MapG2 struct{} +// Bls12381MapG2 implements EIP-2537 MapG2 precompile. +type Bls12381MapG2 struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bls12381MapG2) RequiredGas(input []byte) uint64 { +func (c *Bls12381MapG2) RequiredGas(input []byte) uint64 { return params.Bls12381MapG2Gas } -func (c *bls12381MapG2) Run(_ *EVM, input []byte) ([]byte, error) { +func (c *Bls12381MapG2) Run(_ *EVM, input []byte) ([]byte, error) { // Implements EIP-2537 Map_FP2_TO_G2 precompile logic. // > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field. // > Output of this call is `256` bytes and is G2 point following respective encoding rules. @@ -1072,11 +1072,11 @@ func (c *bls12381MapG2) Run(_ *EVM, input []byte) ([]byte, error) { return g.EncodePoint(r), nil } -// kzgPointEvaluation implements the EIP-4844 point evaluation precompile. -type kzgPointEvaluation struct{} +// KzgPointEvaluation implements the EIP-4844 point evaluation precompile. +type KzgPointEvaluation struct{} // RequiredGas estimates the gas required for running the point evaluation precompile. -func (b *kzgPointEvaluation) RequiredGas(input []byte) uint64 { +func (b *KzgPointEvaluation) RequiredGas(input []byte) uint64 { return params.BlobTxPointEvaluationPrecompileGas } @@ -1093,7 +1093,7 @@ var ( ) // Run executes the point evaluation precompile. -func (b *kzgPointEvaluation) Run(_ *EVM, input []byte) ([]byte, error) { +func (b *KzgPointEvaluation) Run(_ *EVM, input []byte) ([]byte, error) { if len(input) != blobVerifyInputLength { return nil, errBlobVerifyInvalidInputLength } diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index 5001a023f9..7c3b6c72d9 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package vm +package vm_test import ( "bytes" @@ -25,6 +25,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" ) // precompiledTest defines the input/output pairs for precompiled contract tests. @@ -45,50 +46,50 @@ 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}): &ecrecover{}, - 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}): &bn256AddIstanbul{}, - common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - common.BytesToAddress([]byte{9}): &blake2F{}, - common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{}, +var allPrecompiles = map[common.Address]vm.PrecompiledContract{ + common.BytesToAddress([]byte{1}): &vm.Ecrecover{}, + common.BytesToAddress([]byte{2}): &vm.Sha256hash{}, + common.BytesToAddress([]byte{3}): &vm.Ripemd160hash{}, + common.BytesToAddress([]byte{4}): &vm.DataCopy{}, + common.BytesToAddress([]byte{5}): &vm.BigModExp{Eip2565: false}, + common.BytesToAddress([]byte{0xf5}): &vm.BigModExp{Eip2565: true}, + common.BytesToAddress([]byte{6}): &vm.Bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &vm.Bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &vm.Bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &vm.Blake2F{}, + common.BytesToAddress([]byte{0x0a}): &vm.KzgPointEvaluation{}, - common.BytesToAddress([]byte{0x0f, 0x0a}): &bls12381G1Add{}, - common.BytesToAddress([]byte{0x0f, 0x0b}): &bls12381G1Mul{}, - common.BytesToAddress([]byte{0x0f, 0x0c}): &bls12381G1MultiExp{}, - common.BytesToAddress([]byte{0x0f, 0x0d}): &bls12381G2Add{}, - common.BytesToAddress([]byte{0x0f, 0x0e}): &bls12381G2Mul{}, - common.BytesToAddress([]byte{0x0f, 0x0f}): &bls12381G2MultiExp{}, - common.BytesToAddress([]byte{0x0f, 0x10}): &bls12381Pairing{}, - common.BytesToAddress([]byte{0x0f, 0x11}): &bls12381MapG1{}, - common.BytesToAddress([]byte{0x0f, 0x12}): &bls12381MapG2{}, + common.BytesToAddress([]byte{0x0f, 0x0a}): &vm.Bls12381G1Add{}, + common.BytesToAddress([]byte{0x0f, 0x0b}): &vm.Bls12381G1Mul{}, + common.BytesToAddress([]byte{0x0f, 0x0c}): &vm.Bls12381G1MultiExp{}, + common.BytesToAddress([]byte{0x0f, 0x0d}): &vm.Bls12381G2Add{}, + common.BytesToAddress([]byte{0x0f, 0x0e}): &vm.Bls12381G2Mul{}, + common.BytesToAddress([]byte{0x0f, 0x0f}): &vm.Bls12381G2MultiExp{}, + common.BytesToAddress([]byte{0x0f, 0x10}): &vm.Bls12381Pairing{}, + common.BytesToAddress([]byte{0x0f, 0x11}): &vm.Bls12381MapG1{}, + common.BytesToAddress([]byte{0x0f, 0x12}): &vm.Bls12381MapG2{}, } // EIP-152 test vectors -var blake2FMalformedInputTests = []precompiledFailureTest{ +var Blake2FMalformedInputTests = []precompiledFailureTest{ { Input: "", - ExpectedError: errBlake2FInvalidInputLength.Error(), + ExpectedError: vm.ErrBlake2FInvalidInputLength.Error(), Name: "vector 0: empty input", }, { Input: "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - ExpectedError: errBlake2FInvalidInputLength.Error(), + ExpectedError: vm.ErrBlake2FInvalidInputLength.Error(), Name: "vector 1: less than 213 bytes input", }, { Input: "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - ExpectedError: errBlake2FInvalidInputLength.Error(), + ExpectedError: vm.ErrBlake2FInvalidInputLength.Error(), Name: "vector 2: more than 213 bytes input", }, { Input: "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002", - ExpectedError: errBlake2FInvalidFinalFlag.Error(), + ExpectedError: vm.ErrBlake2FInvalidFinalFlag.Error(), Name: "vector 3: malformed final block indicator flag", }, } @@ -98,7 +99,7 @@ func testPrecompiled(addr string, test precompiledTest, t *testing.T) { in := common.Hex2Bytes(test.Input) gas := p.RequiredGas(in) t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) { - if res, _, err := RunPrecompiledContract(p, nil, in, gas); err != nil { + if res, _, err := vm.RunPrecompiledContract(p, nil, in, gas); err != nil { t.Error(err) } else if common.Bytes2Hex(res) != test.Expected { t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res)) @@ -120,7 +121,7 @@ func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) { gas := p.RequiredGas(in) - 1 t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) { - _, _, err := RunPrecompiledContract(p, nil, in, gas) + _, _, err := vm.RunPrecompiledContract(p, nil, in, gas) if err.Error() != "out of gas" { t.Errorf("Expected error [out of gas], got [%v]", err) } @@ -137,7 +138,7 @@ func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing in := common.Hex2Bytes(test.Input) gas := p.RequiredGas(in) t.Run(test.Name, func(t *testing.T) { - _, _, err := RunPrecompiledContract(p, nil, in, gas) + _, _, err := vm.RunPrecompiledContract(p, nil, in, gas) if err.Error() != test.ExpectedError { t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err) } @@ -169,7 +170,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) { bench.ResetTimer() for i := 0; i < bench.N; i++ { copy(data, in) - res, _, err = RunPrecompiledContract(p, nil, data, reqGas) + res, _, err = vm.RunPrecompiledContract(p, nil, data, reqGas) } bench.StopTimer() elapsed := uint64(time.Since(start)) @@ -237,8 +238,8 @@ 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) } +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) } @@ -263,11 +264,11 @@ func BenchmarkPrecompiledBn256ScalarMul(b *testing.B) { benchJson("bn256ScalarMu func TestPrecompiledBn256Pairing(t *testing.T) { testJson("bn256Pairing", "08", t) } func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJson("bn256Pairing", "08", b) } -func TestPrecompiledBlake2F(t *testing.T) { testJson("blake2F", "09", t) } -func BenchmarkPrecompiledBlake2F(b *testing.B) { benchJson("blake2F", "09", 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 { + for _, test := range Blake2FMalformedInputTests { testPrecompiledFailure("09", test, t) } } diff --git a/core/vm/eips.go b/core/vm/eips.go index 35f0a3f7c2..dd3420f32a 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -71,14 +71,14 @@ func ActivateableEips() []string { // - Define SELFBALANCE, with cost GasFastStep (5) func enable1884(jt *JumpTable) { // Gas cost changes - jt[SLOAD].constantGas = params.SloadGasEIP1884 - jt[BALANCE].constantGas = params.BalanceGasEIP1884 - jt[EXTCODEHASH].constantGas = params.ExtcodeHashGasEIP1884 + jt[SLOAD].ConstantGas = params.SloadGasEIP1884 + jt[BALANCE].ConstantGas = params.BalanceGasEIP1884 + jt[EXTCODEHASH].ConstantGas = params.ExtcodeHashGasEIP1884 // New opcode jt[SELFBALANCE] = &operation{ execute: opSelfBalance, - constantGas: GasFastStep, + ConstantGas: GasFastStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), } @@ -96,7 +96,7 @@ func enable1344(jt *JumpTable) { // New opcode jt[CHAINID] = &operation{ execute: opChainID, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), } @@ -111,7 +111,7 @@ func opChainID(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([] // enable2200 applies EIP-2200 (Rebalance net-metered SSTORE) func enable2200(jt *JumpTable) { - jt[SLOAD].constantGas = params.SloadGasEIP2200 + jt[SLOAD].ConstantGas = params.SloadGasEIP2200 jt[SSTORE].dynamicGas = gasSStoreEIP2200 } @@ -120,36 +120,36 @@ func enable2200(jt *JumpTable) { func enable2929(jt *JumpTable) { jt[SSTORE].dynamicGas = gasSStoreEIP2929 - jt[SLOAD].constantGas = 0 + jt[SLOAD].ConstantGas = 0 jt[SLOAD].dynamicGas = gasSLoadEIP2929 - jt[EXTCODECOPY].constantGas = params.WarmStorageReadCostEIP2929 + jt[EXTCODECOPY].ConstantGas = params.WarmStorageReadCostEIP2929 jt[EXTCODECOPY].dynamicGas = gasExtCodeCopyEIP2929 - jt[EXTCODESIZE].constantGas = params.WarmStorageReadCostEIP2929 + jt[EXTCODESIZE].ConstantGas = params.WarmStorageReadCostEIP2929 jt[EXTCODESIZE].dynamicGas = gasEip2929AccountCheck - jt[EXTCODEHASH].constantGas = params.WarmStorageReadCostEIP2929 + jt[EXTCODEHASH].ConstantGas = params.WarmStorageReadCostEIP2929 jt[EXTCODEHASH].dynamicGas = gasEip2929AccountCheck - jt[BALANCE].constantGas = params.WarmStorageReadCostEIP2929 + jt[BALANCE].ConstantGas = params.WarmStorageReadCostEIP2929 jt[BALANCE].dynamicGas = gasEip2929AccountCheck - jt[CALL].constantGas = params.WarmStorageReadCostEIP2929 + jt[CALL].ConstantGas = params.WarmStorageReadCostEIP2929 jt[CALL].dynamicGas = gasCallEIP2929 - jt[CALLCODE].constantGas = params.WarmStorageReadCostEIP2929 + jt[CALLCODE].ConstantGas = params.WarmStorageReadCostEIP2929 jt[CALLCODE].dynamicGas = gasCallCodeEIP2929 - jt[STATICCALL].constantGas = params.WarmStorageReadCostEIP2929 + jt[STATICCALL].ConstantGas = params.WarmStorageReadCostEIP2929 jt[STATICCALL].dynamicGas = gasStaticCallEIP2929 - jt[DELEGATECALL].constantGas = params.WarmStorageReadCostEIP2929 + jt[DELEGATECALL].ConstantGas = params.WarmStorageReadCostEIP2929 jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP2929 - // This was previously part of the dynamic cost, but we're using it as a constantGas + // This was previously part of the dynamic cost, but we're using it as a ConstantGas // factor here - jt[SELFDESTRUCT].constantGas = params.SelfdestructGasEIP150 + jt[SELFDESTRUCT].ConstantGas = params.SelfdestructGasEIP150 jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP2929 } @@ -168,7 +168,7 @@ func enable3198(jt *JumpTable) { // New opcode jt[BASEFEE] = &operation{ execute: opBaseFee, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), } @@ -179,22 +179,22 @@ func enable3198(jt *JumpTable) { // - Adds TSTORE that writes to transient storage func enable1153(jt *JumpTable) { jt[TLOAD] = &operation{ - execute: opTload, - constantGas: params.WarmStorageReadCostEIP2929, + execute: OpTload, + ConstantGas: params.WarmStorageReadCostEIP2929, minStack: minStack(1, 1), maxStack: maxStack(1, 1), } jt[TSTORE] = &operation{ - execute: opTstore, - constantGas: params.WarmStorageReadCostEIP2929, + execute: OpTstore, + ConstantGas: params.WarmStorageReadCostEIP2929, minStack: minStack(2, 0), maxStack: maxStack(2, 0), } } -// opTload implements TLOAD opcode -func opTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +// OpTload implements TLOAD opcode +func OpTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { loc := scope.Stack.peek() hash := common.Hash(loc.Bytes32()) val := interpreter.evm.StateDB.GetTransientState(scope.Contract.Address(), hash) @@ -202,8 +202,8 @@ func opTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by return nil, nil } -// opTstore implements TSTORE opcode -func opTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +// OpTstore implements TSTORE opcode +func OpTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { if interpreter.readOnly { return nil, ErrWriteProtection } @@ -225,7 +225,7 @@ func enable3855(jt *JumpTable) { // New opcode jt[PUSH0] = &operation{ execute: opPush0, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), } @@ -248,17 +248,17 @@ func enable3860(jt *JumpTable) { // https://eips.ethereum.org/EIPS/eip-5656 func enable5656(jt *JumpTable) { jt[MCOPY] = &operation{ - execute: opMcopy, - constantGas: GasFastestStep, - dynamicGas: gasMcopy, + execute: OpMcopy, + ConstantGas: GasFastestStep, + dynamicGas: GasMcopy, minStack: minStack(3, 0), maxStack: maxStack(3, 0), - memorySize: memoryMcopy, + memorySize: MemoryMcopy, } } -// opMcopy implements the MCOPY opcode (https://eips.ethereum.org/EIPS/eip-5656) -func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +// OpMcopy implements the MCOPY opcode (https://eips.ethereum.org/EIPS/eip-5656) +func OpMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { var ( dst = scope.Stack.pop() src = scope.Stack.pop() @@ -270,8 +270,8 @@ func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by return nil, nil } -// opBlobHash implements the BLOBHASH opcode -func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +// OpBlobHash implements the BLOBHASH opcode +func OpBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { index := scope.Stack.peek() if index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) { blobHash := interpreter.evm.TxContext.BlobHashes[index.Uint64()] @@ -292,8 +292,8 @@ func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) // enable4844 applies EIP-4844 (BLOBHASH opcode) func enable4844(jt *JumpTable) { jt[BLOBHASH] = &operation{ - execute: opBlobHash, - constantGas: GasFastestStep, + execute: OpBlobHash, + ConstantGas: GasFastestStep, minStack: minStack(1, 1), maxStack: maxStack(1, 1), } @@ -303,7 +303,7 @@ func enable4844(jt *JumpTable) { func enable7516(jt *JumpTable) { jt[BLOBBASEFEE] = &operation{ execute: opBlobBaseFee, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), } @@ -314,7 +314,7 @@ func enable6780(jt *JumpTable) { jt[SELFDESTRUCT] = &operation{ execute: opSelfdestruct6780, dynamicGas: gasSelfdestructEIP3529, - constantGas: params.SelfdestructGasEIP150, + ConstantGas: params.SelfdestructGasEIP150, minStack: minStack(1, 0), maxStack: maxStack(1, 0), } diff --git a/core/vm/evm.go b/core/vm/evm.go index 7f806c9678..fea3d188b5 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -149,6 +149,10 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig return evm } +func (evm *EVM) GetInterpreter() *EVMInterpreter { + return evm.interpreter +} + // Reset resets the EVM with a new transaction context.Reset // This is not threadsafe and should only be done very cautiously. func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) { diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index 4b141d8f9a..315960ef49 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -24,9 +24,9 @@ import ( "github.com/ethereum/go-ethereum/params" ) -// memoryGasCost calculates the quadratic gas for memory expansion. It does so +// MemoryGasCost calculates the quadratic gas for memory expansion. It does so // only for the memory region that is expanded, not the total memory. -func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { +func MemoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { if newMemSize == 0 { return 0, nil } @@ -38,7 +38,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { if newMemSize > 0x1FFFFFFFE0 { return 0, ErrGasUintOverflow } - newMemSizeWords := toWordSize(newMemSize) + newMemSizeWords := ToWordSize(newMemSize) newMemSize = newMemSizeWords * 32 if newMemSize > uint64(mem.Len()) { @@ -66,7 +66,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { func memoryCopierGas(stackpos int) gasFunc { return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { // Gas for expanding the memory - gas, err := memoryGasCost(mem, memorySize) + gas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } @@ -76,7 +76,7 @@ func memoryCopierGas(stackpos int) gasFunc { return 0, ErrGasUintOverflow } - if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { + if words, overflow = math.SafeMul(ToWordSize(words), params.CopyGas); overflow { return 0, ErrGasUintOverflow } @@ -90,7 +90,7 @@ func memoryCopierGas(stackpos int) gasFunc { var ( gasCallDataCopy = memoryCopierGas(2) gasCodeCopy = memoryCopierGas(2) - gasMcopy = memoryCopierGas(2) + GasMcopy = memoryCopierGas(2) gasExtCodeCopy = memoryCopierGas(3) gasReturnDataCopy = memoryCopierGas(2) ) @@ -229,7 +229,7 @@ func makeGasLog(n uint64) gasFunc { return 0, ErrGasUintOverflow } - gas, err := memoryGasCost(mem, memorySize) + gas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } @@ -253,7 +253,7 @@ func makeGasLog(n uint64) gasFunc { } func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) + gas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } @@ -261,7 +261,7 @@ func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor if overflow { return 0, ErrGasUintOverflow } - if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Keccak256WordGas); overflow { + if wordGas, overflow = math.SafeMul(ToWordSize(wordGas), params.Keccak256WordGas); overflow { return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, wordGas); overflow { @@ -274,7 +274,7 @@ func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor // static cost have a dynamic cost which is solely based on the memory // expansion func pureMemoryGascost(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - return memoryGasCost(mem, memorySize) + return MemoryGasCost(mem, memorySize) } var ( @@ -287,7 +287,7 @@ var ( ) func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) + gas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } @@ -295,7 +295,7 @@ func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memoryS if overflow { return 0, ErrGasUintOverflow } - if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Keccak256WordGas); overflow { + if wordGas, overflow = math.SafeMul(ToWordSize(wordGas), params.Keccak256WordGas); overflow { return 0, ErrGasUintOverflow } if gas, overflow = math.SafeAdd(gas, wordGas); overflow { @@ -305,7 +305,7 @@ func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memoryS } func gasCreateEip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) + gas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } @@ -321,7 +321,7 @@ func gasCreateEip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m return gas, nil } func gasCreate2Eip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) + gas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } @@ -379,7 +379,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize if transfersValue { gas += params.CallValueTransferGas } - memoryGas, err := memoryGasCost(mem, memorySize) + memoryGas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } @@ -399,7 +399,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize } func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - memoryGas, err := memoryGasCost(mem, memorySize) + memoryGas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } @@ -424,7 +424,7 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory } func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) + gas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } @@ -440,7 +440,7 @@ func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me } func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - gas, err := memoryGasCost(mem, memorySize) + gas, err := MemoryGasCost(mem, memorySize) if err != nil { return 0, err } diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go index 4a5259a262..60f8dbd2f0 100644 --- a/core/vm/gas_table_test.go +++ b/core/vm/gas_table_test.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package vm +package vm_test import ( "bytes" @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" ) @@ -41,9 +42,9 @@ func TestMemoryGasCost(t *testing.T) { {0x1fffffffe1, 0, true}, } for i, tt := range tests { - v, err := memoryGasCost(&Memory{}, tt.size) - if (err == ErrGasUintOverflow) != tt.overflow { - t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == ErrGasUintOverflow, tt.overflow) + v, err := vm.MemoryGasCost(&vm.Memory{}, tt.size) + if (err == vm.ErrGasUintOverflow) != tt.overflow { + t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == vm.ErrGasUintOverflow, tt.overflow) } if v != tt.cost { t.Errorf("test %d: gas cost mismatch: have %v, want %v", i, v, tt.cost) @@ -76,7 +77,7 @@ var eip2200Tests = []struct { {1, math.MaxUint64, "0x60016000556001600055", 1612, 0, nil}, // 1 -> 1 -> 1 {0, math.MaxUint64, "0x600160005560006000556001600055", 40818, 19200, nil}, // 0 -> 1 -> 0 -> 1 {1, math.MaxUint64, "0x600060005560016000556000600055", 10818, 19200, nil}, // 1 -> 0 -> 1 -> 0 - {1, 2306, "0x6001600055", 2306, 0, ErrOutOfGas}, // 1 -> 1 (2300 sentry + 2xPUSH) + {1, 2306, "0x6001600055", 2306, 0, vm.ErrOutOfGas}, // 1 -> 1 (2300 sentry + 2xPUSH) {1, 2307, "0x6001600055", 806, 0, nil}, // 1 -> 1 (2301 sentry + 2xPUSH) } @@ -90,13 +91,13 @@ func TestEIP2200(t *testing.T) { statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original})) statedb.Finalise(true) // Push the state into the "original" slot - vmctx := BlockContext{ - CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true }, - Transfer: func(StateDB, common.Address, common.Address, *big.Int) {}, + vmctx := vm.BlockContext{ + CanTransfer: func(vm.StateDB, common.Address, *big.Int) bool { return true }, + Transfer: func(vm.StateDB, common.Address, common.Address, *big.Int) {}, } - vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}}) + vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, params.AllEthashProtocolChanges, vm.Config{ExtraEips: []int{2200}}) - _, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int)) + _, gas, err := vmenv.Call(vm.AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int)) if err != tt.failure { t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure) } @@ -140,19 +141,19 @@ func TestCreateGas(t *testing.T) { statedb.CreateAccount(address) statedb.SetCode(address, hexutil.MustDecode(tt.code)) statedb.Finalise(true) - vmctx := BlockContext{ - CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true }, - Transfer: func(StateDB, common.Address, common.Address, *big.Int) {}, + vmctx := vm.BlockContext{ + CanTransfer: func(vm.StateDB, common.Address, *big.Int) bool { return true }, + Transfer: func(vm.StateDB, common.Address, common.Address, *big.Int) {}, BlockNumber: big.NewInt(0), } - config := Config{} + config := vm.Config{} if tt.eip3860 { config.ExtraEips = []int{3860} } - vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, config) + vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, params.AllEthashProtocolChanges, config) var startGas = uint64(testGas) - ret, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, startGas, new(big.Int)) + ret, gas, err := vmenv.Call(vm.AccountRef(common.Address{}), address, nil, startGas, new(big.Int)) if err != nil { return false } diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 56ff350201..8c28871312 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -24,55 +24,55 @@ import ( "github.com/holiman/uint256" ) -func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.Add(&x, y) return nil, nil } -func opSub(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpSub(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.Sub(&x, y) return nil, nil } -func opMul(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpMul(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.Mul(&x, y) return nil, nil } -func opDiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpDiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.Div(&x, y) return nil, nil } -func opSdiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpSdiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.SDiv(&x, y) return nil, nil } -func opMod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpMod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.Mod(&x, y) return nil, nil } -func opSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.SMod(&x, y) return nil, nil } -func opExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { base, exponent := scope.Stack.pop(), scope.Stack.peek() exponent.Exp(&base, exponent) return nil, nil } -func opSignExtend(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpSignExtend(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { back, num := scope.Stack.pop(), scope.Stack.peek() num.ExtendSign(num, &back) return nil, nil @@ -84,7 +84,7 @@ func opNot(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte return nil, nil } -func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() if x.Lt(y) { y.SetOne() @@ -94,7 +94,7 @@ func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, return nil, nil } -func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() if x.Gt(y) { y.SetOne() @@ -104,7 +104,7 @@ func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, return nil, nil } -func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() if x.Slt(y) { y.SetOne() @@ -114,7 +114,7 @@ func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte return nil, nil } -func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() if x.Sgt(y) { y.SetOne() @@ -124,7 +124,7 @@ func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte return nil, nil } -func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() if x.Eq(y) { y.SetOne() @@ -134,7 +134,7 @@ func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, return nil, nil } -func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x := scope.Stack.peek() if x.IsZero() { x.SetOne() @@ -144,31 +144,31 @@ func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b return nil, nil } -func opAnd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpAnd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.And(&x, y) return nil, nil } -func opOr(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpOr(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.Or(&x, y) return nil, nil } -func opXor(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpXor(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.peek() y.Xor(&x, y) return nil, nil } -func opByte(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpByte(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { th, val := scope.Stack.pop(), scope.Stack.peek() val.Byte(&th) return nil, nil } -func opAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek() if z.IsZero() { z.Clear() @@ -178,16 +178,16 @@ func opAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b return nil, nil } -func opMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek() z.MulMod(&x, &y, z) return nil, nil } -// opSHL implements Shift Left +// OpSHL implements Shift Left // The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2, // and pushes on the stack arg2 shifted to the left by arg1 number of bits. -func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards shift, value := scope.Stack.pop(), scope.Stack.peek() if shift.LtUint64(256) { @@ -198,10 +198,10 @@ func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte return nil, nil } -// opSHR implements Logical Shift Right +// OpSHR implements Logical Shift Right // The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2, // and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill. -func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards shift, value := scope.Stack.pop(), scope.Stack.peek() if shift.LtUint64(256) { @@ -212,10 +212,10 @@ func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte return nil, nil } -// opSAR implements Arithmetic Shift Right +// OpSAR implements Arithmetic Shift Right // The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2, // and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension. -func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { shift, value := scope.Stack.pop(), scope.Stack.peek() if shift.GtUint64(256) { if value.Sign() >= 0 { @@ -231,7 +231,7 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte return nil, nil } -func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { offset, size := scope.Stack.pop(), scope.Stack.peek() data := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) @@ -252,7 +252,7 @@ func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ( return nil, nil } -func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes())) return nil, nil } @@ -264,7 +264,7 @@ func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([] return nil, nil } -func opOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes())) return nil, nil } @@ -476,7 +476,7 @@ func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) return nil, nil } -func opRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { v := new(uint256.Int).SetBytes(interpreter.evm.Context.Random.Bytes()) scope.Stack.push(v) return nil, nil @@ -499,14 +499,14 @@ func opMload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by return nil, nil } -func opMstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpMstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { // pop value of the stack mStart, val := scope.Stack.pop(), scope.Stack.pop() scope.Memory.Set32(mStart.Uint64(), &val) return nil, nil } -func opMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { +func OpMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { off, val := scope.Stack.pop(), scope.Stack.pop() scope.Memory.store[off.Uint64()] = byte(val.Uint64()) return nil, nil @@ -850,7 +850,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon // following functions are used by the instruction jump table // make log instruction function -func makeLog(size int) executionFunc { +func makeLog(size int) ExecutionFunc { return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { if interpreter.readOnly { return nil, ErrWriteProtection @@ -893,7 +893,7 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by } // make push instruction function -func makePush(size uint64, pushByteSize int) executionFunc { +func makePush(size uint64, pushByteSize int) ExecutionFunc { return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { codeLen := len(scope.Contract.Code) @@ -917,7 +917,7 @@ func makePush(size uint64, pushByteSize int) executionFunc { } // make dup instruction function -func makeDup(size int64) executionFunc { +func makeDup(size int64) ExecutionFunc { return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { scope.Stack.dup(int(size)) return nil, nil @@ -925,7 +925,7 @@ func makeDup(size int64) executionFunc { } // make swap instruction function -func makeSwap(size int64) executionFunc { +func makeSwap(size int64) ExecutionFunc { // switch n + 1 otherwise n would be swapped with n size++ return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 807073336d..1dd0bed76a 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package vm +package vm_test import ( "bytes" @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" @@ -48,7 +49,7 @@ type twoOperandParams struct { var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" var commonParams []*twoOperandParams -var twoOpMethods map[string]executionFunc +var twoOpMethods map[string]vm.ExecutionFunc type contractRef struct { addr common.Address @@ -78,50 +79,50 @@ func init() { commonParams[i*len(params)+j] = &twoOperandParams{x, y} } } - twoOpMethods = map[string]executionFunc{ - "add": opAdd, - "sub": opSub, - "mul": opMul, - "div": opDiv, - "sdiv": opSdiv, - "mod": opMod, - "smod": opSmod, - "exp": opExp, - "signext": opSignExtend, - "lt": opLt, - "gt": opGt, - "slt": opSlt, - "sgt": opSgt, - "eq": opEq, - "and": opAnd, - "or": opOr, - "xor": opXor, - "byte": opByte, - "shl": opSHL, - "shr": opSHR, - "sar": opSAR, + twoOpMethods = map[string]vm.ExecutionFunc{ + "add": vm.OpAdd, + "sub": vm.OpSub, + "mul": vm.OpMul, + "div": vm.OpDiv, + "sdiv": vm.OpSdiv, + "mod": vm.OpMod, + "smod": vm.OpSmod, + "exp": vm.OpExp, + "signext": vm.OpSignExtend, + "lt": vm.OpLt, + "gt": vm.OpGt, + "slt": vm.OpSlt, + "sgt": vm.OpSgt, + "eq": vm.OpEq, + "and": vm.OpAnd, + "or": vm.OpOr, + "xor": vm.OpXor, + "byte": vm.OpByte, + "shl": vm.OpSHL, + "shr": vm.OpSHR, + "sar": vm.OpSAR, } } -func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) { +func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn vm.ExecutionFunc, name string) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() pc = uint64(0) - evmInterpreter = env.interpreter + evmInterpreter = env.GetInterpreter() ) for i, test := range tests { x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X)) y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y)) expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected)) - stack.push(x) - stack.push(y) - opFn(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) - if len(stack.data) != 1 { - t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data)) + stack.Push(x) + stack.Push(y) + opFn(&pc, evmInterpreter, &vm.ScopeContext{nil, stack, nil}) + if len(stack.Data()) != 1 { + t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.Data())) } - actual := stack.pop() + actual := stack.Pop() if actual.Cmp(expected) != 0 { t.Errorf("Testcase %v %d, %v(%x, %x): expected %x, got %x", name, i, name, x, y, expected, actual) @@ -140,7 +141,7 @@ func TestByteOp(t *testing.T) { {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "20", "00"}, {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "FFFFFFFFFFFFFFFF", "00"}, } - testTwoOperandOp(t, tests, opByte, "byte") + testTwoOperandOp(t, tests, vm.OpByte, "byte") } func TestSHL(t *testing.T) { @@ -157,7 +158,7 @@ func TestSHL(t *testing.T) { {"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"}, {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, } - testTwoOperandOp(t, tests, opSHL, "shl") + testTwoOperandOp(t, tests, vm.OpSHL, "shl") } func TestSHR(t *testing.T) { @@ -175,7 +176,7 @@ func TestSHR(t *testing.T) { {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"}, {"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"}, } - testTwoOperandOp(t, tests, opSHR, "shr") + testTwoOperandOp(t, tests, vm.OpSHR, "shr") } func TestSAR(t *testing.T) { @@ -199,14 +200,14 @@ func TestSAR(t *testing.T) { {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"}, } - testTwoOperandOp(t, tests, opSAR, "sar") + testTwoOperandOp(t, tests, vm.OpSAR, "sar") } func TestAddMod(t *testing.T) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - evmInterpreter = NewEVMInterpreter(env) + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() + evmInterpreter = vm.NewEVMInterpreter(env) pc = uint64(0) ) tests := []struct { @@ -229,11 +230,11 @@ func TestAddMod(t *testing.T) { y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.y)) z := new(uint256.Int).SetBytes(common.Hex2Bytes(test.z)) expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.expected)) - stack.push(z) - stack.push(y) - stack.push(x) - opAddmod(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) - actual := stack.pop() + stack.Push(z) + stack.Push(y) + stack.Push(x) + vm.OpAddmod(&pc, evmInterpreter, &vm.ScopeContext{nil, stack, nil}) + actual := stack.Pop() if actual.Cmp(expected) != 0 { t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual) } @@ -246,21 +247,21 @@ func TestWriteExpectedValues(t *testing.T) { t.Skip("Enable this test to create json test cases.") // getResult is a convenience function to generate the expected values - getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase { + getResult := func(args []*twoOperandParams, opFn vm.ExecutionFunc) []TwoOperandTestcase { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() pc = uint64(0) - interpreter = env.interpreter + interpreter = env.Interpreter() ) result := make([]TwoOperandTestcase, len(args)) for i, param := range args { x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x)) y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y)) - stack.push(x) - stack.push(y) - opFn(&pc, interpreter, &ScopeContext{nil, stack, nil}) - actual := stack.pop() + stack.Push(x) + stack.Push(y) + opFn(&pc, interpreter, &vm.ScopeContext{nil, stack, nil}) + actual := stack.Pop() result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)} } return result @@ -291,15 +292,15 @@ func TestJsonTestcases(t *testing.T) { } } -func opBenchmark(bench *testing.B, op executionFunc, args ...string) { +func opBenchmark(bench *testing.B, op vm.ExecutionFunc, args ...string) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - scope = &ScopeContext{nil, stack, nil} - evmInterpreter = NewEVMInterpreter(env) + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() + scope = &vm.ScopeContext{nil, stack, nil} + evmInterpreter = vm.NewEVMInterpreter(env) ) - env.interpreter = evmInterpreter + env.SetInterpreter(evmInterpreter) // convert args intArgs := make([]*uint256.Int, len(args)) for i, arg := range args { @@ -309,10 +310,10 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) { bench.ResetTimer() for i := 0; i < bench.N; i++ { for _, arg := range intArgs { - stack.push(arg) + stack.Push(arg) } op(&pc, evmInterpreter, scope) - stack.pop() + stack.Pop() } bench.StopTimer() @@ -328,169 +329,169 @@ func BenchmarkOpAdd64(b *testing.B) { x := "ffffffff" y := "fd37f3e2bba2c4f" - opBenchmark(b, opAdd, x, y) + opBenchmark(b, vm.OpAdd, x, y) } func BenchmarkOpAdd128(b *testing.B) { x := "ffffffffffffffff" y := "f5470b43c6549b016288e9a65629687" - opBenchmark(b, opAdd, x, y) + opBenchmark(b, vm.OpAdd, x, y) } func BenchmarkOpAdd256(b *testing.B) { x := "0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9" y := "a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57" - opBenchmark(b, opAdd, x, y) + opBenchmark(b, vm.OpAdd, x, y) } func BenchmarkOpSub64(b *testing.B) { x := "51022b6317003a9d" y := "a20456c62e00753a" - opBenchmark(b, opSub, x, y) + opBenchmark(b, vm.OpSub, x, y) } func BenchmarkOpSub128(b *testing.B) { x := "4dde30faaacdc14d00327aac314e915d" y := "9bbc61f5559b829a0064f558629d22ba" - opBenchmark(b, opSub, x, y) + opBenchmark(b, vm.OpSub, x, y) } func BenchmarkOpSub256(b *testing.B) { x := "4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37" y := "97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e" - opBenchmark(b, opSub, x, y) + opBenchmark(b, vm.OpSub, x, y) } func BenchmarkOpMul(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opMul, x, y) + opBenchmark(b, vm.OpMul, x, y) } func BenchmarkOpDiv256(b *testing.B) { x := "ff3f9014f20db29ae04af2c2d265de17" y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611" - opBenchmark(b, opDiv, x, y) + opBenchmark(b, vm.OpDiv, x, y) } func BenchmarkOpDiv128(b *testing.B) { x := "fdedc7f10142ff97" y := "fbdfda0e2ce356173d1993d5f70a2b11" - opBenchmark(b, opDiv, x, y) + opBenchmark(b, vm.OpDiv, x, y) } func BenchmarkOpDiv64(b *testing.B) { x := "fcb34eb3" y := "f97180878e839129" - opBenchmark(b, opDiv, x, y) + opBenchmark(b, vm.OpDiv, x, y) } func BenchmarkOpSdiv(b *testing.B) { x := "ff3f9014f20db29ae04af2c2d265de17" y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611" - opBenchmark(b, opSdiv, x, y) + opBenchmark(b, vm.OpSdiv, x, y) } func BenchmarkOpMod(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opMod, x, y) + opBenchmark(b, vm.OpMod, x, y) } func BenchmarkOpSmod(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opSmod, x, y) + opBenchmark(b, vm.OpSmod, x, y) } func BenchmarkOpExp(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opExp, x, y) + opBenchmark(b, vm.OpExp, x, y) } func BenchmarkOpSignExtend(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opSignExtend, x, y) + opBenchmark(b, vm.OpSignExtend, x, y) } func BenchmarkOpLt(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opLt, x, y) + opBenchmark(b, vm.OpLt, x, y) } func BenchmarkOpGt(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opGt, x, y) + opBenchmark(b, vm.OpGt, x, y) } func BenchmarkOpSlt(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opSlt, x, y) + opBenchmark(b, vm.OpSlt, x, y) } func BenchmarkOpSgt(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opSgt, x, y) + opBenchmark(b, vm.OpSgt, x, y) } func BenchmarkOpEq(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opEq, x, y) + opBenchmark(b, vm.OpEq, x, y) } func BenchmarkOpEq2(b *testing.B) { x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe" - opBenchmark(b, opEq, x, y) + opBenchmark(b, vm.OpEq, x, y) } func BenchmarkOpAnd(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opAnd, x, y) + opBenchmark(b, vm.OpAnd, x, y) } func BenchmarkOpOr(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opOr, x, y) + opBenchmark(b, vm.OpOr, x, y) } func BenchmarkOpXor(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opXor, x, y) + opBenchmark(b, vm.OpXor, x, y) } func BenchmarkOpByte(b *testing.B) { x := alphabetSoup y := alphabetSoup - opBenchmark(b, opByte, x, y) + opBenchmark(b, vm.OpByte, x, y) } func BenchmarkOpAddmod(b *testing.B) { @@ -498,7 +499,7 @@ func BenchmarkOpAddmod(b *testing.B) { y := alphabetSoup z := alphabetSoup - opBenchmark(b, opAddmod, x, y, z) + opBenchmark(b, vm.OpAddmod, x, y, z) } func BenchmarkOpMulmod(b *testing.B) { @@ -506,53 +507,53 @@ func BenchmarkOpMulmod(b *testing.B) { y := alphabetSoup z := alphabetSoup - opBenchmark(b, opMulmod, x, y, z) + opBenchmark(b, vm.OpMulmod, x, y, z) } func BenchmarkOpSHL(b *testing.B) { x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" y := "ff" - opBenchmark(b, opSHL, x, y) + opBenchmark(b, vm.OpSHL, x, y) } func BenchmarkOpSHR(b *testing.B) { x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" y := "ff" - opBenchmark(b, opSHR, x, y) + opBenchmark(b, vm.OpSHR, x, y) } func BenchmarkOpSAR(b *testing.B) { x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" y := "ff" - opBenchmark(b, opSAR, x, y) + opBenchmark(b, vm.OpSAR, x, y) } func BenchmarkOpIsZero(b *testing.B) { x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" - opBenchmark(b, opIszero, x) + opBenchmark(b, vm.OpIszero, x) } func TestOpMstore(t *testing.T) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() - evmInterpreter = NewEVMInterpreter(env) + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() + mem = vm.NewMemory() + evmInterpreter = vm.NewEVMInterpreter(env) ) - env.interpreter = evmInterpreter + env.SetInterpreter(evmInterpreter) mem.Resize(64) pc := uint64(0) v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700" - stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v))) - stack.push(new(uint256.Int)) - opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) + stack.Push(new(uint256.Int).SetBytes(common.Hex2Bytes(v))) + stack.Push(new(uint256.Int)) + vm.OpMstore(&pc, evmInterpreter, &vm.ScopeContext{mem, stack, nil}) if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v { t.Fatalf("Mstore fail, got %v, expected %v", got, v) } - stack.push(new(uint256.Int).SetUint64(0x1)) - stack.push(new(uint256.Int)) - opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) + stack.Push(new(uint256.Int).SetUint64(0x1)) + stack.Push(new(uint256.Int)) + vm.OpMstore(&pc, evmInterpreter, &vm.ScopeContext{mem, stack, nil}) if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" { t.Fatalf("Mstore failed to overwrite previous value") } @@ -560,13 +561,13 @@ func TestOpMstore(t *testing.T) { func BenchmarkOpMstore(bench *testing.B) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() - evmInterpreter = NewEVMInterpreter(env) + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() + mem = vm.NewMemory() + evmInterpreter = vm.NewEVMInterpreter(env) ) - env.interpreter = evmInterpreter + env.SetInterpreter(evmInterpreter) mem.Resize(64) pc := uint64(0) memStart := new(uint256.Int) @@ -574,24 +575,24 @@ func BenchmarkOpMstore(bench *testing.B) { bench.ResetTimer() for i := 0; i < bench.N; i++ { - stack.push(value) - stack.push(memStart) - opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) + stack.Push(value) + stack.Push(memStart) + vm.OpMstore(&pc, evmInterpreter, &vm.ScopeContext{mem, stack, nil}) } } func TestOpTstore(t *testing.T) { var ( statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() - evmInterpreter = NewEVMInterpreter(env) + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, statedb, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() + mem = vm.NewMemory() + evmInterpreter = vm.NewEVMInterpreter(env) caller = common.Address{} to = common.Address{1} contractRef = contractRef{caller} - contract = NewContract(contractRef, AccountRef(to), new(big.Int), 0) - scopeContext = ScopeContext{mem, stack, contract} + contract = vm.NewContract(contractRef, vm.AccountRef(to), new(big.Int), 0) + scopeContext = vm.ScopeContext{mem, stack, contract} value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700") ) @@ -599,25 +600,25 @@ func TestOpTstore(t *testing.T) { statedb.CreateAccount(caller) statedb.CreateAccount(to) - env.interpreter = evmInterpreter + env.SetInterpreter(evmInterpreter) pc := uint64(0) // push the value to the stack - stack.push(new(uint256.Int).SetBytes(value)) + stack.Push(new(uint256.Int).SetBytes(value)) // push the location to the stack - stack.push(new(uint256.Int)) - opTstore(&pc, evmInterpreter, &scopeContext) + stack.Push(new(uint256.Int)) + vm.OpTstore(&pc, evmInterpreter, &scopeContext) // there should be no elements on the stack after TSTORE - if stack.len() != 0 { + if stack.Len() != 0 { t.Fatal("stack wrong size") } // push the location to the stack - stack.push(new(uint256.Int)) - opTload(&pc, evmInterpreter, &scopeContext) + stack.Push(new(uint256.Int)) + vm.OpTload(&pc, evmInterpreter, &scopeContext) // there should be one element on the stack after TLOAD - if stack.len() != 1 { + if stack.Len() != 1 { t.Fatal("stack wrong size") } - val := stack.peek() + val := stack.Peek() if !bytes.Equal(val.Bytes(), value) { t.Fatal("incorrect element read from transient storage") } @@ -625,21 +626,21 @@ func TestOpTstore(t *testing.T) { func BenchmarkOpKeccak256(bench *testing.B) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() - evmInterpreter = NewEVMInterpreter(env) + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() + mem = vm.NewMemory() + evmInterpreter = vm.NewEVMInterpreter(env) ) - env.interpreter = evmInterpreter + env.SetInterpreter(evmInterpreter) mem.Resize(32) pc := uint64(0) start := new(uint256.Int) bench.ResetTimer() for i := 0; i < bench.N; i++ { - stack.push(uint256.NewInt(32)) - stack.push(start) - opKeccak256(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) + stack.Push(uint256.NewInt(32)) + stack.Push(start) + vm.OpKeccak256(&pc, evmInterpreter, &vm.ScopeContext{mem, stack, nil}) } } @@ -701,11 +702,11 @@ func TestCreate2Addreses(t *testing.T) { codeHash := crypto.Keccak256(code) address := crypto.CreateAddress2(origin, salt, codeHash) /* - stack := newstack() + stack :=vm.Newstack() // salt, but we don't need that for this test - stack.push(big.NewInt(int64(len(code)))) //size - stack.push(big.NewInt(0)) // memstart - stack.push(big.NewInt(0)) // value + stack.Push(big.NewInt(int64(len(code)))) //size + stack.Push(big.NewInt(0)) // memstart + stack.Push(big.NewInt(0)) // value gas, _ := gasCreate2(params.GasTable{}, nil, nil, stack, nil, 0) fmt.Printf("Example %d\n* address `0x%x`\n* salt `0x%x`\n* init_code `0x%x`\n* gas (assuming no mem expansion): `%v`\n* result: `%s`\n\n", i,origin, salt, code, gas, address.String()) */ @@ -729,16 +730,16 @@ func TestRandom(t *testing.T) { {name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})}, } { var ( - env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + env = vm.NewEVM(vm.BlockContext{Random: &tt.random}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() pc = uint64(0) - evmInterpreter = env.interpreter + evmInterpreter = env.Interpreter() ) - opRandom(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) - if len(stack.data) != 1 { - t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data)) + vm.OpRandom(&pc, evmInterpreter, &vm.ScopeContext{nil, stack, nil}) + if len(stack.Data()) != 1 { + t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.Data())) } - actual := stack.pop() + actual := stack.Pop() expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.random.Bytes())) if overflow { t.Errorf("Testcase %v: invalid overflow", tt.name) @@ -770,17 +771,17 @@ func TestBlobHash(t *testing.T) { {name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil}, } { var ( - env = NewEVM(BlockContext{}, TxContext{BlobHashes: tt.hashes}, nil, params.TestChainConfig, Config{}) - stack = newstack() + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{BlobHashes: tt.hashes}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() pc = uint64(0) - evmInterpreter = env.interpreter + evmInterpreter = env.Interpreter() ) - stack.push(uint256.NewInt(tt.idx)) - opBlobHash(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) - if len(stack.data) != 1 { - t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data)) + stack.Push(uint256.NewInt(tt.idx)) + vm.OpBlobHash(&pc, evmInterpreter, &vm.ScopeContext{nil, stack, nil}) + if len(stack.Data()) != 1 { + t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.Data())) } - actual := stack.pop() + actual := stack.Pop() expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.expect.Bytes())) if overflow { t.Errorf("Testcase %v: invalid overflow", tt.name) @@ -873,14 +874,14 @@ func TestOpMCopy(t *testing.T) { }, } { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{}) + stack = vm.Newstack() pc = uint64(0) - evmInterpreter = env.interpreter + evmInterpreter = env.Interpreter() ) data := common.FromHex(strings.ReplaceAll(tc.pre, " ", "")) // Set pre - mem := NewMemory() + mem := vm.NewMemory() mem.Resize(uint64(len(data))) mem.Set(0, uint64(len(data)), data) // Push stack args @@ -888,38 +889,38 @@ func TestOpMCopy(t *testing.T) { src, _ := uint256.FromHex(tc.src) dst, _ := uint256.FromHex(tc.dst) - stack.push(len) - stack.push(src) - stack.push(dst) + stack.Push(len) + stack.Push(src) + stack.Push(dst) wantErr := (tc.wantGas == 0) // Calc mem expansion var memorySize uint64 - if memSize, overflow := memoryMcopy(stack); overflow { + if memSize, overflow := vm.MemoryMcopy(stack); overflow { if wantErr { continue } t.Errorf("overflow") } else { var overflow bool - if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { - t.Error(ErrGasUintOverflow) + if memorySize, overflow = math.SafeMul(vm.ToWordSize(memSize), 32); overflow { + t.Error(vm.ErrGasUintOverflow) } } // and the dynamic cost var haveGas uint64 - if dynamicCost, err := gasMcopy(env, nil, stack, mem, memorySize); err != nil { + if dynamicCost, err := vm.GasMcopy(env, nil, stack, mem, memorySize); err != nil { t.Error(err) } else { - haveGas = GasFastestStep + dynamicCost + haveGas = vm.GasFastestStep + dynamicCost } // Expand mem if memorySize > 0 { mem.Resize(memorySize) } // Do the copy - opMcopy(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) + vm.OpMcopy(&pc, evmInterpreter, &vm.ScopeContext{mem, stack, nil}) want := common.FromHex(strings.ReplaceAll(tc.want, " ", "")) - if have := mem.store; !bytes.Equal(want, have) { + if have := mem.GetStore(); !bytes.Equal(want, have) { t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have) } wantGas := tc.wantGas diff --git a/core/vm/interface.go b/core/vm/interface.go index 4f1424076f..25ea39c5f1 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -20,7 +20,6 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" ) @@ -88,7 +87,7 @@ type StateDB interface { Finalise(deleteEmptyObjects bool) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) SetTxContext(thash common.Hash, ti int) - Copy() *state.StateDB + Copy() StateDB IntermediateRoot(deleteEmptyObjects bool) common.Hash GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log TxIndex() int diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 28da2e80e6..687f7eb51f 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -84,7 +84,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter { var extraEips []int if len(evm.Config.ExtraEips) > 0 { // Deep-copy jumptable to prevent modification of opcodes in other tables - table = copyJumpTable(table) + table = CopyJumpTable(table) } for _, eip := range evm.Config.ExtraEips { if err := EnableEIP(eip, table); err != nil { @@ -128,7 +128,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( var ( op OpCode // current opcode mem = NewMemory() // bound memory - stack = newstack() // local stack + stack = Newstack() // local stack callContext = &ScopeContext{ Memory: mem, Stack: stack, @@ -178,7 +178,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // enough stack items available to perform the operation. op = contract.GetOp(pc) operation := in.table[op] - cost = operation.constantGas // For tracing + cost = operation.ConstantGas // For tracing // Validate stack if sLen := stack.len(); sLen < operation.minStack { return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack} @@ -202,7 +202,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( } // memory is expanded in words of 32 bytes. Gas // is also calculated in words. - if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { + if memorySize, overflow = math.SafeMul(ToWordSize(memSize), 32); overflow { return nil, ErrGasUintOverflow } } diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go index 96e681fccd..4fc3fac6db 100644 --- a/core/vm/interpreter_test.go +++ b/core/vm/interpreter_test.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package vm +package vm_test import ( "math/big" @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" ) @@ -38,8 +39,8 @@ var loopInterruptTests = []string{ func TestLoopInterrupt(t *testing.T) { address := common.BytesToAddress([]byte("contract")) - vmctx := BlockContext{ - Transfer: func(StateDB, common.Address, common.Address, *big.Int) {}, + vmctx := vm.BlockContext{ + Transfer: func(vm.StateDB, common.Address, common.Address, *big.Int) {}, } for i, tt := range loopInterruptTests { @@ -48,13 +49,13 @@ func TestLoopInterrupt(t *testing.T) { statedb.SetCode(address, common.Hex2Bytes(tt)) statedb.Finalise(true) - evm := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{}) + evm := vm.NewEVM(vmctx, vm.TxContext{}, statedb, params.AllEthashProtocolChanges, vm.Config{}) errChannel := make(chan error) timeout := make(chan bool) - go func(evm *EVM) { - _, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(big.Int)) + go func(evm *vm.EVM) { + _, _, err := evm.Call(vm.AccountRef(common.Address{}), address, nil, math.MaxUint64, new(big.Int)) errChannel <- err }(evm) diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index fb87258326..a27fd128fb 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -23,7 +23,7 @@ import ( ) type ( - executionFunc func(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) + ExecutionFunc func(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) gasFunc func(*EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64 // memorySizeFunc returns the required size, and whether the operation overflowed a uint64 memorySizeFunc func(*Stack) (size uint64, overflow bool) @@ -31,8 +31,8 @@ type ( type operation struct { // execute is the operation function - execute executionFunc - constantGas uint64 + execute ExecutionFunc + ConstantGas uint64 dynamicGas gasFunc // minStack tells how many stack items are required minStack int @@ -54,7 +54,7 @@ var ( istanbulInstructionSet = newIstanbulInstructionSet() berlinInstructionSet = newBerlinInstructionSet() londonInstructionSet = newLondonInstructionSet() - mergeInstructionSet = newMergeInstructionSet() + mergeInstructionSet = NewMergeInstructionSet() shanghaiInstructionSet = newShanghaiInstructionSet() cancunInstructionSet = newCancunInstructionSet() ) @@ -91,18 +91,18 @@ func newCancunInstructionSet() JumpTable { } func newShanghaiInstructionSet() JumpTable { - instructionSet := newMergeInstructionSet() + instructionSet := NewMergeInstructionSet() enable3855(&instructionSet) // PUSH0 instruction enable3860(&instructionSet) // Limit and meter initcode return validate(instructionSet) } -func newMergeInstructionSet() JumpTable { +func NewMergeInstructionSet() JumpTable { instructionSet := newLondonInstructionSet() instructionSet[PREVRANDAO] = &operation{ - execute: opRandom, - constantGas: GasQuickStep, + execute: OpRandom, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), } @@ -143,32 +143,32 @@ func newIstanbulInstructionSet() JumpTable { func newConstantinopleInstructionSet() JumpTable { instructionSet := newByzantiumInstructionSet() instructionSet[SHL] = &operation{ - execute: opSHL, - constantGas: GasFastestStep, + execute: OpSHL, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), } instructionSet[SHR] = &operation{ - execute: opSHR, - constantGas: GasFastestStep, + execute: OpSHR, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), } instructionSet[SAR] = &operation{ - execute: opSAR, - constantGas: GasFastestStep, + execute: OpSAR, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), } instructionSet[EXTCODEHASH] = &operation{ execute: opExtCodeHash, - constantGas: params.ExtcodeHashGasConstantinople, + ConstantGas: params.ExtcodeHashGasConstantinople, minStack: minStack(1, 1), maxStack: maxStack(1, 1), } instructionSet[CREATE2] = &operation{ execute: opCreate2, - constantGas: params.Create2Gas, + ConstantGas: params.Create2Gas, dynamicGas: gasCreate2, minStack: minStack(4, 1), maxStack: maxStack(4, 1), @@ -183,7 +183,7 @@ func newByzantiumInstructionSet() JumpTable { instructionSet := newSpuriousDragonInstructionSet() instructionSet[STATICCALL] = &operation{ execute: opStaticCall, - constantGas: params.CallGasEIP150, + ConstantGas: params.CallGasEIP150, dynamicGas: gasStaticCall, minStack: minStack(6, 1), maxStack: maxStack(6, 1), @@ -191,13 +191,13 @@ func newByzantiumInstructionSet() JumpTable { } instructionSet[RETURNDATASIZE] = &operation{ execute: opReturnDataSize, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), } instructionSet[RETURNDATACOPY] = &operation{ execute: opReturnDataCopy, - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, dynamicGas: gasReturnDataCopy, minStack: minStack(3, 0), maxStack: maxStack(3, 0), @@ -223,13 +223,13 @@ func newSpuriousDragonInstructionSet() JumpTable { // EIP 150 a.k.a Tangerine Whistle func newTangerineWhistleInstructionSet() JumpTable { instructionSet := newHomesteadInstructionSet() - instructionSet[BALANCE].constantGas = params.BalanceGasEIP150 - instructionSet[EXTCODESIZE].constantGas = params.ExtcodeSizeGasEIP150 - instructionSet[SLOAD].constantGas = params.SloadGasEIP150 - instructionSet[EXTCODECOPY].constantGas = params.ExtcodeCopyBaseEIP150 - instructionSet[CALL].constantGas = params.CallGasEIP150 - instructionSet[CALLCODE].constantGas = params.CallGasEIP150 - instructionSet[DELEGATECALL].constantGas = params.CallGasEIP150 + instructionSet[BALANCE].ConstantGas = params.BalanceGasEIP150 + instructionSet[EXTCODESIZE].ConstantGas = params.ExtcodeSizeGasEIP150 + instructionSet[SLOAD].ConstantGas = params.SloadGasEIP150 + instructionSet[EXTCODECOPY].ConstantGas = params.ExtcodeCopyBaseEIP150 + instructionSet[CALL].ConstantGas = params.CallGasEIP150 + instructionSet[CALLCODE].ConstantGas = params.CallGasEIP150 + instructionSet[DELEGATECALL].ConstantGas = params.CallGasEIP150 return validate(instructionSet) } @@ -240,7 +240,7 @@ func newHomesteadInstructionSet() JumpTable { instructionSet[DELEGATECALL] = &operation{ execute: opDelegateCall, dynamicGas: gasDelegateCall, - constantGas: params.CallGasFrontier, + ConstantGas: params.CallGasFrontier, minStack: minStack(6, 1), maxStack: maxStack(6, 1), memorySize: memoryDelegateCall, @@ -254,195 +254,195 @@ func newFrontierInstructionSet() JumpTable { tbl := JumpTable{ STOP: { execute: opStop, - constantGas: 0, + ConstantGas: 0, minStack: minStack(0, 0), maxStack: maxStack(0, 0), }, ADD: { - execute: opAdd, - constantGas: GasFastestStep, + execute: OpAdd, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, MUL: { - execute: opMul, - constantGas: GasFastStep, + execute: OpMul, + ConstantGas: GasFastStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, SUB: { - execute: opSub, - constantGas: GasFastestStep, + execute: OpSub, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, DIV: { - execute: opDiv, - constantGas: GasFastStep, + execute: OpDiv, + ConstantGas: GasFastStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, SDIV: { - execute: opSdiv, - constantGas: GasFastStep, + execute: OpSdiv, + ConstantGas: GasFastStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, MOD: { - execute: opMod, - constantGas: GasFastStep, + execute: OpMod, + ConstantGas: GasFastStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, SMOD: { - execute: opSmod, - constantGas: GasFastStep, + execute: OpSmod, + ConstantGas: GasFastStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, ADDMOD: { - execute: opAddmod, - constantGas: GasMidStep, + execute: OpAddmod, + ConstantGas: GasMidStep, minStack: minStack(3, 1), maxStack: maxStack(3, 1), }, MULMOD: { - execute: opMulmod, - constantGas: GasMidStep, + execute: OpMulmod, + ConstantGas: GasMidStep, minStack: minStack(3, 1), maxStack: maxStack(3, 1), }, EXP: { - execute: opExp, + execute: OpExp, dynamicGas: gasExpFrontier, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, SIGNEXTEND: { - execute: opSignExtend, - constantGas: GasFastStep, + execute: OpSignExtend, + ConstantGas: GasFastStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, LT: { - execute: opLt, - constantGas: GasFastestStep, + execute: OpLt, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, GT: { - execute: opGt, - constantGas: GasFastestStep, + execute: OpGt, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, SLT: { - execute: opSlt, - constantGas: GasFastestStep, + execute: OpSlt, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, SGT: { - execute: opSgt, - constantGas: GasFastestStep, + execute: OpSgt, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, EQ: { - execute: opEq, - constantGas: GasFastestStep, + execute: OpEq, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, ISZERO: { - execute: opIszero, - constantGas: GasFastestStep, + execute: OpIszero, + ConstantGas: GasFastestStep, minStack: minStack(1, 1), maxStack: maxStack(1, 1), }, AND: { - execute: opAnd, - constantGas: GasFastestStep, + execute: OpAnd, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, XOR: { - execute: opXor, - constantGas: GasFastestStep, + execute: OpXor, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, OR: { - execute: opOr, - constantGas: GasFastestStep, + execute: OpOr, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, NOT: { execute: opNot, - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(1, 1), maxStack: maxStack(1, 1), }, BYTE: { - execute: opByte, - constantGas: GasFastestStep, + execute: OpByte, + ConstantGas: GasFastestStep, minStack: minStack(2, 1), maxStack: maxStack(2, 1), }, KECCAK256: { - execute: opKeccak256, - constantGas: params.Keccak256Gas, + execute: OpKeccak256, + ConstantGas: params.Keccak256Gas, dynamicGas: gasKeccak256, minStack: minStack(2, 1), maxStack: maxStack(2, 1), memorySize: memoryKeccak256, }, ADDRESS: { - execute: opAddress, - constantGas: GasQuickStep, + execute: OpAddress, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, BALANCE: { execute: opBalance, - constantGas: params.BalanceGasFrontier, + ConstantGas: params.BalanceGasFrontier, minStack: minStack(1, 1), maxStack: maxStack(1, 1), }, ORIGIN: { - execute: opOrigin, - constantGas: GasQuickStep, + execute: OpOrigin, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, CALLER: { execute: opCaller, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, CALLVALUE: { execute: opCallValue, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, CALLDATALOAD: { execute: opCallDataLoad, - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(1, 1), maxStack: maxStack(1, 1), }, CALLDATASIZE: { execute: opCallDataSize, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, CALLDATACOPY: { execute: opCallDataCopy, - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, dynamicGas: gasCallDataCopy, minStack: minStack(3, 0), maxStack: maxStack(3, 0), @@ -450,13 +450,13 @@ func newFrontierInstructionSet() JumpTable { }, CODESIZE: { execute: opCodeSize, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, CODECOPY: { execute: opCodeCopy, - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, dynamicGas: gasCodeCopy, minStack: minStack(3, 0), maxStack: maxStack(3, 0), @@ -464,19 +464,19 @@ func newFrontierInstructionSet() JumpTable { }, GASPRICE: { execute: opGasprice, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, EXTCODESIZE: { execute: opExtCodeSize, - constantGas: params.ExtcodeSizeGasFrontier, + ConstantGas: params.ExtcodeSizeGasFrontier, minStack: minStack(1, 1), maxStack: maxStack(1, 1), }, EXTCODECOPY: { execute: opExtCodeCopy, - constantGas: params.ExtcodeCopyBaseFrontier, + ConstantGas: params.ExtcodeCopyBaseFrontier, dynamicGas: gasExtCodeCopy, minStack: minStack(4, 0), maxStack: maxStack(4, 0), @@ -484,65 +484,65 @@ func newFrontierInstructionSet() JumpTable { }, BLOCKHASH: { execute: opBlockhash, - constantGas: GasExtStep, + ConstantGas: GasExtStep, minStack: minStack(1, 1), maxStack: maxStack(1, 1), }, COINBASE: { execute: opCoinbase, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, TIMESTAMP: { execute: opTimestamp, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, NUMBER: { execute: opNumber, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, DIFFICULTY: { execute: opDifficulty, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, GASLIMIT: { execute: opGasLimit, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, POP: { execute: opPop, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(1, 0), maxStack: maxStack(1, 0), }, MLOAD: { execute: opMload, - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, dynamicGas: gasMLoad, minStack: minStack(1, 1), maxStack: maxStack(1, 1), memorySize: memoryMLoad, }, MSTORE: { - execute: opMstore, - constantGas: GasFastestStep, + execute: OpMstore, + ConstantGas: GasFastestStep, dynamicGas: gasMStore, minStack: minStack(2, 0), maxStack: maxStack(2, 0), memorySize: memoryMStore, }, MSTORE8: { - execute: opMstore8, - constantGas: GasFastestStep, + execute: OpMstore8, + ConstantGas: GasFastestStep, dynamicGas: gasMStore8, memorySize: memoryMStore8, minStack: minStack(2, 0), @@ -550,7 +550,7 @@ func newFrontierInstructionSet() JumpTable { }, SLOAD: { execute: opSload, - constantGas: params.SloadGasFrontier, + ConstantGas: params.SloadGasFrontier, minStack: minStack(1, 1), maxStack: maxStack(1, 1), }, @@ -562,421 +562,421 @@ func newFrontierInstructionSet() JumpTable { }, JUMP: { execute: opJump, - constantGas: GasMidStep, + ConstantGas: GasMidStep, minStack: minStack(1, 0), maxStack: maxStack(1, 0), }, JUMPI: { execute: opJumpi, - constantGas: GasSlowStep, + ConstantGas: GasSlowStep, minStack: minStack(2, 0), maxStack: maxStack(2, 0), }, PC: { execute: opPc, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, MSIZE: { execute: opMsize, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, GAS: { execute: opGas, - constantGas: GasQuickStep, + ConstantGas: GasQuickStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, JUMPDEST: { execute: opJumpdest, - constantGas: params.JumpdestGas, + ConstantGas: params.JumpdestGas, minStack: minStack(0, 0), maxStack: maxStack(0, 0), }, PUSH1: { execute: opPush1, - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH2: { execute: makePush(2, 2), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH3: { execute: makePush(3, 3), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH4: { execute: makePush(4, 4), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH5: { execute: makePush(5, 5), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH6: { execute: makePush(6, 6), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH7: { execute: makePush(7, 7), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH8: { execute: makePush(8, 8), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH9: { execute: makePush(9, 9), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH10: { execute: makePush(10, 10), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH11: { execute: makePush(11, 11), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH12: { execute: makePush(12, 12), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH13: { execute: makePush(13, 13), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH14: { execute: makePush(14, 14), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH15: { execute: makePush(15, 15), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH16: { execute: makePush(16, 16), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH17: { execute: makePush(17, 17), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH18: { execute: makePush(18, 18), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH19: { execute: makePush(19, 19), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH20: { execute: makePush(20, 20), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH21: { execute: makePush(21, 21), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH22: { execute: makePush(22, 22), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH23: { execute: makePush(23, 23), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH24: { execute: makePush(24, 24), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH25: { execute: makePush(25, 25), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH26: { execute: makePush(26, 26), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH27: { execute: makePush(27, 27), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH28: { execute: makePush(28, 28), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH29: { execute: makePush(29, 29), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH30: { execute: makePush(30, 30), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH31: { execute: makePush(31, 31), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, PUSH32: { execute: makePush(32, 32), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minStack(0, 1), maxStack: maxStack(0, 1), }, DUP1: { execute: makeDup(1), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(1), maxStack: maxDupStack(1), }, DUP2: { execute: makeDup(2), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(2), maxStack: maxDupStack(2), }, DUP3: { execute: makeDup(3), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(3), maxStack: maxDupStack(3), }, DUP4: { execute: makeDup(4), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(4), maxStack: maxDupStack(4), }, DUP5: { execute: makeDup(5), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(5), maxStack: maxDupStack(5), }, DUP6: { execute: makeDup(6), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(6), maxStack: maxDupStack(6), }, DUP7: { execute: makeDup(7), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(7), maxStack: maxDupStack(7), }, DUP8: { execute: makeDup(8), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(8), maxStack: maxDupStack(8), }, DUP9: { execute: makeDup(9), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(9), maxStack: maxDupStack(9), }, DUP10: { execute: makeDup(10), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(10), maxStack: maxDupStack(10), }, DUP11: { execute: makeDup(11), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(11), maxStack: maxDupStack(11), }, DUP12: { execute: makeDup(12), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(12), maxStack: maxDupStack(12), }, DUP13: { execute: makeDup(13), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(13), maxStack: maxDupStack(13), }, DUP14: { execute: makeDup(14), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(14), maxStack: maxDupStack(14), }, DUP15: { execute: makeDup(15), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(15), maxStack: maxDupStack(15), }, DUP16: { execute: makeDup(16), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minDupStack(16), maxStack: maxDupStack(16), }, SWAP1: { execute: makeSwap(1), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(2), maxStack: maxSwapStack(2), }, SWAP2: { execute: makeSwap(2), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(3), maxStack: maxSwapStack(3), }, SWAP3: { execute: makeSwap(3), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(4), maxStack: maxSwapStack(4), }, SWAP4: { execute: makeSwap(4), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(5), maxStack: maxSwapStack(5), }, SWAP5: { execute: makeSwap(5), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(6), maxStack: maxSwapStack(6), }, SWAP6: { execute: makeSwap(6), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(7), maxStack: maxSwapStack(7), }, SWAP7: { execute: makeSwap(7), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(8), maxStack: maxSwapStack(8), }, SWAP8: { execute: makeSwap(8), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(9), maxStack: maxSwapStack(9), }, SWAP9: { execute: makeSwap(9), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(10), maxStack: maxSwapStack(10), }, SWAP10: { execute: makeSwap(10), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(11), maxStack: maxSwapStack(11), }, SWAP11: { execute: makeSwap(11), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(12), maxStack: maxSwapStack(12), }, SWAP12: { execute: makeSwap(12), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(13), maxStack: maxSwapStack(13), }, SWAP13: { execute: makeSwap(13), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(14), maxStack: maxSwapStack(14), }, SWAP14: { execute: makeSwap(14), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(15), maxStack: maxSwapStack(15), }, SWAP15: { execute: makeSwap(15), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(16), maxStack: maxSwapStack(16), }, SWAP16: { execute: makeSwap(16), - constantGas: GasFastestStep, + ConstantGas: GasFastestStep, minStack: minSwapStack(17), maxStack: maxSwapStack(17), }, @@ -1017,7 +1017,7 @@ func newFrontierInstructionSet() JumpTable { }, CREATE: { execute: opCreate, - constantGas: params.CreateGas, + ConstantGas: params.CreateGas, dynamicGas: gasCreate, minStack: minStack(3, 1), maxStack: maxStack(3, 1), @@ -1025,7 +1025,7 @@ func newFrontierInstructionSet() JumpTable { }, CALL: { execute: opCall, - constantGas: params.CallGasFrontier, + ConstantGas: params.CallGasFrontier, dynamicGas: gasCall, minStack: minStack(7, 1), maxStack: maxStack(7, 1), @@ -1033,7 +1033,7 @@ func newFrontierInstructionSet() JumpTable { }, CALLCODE: { execute: opCallCode, - constantGas: params.CallGasFrontier, + ConstantGas: params.CallGasFrontier, dynamicGas: gasCallCode, minStack: minStack(7, 1), maxStack: maxStack(7, 1), @@ -1064,7 +1064,7 @@ func newFrontierInstructionSet() JumpTable { return validate(tbl) } -func copyJumpTable(source *JumpTable) *JumpTable { +func CopyJumpTable(source *JumpTable) *JumpTable { dest := *source for i, op := range source { if op != nil { diff --git a/core/vm/jump_table_export.go b/core/vm/jump_table_export.go index b74109da0a..52b86ae448 100644 --- a/core/vm/jump_table_export.go +++ b/core/vm/jump_table_export.go @@ -35,7 +35,7 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) { case rules.IsShanghai: return newShanghaiInstructionSet(), nil case rules.IsMerge: - return newMergeInstructionSet(), nil + return NewMergeInstructionSet(), nil case rules.IsLondon: return newLondonInstructionSet(), nil case rules.IsBerlin: @@ -72,5 +72,5 @@ func (op *operation) HasCost() bool { // However, go-lang does now allow that. So we'll just check some other // 'indicators' that this is an invalid op. Alas, STOP is impossible to // filter out - return op.dynamicGas != nil || op.constantGas != 0 + return op.dynamicGas != nil || op.ConstantGas != 0 } diff --git a/core/vm/jump_table_test.go b/core/vm/jump_table_test.go index f67915fff3..dbd63ac952 100644 --- a/core/vm/jump_table_test.go +++ b/core/vm/jump_table_test.go @@ -14,22 +14,23 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package vm +package vm_test import ( "testing" + "github.com/ethereum/go-ethereum/core/vm" "github.com/stretchr/testify/require" ) // TestJumpTableCopy tests that deep copy is necessery to prevent modify shared jump table func TestJumpTableCopy(t *testing.T) { - tbl := newMergeInstructionSet() - require.Equal(t, uint64(0), tbl[SLOAD].constantGas) + tbl := vm.NewMergeInstructionSet() + require.Equal(t, uint64(0), tbl[vm.SLOAD].ConstantGas) // a deep copy won't modify the shared jump table - deepCopy := copyJumpTable(&tbl) - deepCopy[SLOAD].constantGas = 100 - require.Equal(t, uint64(100), deepCopy[SLOAD].constantGas) - require.Equal(t, uint64(0), tbl[SLOAD].constantGas) + deepCopy := vm.CopyJumpTable(&tbl) + deepCopy[vm.SLOAD].ConstantGas = 100 + require.Equal(t, uint64(100), deepCopy[vm.SLOAD].ConstantGas) + require.Equal(t, uint64(0), tbl[vm.SLOAD].ConstantGas) } diff --git a/core/vm/memory.go b/core/vm/memory.go index e0202fd7c0..b4f8aa29f1 100644 --- a/core/vm/memory.go +++ b/core/vm/memory.go @@ -114,3 +114,7 @@ func (m *Memory) Copy(dst, src, len uint64) { } copy(m.store[dst:], m.store[src:src+len]) } + +func (m *Memory) GetStore() []byte { + return m.store +} diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go index 61a910a03d..19bd8697e1 100644 --- a/core/vm/memory_table.go +++ b/core/vm/memory_table.go @@ -48,7 +48,7 @@ func memoryMStore(stack *Stack) (uint64, bool) { return calcMemSize64WithUint(stack.Back(0), 32) } -func memoryMcopy(stack *Stack) (uint64, bool) { +func MemoryMcopy(stack *Stack) (uint64, bool) { mStart := stack.Back(0) // stack[0]: dest if stack.Back(1).Gt(mStart) { mStart = stack.Back(1) // stack[1]: source diff --git a/core/vm/memory_test.go b/core/vm/memory_test.go index ba36f8023c..5686c7c24e 100644 --- a/core/vm/memory_test.go +++ b/core/vm/memory_test.go @@ -1,4 +1,4 @@ -package vm +package vm_test import ( "bytes" @@ -6,6 +6,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" ) func TestMemoryCopy(t *testing.T) { @@ -53,7 +54,7 @@ func TestMemoryCopy(t *testing.T) { "11", }, } { - m := NewMemory() + m := vm.NewMemory() // Clean spaces data := common.FromHex(strings.ReplaceAll(tc.pre, " ", "")) // Set pre @@ -62,7 +63,7 @@ func TestMemoryCopy(t *testing.T) { // Do the copy m.Copy(tc.dst, tc.src, tc.len) want := common.FromHex(strings.ReplaceAll(tc.want, " ", "")) - if have := m.store; !bytes.Equal(want, have) { + if have := m.GetStore(); !bytes.Equal(want, have) { t.Errorf("case %d: want: %#x\nhave: %#x\n", i, want, have) } } diff --git a/core/vm/operations_acl.go b/core/vm/operations_acl.go index 04c6409ebd..59d19dac48 100644 --- a/core/vm/operations_acl.go +++ b/core/vm/operations_acl.go @@ -129,7 +129,7 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo if !evm.StateDB.AddressInAccessList(addr) { evm.StateDB.AddAddressToAccessList(addr) var overflow bool - // We charge (cold-warm), since 'warm' is already charged as constantGas + // We charge (cold-warm), since 'warm' is already charged as ConstantGas if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow { return 0, ErrGasUintOverflow } @@ -151,7 +151,7 @@ func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Mem if !evm.StateDB.AddressInAccessList(addr) { // If the caller cannot afford the cost, this change will be rolled back evm.StateDB.AddAddressToAccessList(addr) - // The warm storage read cost is already charged as constantGas + // The warm storage read cost is already charged as ConstantGas return params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929, nil } return 0, nil diff --git a/core/vm/stack.go b/core/vm/stack.go index e1a957e244..fbcf8c4676 100644 --- a/core/vm/stack.go +++ b/core/vm/stack.go @@ -35,7 +35,7 @@ type Stack struct { data []uint256.Int } -func newstack() *Stack { +func Newstack() *Stack { return stackPool.Get().(*Stack) } @@ -80,3 +80,27 @@ func (st *Stack) peek() *uint256.Int { func (st *Stack) Back(n int) *uint256.Int { return &st.data[st.len()-n-1] } + +func (st *Stack) Push(d *uint256.Int) { + st.push(d) +} + +func (st *Stack) Pop() (ret uint256.Int) { + return st.pop() +} + +func (st *Stack) Len() int { + return st.len() +} + +func (st *Stack) Swap(n int) { + st.swap(n) +} + +func (st *Stack) Dup(n int) { + st.dup(n) +} + +func (st *Stack) Peek() *uint256.Int { + return st.peek() +} diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 867c112546..f2cc5e15e4 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -184,7 +184,7 @@ type txTraceResult struct { // blockTraceTask represents a single block trace task when an entire chain is // being traced. type blockTraceTask struct { - statedb *state.StateDB // Intermediate state prepped for tracing + statedb vm.StateDB // Intermediate state prepped for tracing block *types.Block // Block to trace the transactions from release StateReleaseFunc // The function to release the held resource for this task results []*txTraceResult // Trace results produced by the task @@ -201,8 +201,8 @@ type blockTraceResult struct { // txTraceTask represents a single transaction trace task when an entire block // is being traced. type txTraceTask struct { - statedb *state.StateDB // Intermediate state prepped for tracing - index int // Transaction offset in the block + statedb vm.StateDB // Intermediate state prepped for tracing + index int // Transaction offset in the block } // TraceChain returns the structured logs created during the execution of EVM diff --git a/miner/worker.go b/miner/worker.go index 938d739a49..dfa6225305 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -212,7 +212,7 @@ type worker struct { snapshotMu sync.RWMutex // The lock used to protect the snapshots below snapshotBlock *types.Block snapshotReceipts types.Receipts - snapshotState *state.StateDB + snapshotState vm.StateDB // atomic status counters running atomic.Bool // The indicator whether the consensus engine is running or not.