Use interface as Copy() result

This commit is contained in:
codchen 2023-10-20 14:00:37 +08:00
parent 16a8208f36
commit d04ef5cf81
27 changed files with 753 additions and 714 deletions

View file

@ -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,

View file

@ -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 {

View file

@ -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++

View file

@ -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 <http://www.gnu.org/licenses/>.
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)
}

View file

@ -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
}

View file

@ -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)
}

View file

@ -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
}

View file

@ -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 <http://www.gnu.org/licenses/>.
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)
}
}

View file

@ -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),
}

View file

@ -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) {

View file

@ -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
}

View file

@ -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 <http://www.gnu.org/licenses/>.
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
}

View file

@ -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) {

View file

@ -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 <http://www.gnu.org/licenses/>.
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

View file

@ -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

View file

@ -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
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
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)

File diff suppressed because it is too large Load diff

View file

@ -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
}

View file

@ -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 <http://www.gnu.org/licenses/>.
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)
}

View file

@ -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
}

View file

@ -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

View file

@ -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)
}
}

View file

@ -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

View file

@ -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()
}

View file

@ -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,7 +201,7 @@ 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
statedb vm.StateDB // Intermediate state prepped for tracing
index int // Transaction offset in the block
}

View file

@ -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.