mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
Use interface as Copy() result
This commit is contained in:
parent
16a8208f36
commit
d04ef5cf81
27 changed files with 753 additions and 714 deletions
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"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.
|
// Copy creates a deep, independent copy of the state.
|
||||||
// Snapshots of the copied state cannot be applied to the copy.
|
// 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
|
// Copy all the basic fields, initialize the memory ones
|
||||||
state := &StateDB{
|
state := &StateDB{
|
||||||
db: s.db,
|
db: s.db,
|
||||||
|
|
|
||||||
|
|
@ -181,16 +181,16 @@ func TestCopy(t *testing.T) {
|
||||||
// modify all in memory
|
// modify all in memory
|
||||||
for i := byte(0); i < 255; i++ {
|
for i := byte(0); i < 255; i++ {
|
||||||
origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
copyObj := copy.(*StateDB).GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
ccopyObj := ccopy.(*StateDB).GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
|
|
||||||
origObj.AddBalance(big.NewInt(2 * int64(i)))
|
origObj.AddBalance(big.NewInt(2 * int64(i)))
|
||||||
copyObj.AddBalance(big.NewInt(3 * int64(i)))
|
copyObj.AddBalance(big.NewInt(3 * int64(i)))
|
||||||
ccopyObj.AddBalance(big.NewInt(4 * int64(i)))
|
ccopyObj.AddBalance(big.NewInt(4 * int64(i)))
|
||||||
|
|
||||||
orig.updateStateObject(origObj)
|
orig.updateStateObject(origObj)
|
||||||
copy.updateStateObject(copyObj)
|
copy.(*StateDB).updateStateObject(copyObj)
|
||||||
ccopy.updateStateObject(copyObj)
|
ccopy.(*StateDB).updateStateObject(copyObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalise the changes on all concurrently
|
// Finalise the changes on all concurrently
|
||||||
|
|
@ -202,15 +202,15 @@ func TestCopy(t *testing.T) {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(3)
|
wg.Add(3)
|
||||||
go finalise(&wg, orig)
|
go finalise(&wg, orig)
|
||||||
go finalise(&wg, copy)
|
go finalise(&wg, copy.(*StateDB))
|
||||||
go finalise(&wg, ccopy)
|
go finalise(&wg, ccopy.(*StateDB))
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
// Verify that the three states have been updated independently
|
// Verify that the three states have been updated independently
|
||||||
for i := byte(0); i < 255; i++ {
|
for i := byte(0); i < 255; i++ {
|
||||||
origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
origObj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
copyObj := copy.(*StateDB).GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
ccopyObj := ccopy.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 {
|
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)
|
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
|
// Check the copy
|
||||||
// Make a copy
|
// Make a copy
|
||||||
state = stateCopy1
|
state = stateCopy1.(*StateDB)
|
||||||
verifyAddrs("aa", "bb")
|
verifyAddrs("aa", "bb")
|
||||||
verifySlots("bb", "01", "02")
|
verifySlots("bb", "01", "02")
|
||||||
if got, exp := len(state.accessList.addresses), 2; got != exp {
|
if got, exp := len(state.accessList.addresses), 2; got != exp {
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,16 @@ const (
|
||||||
set7BitsMask = uint16(0b111_1111)
|
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
|
// An unset bit means the byte is an opcode, a set bit means
|
||||||
// it's data (i.e. argument of PUSHxx).
|
// 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)
|
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)
|
a := flag << (pos % 8)
|
||||||
bits[pos/8] |= byte(a)
|
bits[pos/8] |= byte(a)
|
||||||
if b := byte(a >> 8); b != 0 {
|
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))
|
a := byte(0xFF << (pos % 8))
|
||||||
bits[pos/8] |= a
|
bits[pos/8] |= a
|
||||||
bits[pos/8+1] = ^a
|
bits[pos/8+1] = ^a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bits bitvec) set16(pos uint64) {
|
func (bits Bitvec) set16(pos uint64) {
|
||||||
a := byte(0xFF << (pos % 8))
|
a := byte(0xFF << (pos % 8))
|
||||||
bits[pos/8] |= a
|
bits[pos/8] |= a
|
||||||
bits[pos/8+1] = 0xFF
|
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.
|
// 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
|
return (((*bits)[pos/8] >> (pos % 8)) & 1) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// codeBitmap collects data locations in code.
|
// CodeBitmap collects data locations in code.
|
||||||
func codeBitmap(code []byte) bitvec {
|
func CodeBitmap(code []byte) Bitvec {
|
||||||
// The bitmap is 4 bytes longer than necessary, in case the code
|
// The bitmap is 4 bytes longer than necessary, in case the code
|
||||||
// ends with a PUSH32, the algorithm will set bits on the
|
// ends with a PUSH32, the algorithm will set bits on the
|
||||||
// bitvector outside the bounds of the actual code.
|
// Bitvector outside the bounds of the actual code.
|
||||||
bits := make(bitvec, len(code)/8+1+4)
|
bits := make(Bitvec, len(code)/8+1+4)
|
||||||
return codeBitmapInternal(code, bits)
|
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
|
// It exists for the purpose of being able to run benchmark tests
|
||||||
// without dynamic allocations affecting the results.
|
// 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)); {
|
for pc := uint64(0); pc < uint64(len(code)); {
|
||||||
op := OpCode(code[pc])
|
op := OpCode(code[pc])
|
||||||
pc++
|
pc++
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,13 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package vm
|
package vm_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -29,30 +30,30 @@ func TestJumpDestAnalysis(t *testing.T) {
|
||||||
exp byte
|
exp byte
|
||||||
which int
|
which int
|
||||||
}{
|
}{
|
||||||
{[]byte{byte(PUSH1), 0x01, 0x01, 0x01}, 0b0000_0010, 0},
|
{[]byte{byte(vm.PUSH1), 0x01, 0x01, 0x01}, 0b0000_0010, 0},
|
||||||
{[]byte{byte(PUSH1), byte(PUSH1), byte(PUSH1), byte(PUSH1)}, 0b0000_1010, 0},
|
{[]byte{byte(vm.PUSH1), byte(vm.PUSH1), byte(vm.PUSH1), byte(vm.PUSH1)}, 0b0000_1010, 0},
|
||||||
{[]byte{0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1)}, 0b0101_0100, 0},
|
{[]byte{0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.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(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(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 1},
|
{[]byte{byte(vm.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(vm.PUSH2), byte(vm.PUSH2), byte(vm.PUSH2), 0x01, 0x01, 0x01}, 0b1100_0000, 0},
|
||||||
{[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(PUSH2), 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1},
|
{[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(vm.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(vm.PUSH3), 0x01, 0x01, 0x01, byte(vm.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{byte(vm.PUSH3), 0x01, 0x01, 0x01, byte(vm.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(vm.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{0x01, byte(vm.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(vm.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(vm.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(vm.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(vm.PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(vm.PUSH1), 0x01}, 0b1111_1110, 0},
|
||||||
{[]byte{byte(PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(PUSH1), 0x01}, 0b0000_0101, 1},
|
{[]byte{byte(vm.PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(vm.PUSH1), 0x01}, 0b0000_0101, 1},
|
||||||
{[]byte{byte(PUSH32)}, 0b1111_1110, 0},
|
{[]byte{byte(vm.PUSH32)}, 0b1111_1110, 0},
|
||||||
{[]byte{byte(PUSH32)}, 0b1111_1111, 1},
|
{[]byte{byte(vm.PUSH32)}, 0b1111_1111, 1},
|
||||||
{[]byte{byte(PUSH32)}, 0b1111_1111, 2},
|
{[]byte{byte(vm.PUSH32)}, 0b1111_1111, 2},
|
||||||
{[]byte{byte(PUSH32)}, 0b1111_1111, 3},
|
{[]byte{byte(vm.PUSH32)}, 0b1111_1111, 3},
|
||||||
{[]byte{byte(PUSH32)}, 0b0000_0001, 4},
|
{[]byte{byte(vm.PUSH32)}, 0b0000_0001, 4},
|
||||||
}
|
}
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
ret := codeBitmap(test.code)
|
ret := vm.CodeBitmap(test.code)
|
||||||
if ret[test.which] != test.exp {
|
if ret[test.which] != test.exp {
|
||||||
t.Fatalf("test %d: expected %x, got %02x", i, test.exp, ret[test.which])
|
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.SetBytes(analysisCodeSize)
|
||||||
bench.ResetTimer()
|
bench.ResetTimer()
|
||||||
for i := 0; i < bench.N; i++ {
|
for i := 0; i < bench.N; i++ {
|
||||||
codeBitmap(code)
|
vm.CodeBitmap(code)
|
||||||
}
|
}
|
||||||
bench.StopTimer()
|
bench.StopTimer()
|
||||||
}
|
}
|
||||||
|
|
@ -83,27 +84,27 @@ func BenchmarkJumpdestHashing_1200k(bench *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkJumpdestOpAnalysis(bench *testing.B) {
|
func BenchmarkJumpdestOpAnalysis(bench *testing.B) {
|
||||||
var op OpCode
|
var op vm.OpCode
|
||||||
bencher := func(b *testing.B) {
|
bencher := func(b *testing.B) {
|
||||||
code := make([]byte, analysisCodeSize)
|
code := make([]byte, analysisCodeSize)
|
||||||
b.SetBytes(analysisCodeSize)
|
b.SetBytes(analysisCodeSize)
|
||||||
for i := range code {
|
for i := range code {
|
||||||
code[i] = byte(op)
|
code[i] = byte(op)
|
||||||
}
|
}
|
||||||
bits := make(bitvec, len(code)/8+1+4)
|
bits := make(vm.Bitvec, len(code)/8+1+4)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
for j := range bits {
|
for j := range bits {
|
||||||
bits[j] = 0
|
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)
|
bench.Run(op.String(), bencher)
|
||||||
}
|
}
|
||||||
op = JUMPDEST
|
op = vm.JUMPDEST
|
||||||
bench.Run(op.String(), bencher)
|
bench.Run(op.String(), bencher)
|
||||||
op = STOP
|
op = vm.STOP
|
||||||
bench.Run(op.String(), bencher)
|
bench.Run(op.String(), bencher)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,8 @@ func getData(data []byte, start uint64, size uint64) []byte {
|
||||||
return common.RightPadBytes(data[start:end], int(size))
|
return common.RightPadBytes(data[start:end], int(size))
|
||||||
}
|
}
|
||||||
|
|
||||||
// toWordSize returns the ceiled word size required for memory expansion.
|
// ToWordSize returns the ceiled word size required for memory expansion.
|
||||||
func toWordSize(size uint64) uint64 {
|
func ToWordSize(size uint64) uint64 {
|
||||||
if size > math.MaxUint64-31 {
|
if size > math.MaxUint64-31 {
|
||||||
return math.MaxUint64/32 + 1
|
return math.MaxUint64/32 + 1
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,8 @@ type Contract struct {
|
||||||
caller ContractRef
|
caller ContractRef
|
||||||
self ContractRef
|
self ContractRef
|
||||||
|
|
||||||
jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis.
|
jumpdests map[common.Hash]Bitvec // Aggregated result of JUMPDEST analysis.
|
||||||
analysis bitvec // Locally cached result of JUMPDEST analysis
|
analysis Bitvec // Locally cached result of JUMPDEST analysis
|
||||||
|
|
||||||
Code []byte
|
Code []byte
|
||||||
CodeHash common.Hash
|
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.
|
// Reuse JUMPDEST analysis from parent context if available.
|
||||||
c.jumpdests = parent.jumpdests
|
c.jumpdests = parent.jumpdests
|
||||||
} else {
|
} 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
|
// 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 {
|
if !exist {
|
||||||
// Do the analysis and save in parent context
|
// Do the analysis and save in parent context
|
||||||
// We do not need to store it in c.analysis
|
// We do not need to store it in c.analysis
|
||||||
analysis = codeBitmap(c.Code)
|
analysis = CodeBitmap(c.Code)
|
||||||
c.jumpdests[c.CodeHash] = analysis
|
c.jumpdests[c.CodeHash] = analysis
|
||||||
}
|
}
|
||||||
// Also stash it in current contract for faster access
|
// 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
|
// we don't have to recalculate it for every JUMP instruction in the execution
|
||||||
// However, we don't save it within the parent context
|
// However, we don't save it within the parent context
|
||||||
if c.analysis == nil {
|
if c.analysis == nil {
|
||||||
c.analysis = codeBitmap(c.Code)
|
c.analysis = CodeBitmap(c.Code)
|
||||||
}
|
}
|
||||||
return c.analysis.codeSegment(udest)
|
return c.analysis.codeSegment(udest)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"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/blake2b"
|
||||||
"github.com/ethereum/go-ethereum/crypto/bls12381"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/bn256"
|
"github.com/ethereum/go-ethereum/crypto/bn256"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -45,20 +45,20 @@ type PrecompiledContract interface {
|
||||||
// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
|
// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
|
||||||
// contracts used in the Frontier and Homestead releases.
|
// contracts used in the Frontier and Homestead releases.
|
||||||
var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
|
var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{1}): &ecrecover{},
|
common.BytesToAddress([]byte{1}): &Ecrecover{},
|
||||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
common.BytesToAddress([]byte{2}): &Sha256hash{},
|
||||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
common.BytesToAddress([]byte{3}): &Ripemd160hash{},
|
||||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
common.BytesToAddress([]byte{4}): &DataCopy{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum
|
// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum
|
||||||
// contracts used in the Byzantium release.
|
// contracts used in the Byzantium release.
|
||||||
var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
|
var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{1}): &ecrecover{},
|
common.BytesToAddress([]byte{1}): &Ecrecover{},
|
||||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
common.BytesToAddress([]byte{2}): &Sha256hash{},
|
||||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
common.BytesToAddress([]byte{3}): &Ripemd160hash{},
|
||||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
common.BytesToAddress([]byte{4}): &DataCopy{},
|
||||||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
|
common.BytesToAddress([]byte{5}): &BigModExp{Eip2565: false},
|
||||||
common.BytesToAddress([]byte{6}): &bn256AddByzantium{},
|
common.BytesToAddress([]byte{6}): &bn256AddByzantium{},
|
||||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{},
|
common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{},
|
||||||
common.BytesToAddress([]byte{8}): &bn256PairingByzantium{},
|
common.BytesToAddress([]byte{8}): &bn256PairingByzantium{},
|
||||||
|
|
@ -67,58 +67,58 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
|
||||||
// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
|
// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
|
||||||
// contracts used in the Istanbul release.
|
// contracts used in the Istanbul release.
|
||||||
var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
|
var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{1}): &ecrecover{},
|
common.BytesToAddress([]byte{1}): &Ecrecover{},
|
||||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
common.BytesToAddress([]byte{2}): &Sha256hash{},
|
||||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
common.BytesToAddress([]byte{3}): &Ripemd160hash{},
|
||||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
common.BytesToAddress([]byte{4}): &DataCopy{},
|
||||||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
|
common.BytesToAddress([]byte{5}): &BigModExp{Eip2565: false},
|
||||||
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
|
common.BytesToAddress([]byte{6}): &Bn256AddIstanbul{},
|
||||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
common.BytesToAddress([]byte{7}): &Bn256ScalarMulIstanbul{},
|
||||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
common.BytesToAddress([]byte{8}): &Bn256PairingIstanbul{},
|
||||||
common.BytesToAddress([]byte{9}): &blake2F{},
|
common.BytesToAddress([]byte{9}): &Blake2F{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum
|
// PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum
|
||||||
// contracts used in the Berlin release.
|
// contracts used in the Berlin release.
|
||||||
var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
|
var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{1}): &ecrecover{},
|
common.BytesToAddress([]byte{1}): &Ecrecover{},
|
||||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
common.BytesToAddress([]byte{2}): &Sha256hash{},
|
||||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
common.BytesToAddress([]byte{3}): &Ripemd160hash{},
|
||||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
common.BytesToAddress([]byte{4}): &DataCopy{},
|
||||||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
|
common.BytesToAddress([]byte{5}): &BigModExp{Eip2565: true},
|
||||||
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
|
common.BytesToAddress([]byte{6}): &Bn256AddIstanbul{},
|
||||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
common.BytesToAddress([]byte{7}): &Bn256ScalarMulIstanbul{},
|
||||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
common.BytesToAddress([]byte{8}): &Bn256PairingIstanbul{},
|
||||||
common.BytesToAddress([]byte{9}): &blake2F{},
|
common.BytesToAddress([]byte{9}): &Blake2F{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrecompiledContractsCancun contains the default set of pre-compiled Ethereum
|
// PrecompiledContractsCancun contains the default set of pre-compiled Ethereum
|
||||||
// contracts used in the Cancun release.
|
// contracts used in the Cancun release.
|
||||||
var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
|
var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{1}): &ecrecover{},
|
common.BytesToAddress([]byte{1}): &Ecrecover{},
|
||||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
common.BytesToAddress([]byte{2}): &Sha256hash{},
|
||||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
common.BytesToAddress([]byte{3}): &Ripemd160hash{},
|
||||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
common.BytesToAddress([]byte{4}): &DataCopy{},
|
||||||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
|
common.BytesToAddress([]byte{5}): &BigModExp{Eip2565: true},
|
||||||
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
|
common.BytesToAddress([]byte{6}): &Bn256AddIstanbul{},
|
||||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
common.BytesToAddress([]byte{7}): &Bn256ScalarMulIstanbul{},
|
||||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
common.BytesToAddress([]byte{8}): &Bn256PairingIstanbul{},
|
||||||
common.BytesToAddress([]byte{9}): &blake2F{},
|
common.BytesToAddress([]byte{9}): &Blake2F{},
|
||||||
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
|
common.BytesToAddress([]byte{0x0a}): &KzgPointEvaluation{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
|
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
|
||||||
// contracts specified in EIP-2537. These are exported for testing purposes.
|
// contracts specified in EIP-2537. These are exported for testing purposes.
|
||||||
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
|
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{10}): &bls12381G1Add{},
|
common.BytesToAddress([]byte{10}): &Bls12381G1Add{},
|
||||||
common.BytesToAddress([]byte{11}): &bls12381G1Mul{},
|
common.BytesToAddress([]byte{11}): &Bls12381G1Mul{},
|
||||||
common.BytesToAddress([]byte{12}): &bls12381G1MultiExp{},
|
common.BytesToAddress([]byte{12}): &Bls12381G1MultiExp{},
|
||||||
common.BytesToAddress([]byte{13}): &bls12381G2Add{},
|
common.BytesToAddress([]byte{13}): &Bls12381G2Add{},
|
||||||
common.BytesToAddress([]byte{14}): &bls12381G2Mul{},
|
common.BytesToAddress([]byte{14}): &Bls12381G2Mul{},
|
||||||
common.BytesToAddress([]byte{15}): &bls12381G2MultiExp{},
|
common.BytesToAddress([]byte{15}): &Bls12381G2MultiExp{},
|
||||||
common.BytesToAddress([]byte{16}): &bls12381Pairing{},
|
common.BytesToAddress([]byte{16}): &Bls12381Pairing{},
|
||||||
common.BytesToAddress([]byte{17}): &bls12381MapG1{},
|
common.BytesToAddress([]byte{17}): &Bls12381MapG1{},
|
||||||
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
|
common.BytesToAddress([]byte{18}): &Bls12381MapG2{},
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -179,18 +179,18 @@ func RunPrecompiledContract(p PrecompiledContract, evm *EVM, input []byte, suppl
|
||||||
}
|
}
|
||||||
|
|
||||||
// ECRECOVER implemented as a native contract.
|
// 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
|
return params.EcrecoverGas
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ecrecover) Run(_ *EVM, input []byte) ([]byte, error) {
|
func (c *Ecrecover) Run(_ *EVM, input []byte) ([]byte, error) {
|
||||||
const ecRecoverInputLength = 128
|
const ecRecoverInputLength = 128
|
||||||
|
|
||||||
input = common.RightPadBytes(input, ecRecoverInputLength)
|
input = common.RightPadBytes(input, ecRecoverInputLength)
|
||||||
// "input" is (hash, v, r, s), each 32 bytes
|
// "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])
|
r := new(big.Int).SetBytes(input[64:96])
|
||||||
s := new(big.Int).SetBytes(input[96:128])
|
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.
|
// SHA256 implemented as a native contract.
|
||||||
type sha256hash struct{}
|
type Sha256hash struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
// 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.
|
// 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
|
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)
|
h := sha256.Sum256(input)
|
||||||
return h[:], nil
|
return h[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RIPEMD160 implemented as a native contract.
|
// RIPEMD160 implemented as a native contract.
|
||||||
type ripemd160hash struct{}
|
type Ripemd160hash struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
// 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.
|
// 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
|
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 := ripemd160.New()
|
||||||
ripemd.Write(input)
|
ripemd.Write(input)
|
||||||
return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
|
return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// data copy implemented as a native contract.
|
// data copy implemented as a native contract.
|
||||||
type dataCopy struct{}
|
type DataCopy struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
// 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.
|
// 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
|
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
|
return common.CopyBytes(in), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bigModExp implements a native big integer exponential modular operation.
|
// BigModExp implements a native big integer exponential modular operation.
|
||||||
type bigModExp struct {
|
type BigModExp struct {
|
||||||
eip2565 bool
|
Eip2565 bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -313,7 +313,7 @@ func modexpMultComplexity(x *big.Int) *big.Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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 (
|
var (
|
||||||
baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
|
baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
|
||||||
expLen = new(big.Int).SetBytes(getData(input, 32, 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)))
|
adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
|
||||||
// Calculate the gas cost of the operation
|
// Calculate the gas cost of the operation
|
||||||
gas := new(big.Int).Set(math.BigMax(modLen, baseLen))
|
gas := new(big.Int).Set(math.BigMax(modLen, baseLen))
|
||||||
if c.eip2565 {
|
if c.Eip2565 {
|
||||||
// EIP-2565 has three changes
|
// EIP-2565 has three changes
|
||||||
// 1. Different multComplexity (inlined here)
|
// 1. Different multComplexity (inlined here)
|
||||||
// in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565):
|
// in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565):
|
||||||
|
|
@ -383,7 +383,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
|
||||||
return gas.Uint64()
|
return gas.Uint64()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bigModExp) Run(_ *EVM, input []byte) ([]byte, error) {
|
func (c *BigModExp) Run(_ *EVM, input []byte) ([]byte, error) {
|
||||||
var (
|
var (
|
||||||
baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
|
baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
|
||||||
expLen = new(big.Int).SetBytes(getData(input, 32, 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
|
// bn256Add implements a native elliptic curve point addition conforming to
|
||||||
// Istanbul consensus rules.
|
// Istanbul consensus rules.
|
||||||
type bn256AddIstanbul struct{}
|
type Bn256AddIstanbul struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
return params.Bn256AddGasIstanbul
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bn256AddIstanbul) Run(_ *EVM, input []byte) ([]byte, error) {
|
func (c *Bn256AddIstanbul) Run(_ *EVM, input []byte) ([]byte, error) {
|
||||||
return runBn256Add(input)
|
return runBn256Add(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -492,16 +492,16 @@ func runBn256ScalarMul(input []byte) ([]byte, error) {
|
||||||
return res.Marshal(), nil
|
return res.Marshal(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bn256ScalarMulIstanbul implements a native elliptic curve scalar
|
// Bn256ScalarMulIstanbul implements a native elliptic curve scalar
|
||||||
// multiplication conforming to Istanbul consensus rules.
|
// multiplication conforming to Istanbul consensus rules.
|
||||||
type bn256ScalarMulIstanbul struct{}
|
type Bn256ScalarMulIstanbul struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
return params.Bn256ScalarMulGasIstanbul
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *bn256ScalarMulIstanbul) Run(_ *EVM, input []byte) ([]byte, error) {
|
func (c *Bn256ScalarMulIstanbul) Run(_ *EVM, input []byte) ([]byte, error) {
|
||||||
return runBn256ScalarMul(input)
|
return runBn256ScalarMul(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -560,16 +560,16 @@ func runBn256Pairing(input []byte) ([]byte, error) {
|
||||||
return false32Byte, nil
|
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.
|
// conforming to Istanbul consensus rules.
|
||||||
type bn256PairingIstanbul struct{}
|
type Bn256PairingIstanbul struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
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)
|
return runBn256Pairing(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -586,40 +586,40 @@ func (c *bn256PairingByzantium) Run(_ *EVM, input []byte) ([]byte, error) {
|
||||||
return runBn256Pairing(input)
|
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
|
// If the input is malformed, we can't calculate the gas, return 0 and let the
|
||||||
// actual call choke and fault.
|
// actual call choke and fault.
|
||||||
if len(input) != blake2FInputLength {
|
if len(input) != Blake2FInputLength {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return uint64(binary.BigEndian.Uint32(input[0:4]))
|
return uint64(binary.BigEndian.Uint32(input[0:4]))
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
blake2FInputLength = 213
|
Blake2FInputLength = 213
|
||||||
blake2FFinalBlockBytes = byte(1)
|
Blake2FFinalBlockBytes = byte(1)
|
||||||
blake2FNonFinalBlockBytes = byte(0)
|
Blake2FNonFinalBlockBytes = byte(0)
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errBlake2FInvalidInputLength = errors.New("invalid input length")
|
ErrBlake2FInvalidInputLength = errors.New("invalid input length")
|
||||||
errBlake2FInvalidFinalFlag = errors.New("invalid final flag")
|
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)
|
// Make sure the input is valid (correct length and final flag)
|
||||||
if len(input) != blake2FInputLength {
|
if len(input) != Blake2FInputLength {
|
||||||
return nil, errBlake2FInvalidInputLength
|
return nil, ErrBlake2FInvalidInputLength
|
||||||
}
|
}
|
||||||
if input[212] != blake2FNonFinalBlockBytes && input[212] != blake2FFinalBlockBytes {
|
if input[212] != Blake2FNonFinalBlockBytes && input[212] != Blake2FFinalBlockBytes {
|
||||||
return nil, errBlake2FInvalidFinalFlag
|
return nil, ErrBlake2FInvalidFinalFlag
|
||||||
}
|
}
|
||||||
// Parse the input into the Blake2b call parameters
|
// Parse the input into the Blake2b call parameters
|
||||||
var (
|
var (
|
||||||
rounds = binary.BigEndian.Uint32(input[0:4])
|
rounds = binary.BigEndian.Uint32(input[0:4])
|
||||||
final = input[212] == blake2FFinalBlockBytes
|
final = input[212] == Blake2FFinalBlockBytes
|
||||||
|
|
||||||
h [8]uint64
|
h [8]uint64
|
||||||
m [16]uint64
|
m [16]uint64
|
||||||
|
|
@ -649,20 +649,20 @@ func (c *blake2F) Run(_ *EVM, input []byte) ([]byte, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errBLS12381InvalidInputLength = errors.New("invalid input length")
|
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")
|
errBLS12381G1PointSubgroup = errors.New("g1 point is not on correct subgroup")
|
||||||
errBLS12381G2PointSubgroup = errors.New("g2 point is not on correct subgroup")
|
errBLS12381G2PointSubgroup = errors.New("g2 point is not on correct subgroup")
|
||||||
)
|
)
|
||||||
|
|
||||||
// bls12381G1Add implements EIP-2537 G1Add precompile.
|
// Bls12381G1Add implements EIP-2537 G1Add precompile.
|
||||||
type bls12381G1Add struct{}
|
type Bls12381G1Add struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
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.
|
// 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).
|
// > 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).
|
// > 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
|
return g.EncodePoint(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bls12381G1Mul implements EIP-2537 G1Mul precompile.
|
// Bls12381G1Mul implements EIP-2537 G1Mul precompile.
|
||||||
type bls12381G1Mul struct{}
|
type Bls12381G1Mul struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
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.
|
// 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).
|
// > 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).
|
// > 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
|
return g.EncodePoint(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile.
|
// Bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile.
|
||||||
type bls12381G1MultiExp struct{}
|
type Bls12381G1MultiExp struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
// Calculate G1 point, scalar value pair length
|
||||||
k := len(input) / 160
|
k := len(input) / 160
|
||||||
if k == 0 {
|
if k == 0 {
|
||||||
|
|
@ -750,7 +750,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 {
|
||||||
return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000
|
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.
|
// 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).
|
// 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).
|
// 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
|
return g.EncodePoint(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bls12381G2Add implements EIP-2537 G2Add precompile.
|
// Bls12381G2Add implements EIP-2537 G2Add precompile.
|
||||||
type bls12381G2Add struct{}
|
type Bls12381G2Add struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
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.
|
// 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).
|
// > 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).
|
// > 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
|
return g.EncodePoint(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bls12381G2Mul implements EIP-2537 G2Mul precompile.
|
// Bls12381G2Mul implements EIP-2537 G2Mul precompile.
|
||||||
type bls12381G2Mul struct{}
|
type Bls12381G2Mul struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
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.
|
// 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).
|
// > 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).
|
// > 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
|
return g.EncodePoint(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile.
|
// Bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile.
|
||||||
type bls12381G2MultiExp struct{}
|
type Bls12381G2MultiExp struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
// Calculate G2 point, scalar value pair length
|
||||||
k := len(input) / 288
|
k := len(input) / 288
|
||||||
if k == 0 {
|
if k == 0 {
|
||||||
|
|
@ -881,7 +881,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 {
|
||||||
return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000
|
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
|
// 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).
|
// > 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).
|
// > 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
|
return g.EncodePoint(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bls12381Pairing implements EIP-2537 Pairing precompile.
|
// Bls12381Pairing implements EIP-2537 Pairing precompile.
|
||||||
type bls12381Pairing struct{}
|
type Bls12381Pairing struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
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.
|
// 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:
|
// > 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
|
// > - `128` bytes of G1 point encoding
|
||||||
|
|
@ -987,7 +987,7 @@ func decodeBLS12381FieldElement(in []byte) ([]byte, error) {
|
||||||
// check top bytes
|
// check top bytes
|
||||||
for i := 0; i < 16; i++ {
|
for i := 0; i < 16; i++ {
|
||||||
if in[i] != byte(0x00) {
|
if in[i] != byte(0x00) {
|
||||||
return nil, errBLS12381InvalidFieldElementTopBytes
|
return nil, errBLS12381InvalidFieldElementTOpBytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out := make([]byte, 48)
|
out := make([]byte, 48)
|
||||||
|
|
@ -995,15 +995,15 @@ func decodeBLS12381FieldElement(in []byte) ([]byte, error) {
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bls12381MapG1 implements EIP-2537 MapG1 precompile.
|
// Bls12381MapG1 implements EIP-2537 MapG1 precompile.
|
||||||
type bls12381MapG1 struct{}
|
type Bls12381MapG1 struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
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.
|
// 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.
|
// > 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.
|
// > 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
|
return g.EncodePoint(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bls12381MapG2 implements EIP-2537 MapG2 precompile.
|
// Bls12381MapG2 implements EIP-2537 MapG2 precompile.
|
||||||
type bls12381MapG2 struct{}
|
type Bls12381MapG2 struct{}
|
||||||
|
|
||||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
// 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
|
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.
|
// 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.
|
// > 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.
|
// > 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
|
return g.EncodePoint(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// kzgPointEvaluation implements the EIP-4844 point evaluation precompile.
|
// KzgPointEvaluation implements the EIP-4844 point evaluation precompile.
|
||||||
type kzgPointEvaluation struct{}
|
type KzgPointEvaluation struct{}
|
||||||
|
|
||||||
// RequiredGas estimates the gas required for running the point evaluation precompile.
|
// 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
|
return params.BlobTxPointEvaluationPrecompileGas
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1093,7 +1093,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Run executes the point evaluation precompile.
|
// 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 {
|
if len(input) != blobVerifyInputLength {
|
||||||
return nil, errBlobVerifyInvalidInputLength
|
return nil, errBlobVerifyInvalidInputLength
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package vm
|
package vm_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// precompiledTest defines the input/output pairs for precompiled contract tests.
|
// 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
|
// allPrecompiles does not map to the actual set of precompiles, as it also contains
|
||||||
// repriced versions of precompiles at certain slots
|
// repriced versions of precompiles at certain slots
|
||||||
var allPrecompiles = map[common.Address]PrecompiledContract{
|
var allPrecompiles = map[common.Address]vm.PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{1}): &ecrecover{},
|
common.BytesToAddress([]byte{1}): &vm.Ecrecover{},
|
||||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
common.BytesToAddress([]byte{2}): &vm.Sha256hash{},
|
||||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
common.BytesToAddress([]byte{3}): &vm.Ripemd160hash{},
|
||||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
common.BytesToAddress([]byte{4}): &vm.DataCopy{},
|
||||||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
|
common.BytesToAddress([]byte{5}): &vm.BigModExp{Eip2565: false},
|
||||||
common.BytesToAddress([]byte{0xf5}): &bigModExp{eip2565: true},
|
common.BytesToAddress([]byte{0xf5}): &vm.BigModExp{Eip2565: true},
|
||||||
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
|
common.BytesToAddress([]byte{6}): &vm.Bn256AddIstanbul{},
|
||||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
common.BytesToAddress([]byte{7}): &vm.Bn256ScalarMulIstanbul{},
|
||||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
common.BytesToAddress([]byte{8}): &vm.Bn256PairingIstanbul{},
|
||||||
common.BytesToAddress([]byte{9}): &blake2F{},
|
common.BytesToAddress([]byte{9}): &vm.Blake2F{},
|
||||||
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
|
common.BytesToAddress([]byte{0x0a}): &vm.KzgPointEvaluation{},
|
||||||
|
|
||||||
common.BytesToAddress([]byte{0x0f, 0x0a}): &bls12381G1Add{},
|
common.BytesToAddress([]byte{0x0f, 0x0a}): &vm.Bls12381G1Add{},
|
||||||
common.BytesToAddress([]byte{0x0f, 0x0b}): &bls12381G1Mul{},
|
common.BytesToAddress([]byte{0x0f, 0x0b}): &vm.Bls12381G1Mul{},
|
||||||
common.BytesToAddress([]byte{0x0f, 0x0c}): &bls12381G1MultiExp{},
|
common.BytesToAddress([]byte{0x0f, 0x0c}): &vm.Bls12381G1MultiExp{},
|
||||||
common.BytesToAddress([]byte{0x0f, 0x0d}): &bls12381G2Add{},
|
common.BytesToAddress([]byte{0x0f, 0x0d}): &vm.Bls12381G2Add{},
|
||||||
common.BytesToAddress([]byte{0x0f, 0x0e}): &bls12381G2Mul{},
|
common.BytesToAddress([]byte{0x0f, 0x0e}): &vm.Bls12381G2Mul{},
|
||||||
common.BytesToAddress([]byte{0x0f, 0x0f}): &bls12381G2MultiExp{},
|
common.BytesToAddress([]byte{0x0f, 0x0f}): &vm.Bls12381G2MultiExp{},
|
||||||
common.BytesToAddress([]byte{0x0f, 0x10}): &bls12381Pairing{},
|
common.BytesToAddress([]byte{0x0f, 0x10}): &vm.Bls12381Pairing{},
|
||||||
common.BytesToAddress([]byte{0x0f, 0x11}): &bls12381MapG1{},
|
common.BytesToAddress([]byte{0x0f, 0x11}): &vm.Bls12381MapG1{},
|
||||||
common.BytesToAddress([]byte{0x0f, 0x12}): &bls12381MapG2{},
|
common.BytesToAddress([]byte{0x0f, 0x12}): &vm.Bls12381MapG2{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// EIP-152 test vectors
|
// EIP-152 test vectors
|
||||||
var blake2FMalformedInputTests = []precompiledFailureTest{
|
var Blake2FMalformedInputTests = []precompiledFailureTest{
|
||||||
{
|
{
|
||||||
Input: "",
|
Input: "",
|
||||||
ExpectedError: errBlake2FInvalidInputLength.Error(),
|
ExpectedError: vm.ErrBlake2FInvalidInputLength.Error(),
|
||||||
Name: "vector 0: empty input",
|
Name: "vector 0: empty input",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Input: "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
|
Input: "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
|
||||||
ExpectedError: errBlake2FInvalidInputLength.Error(),
|
ExpectedError: vm.ErrBlake2FInvalidInputLength.Error(),
|
||||||
Name: "vector 1: less than 213 bytes input",
|
Name: "vector 1: less than 213 bytes input",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Input: "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
|
Input: "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
|
||||||
ExpectedError: errBlake2FInvalidInputLength.Error(),
|
ExpectedError: vm.ErrBlake2FInvalidInputLength.Error(),
|
||||||
Name: "vector 2: more than 213 bytes input",
|
Name: "vector 2: more than 213 bytes input",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Input: "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002",
|
Input: "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002",
|
||||||
ExpectedError: errBlake2FInvalidFinalFlag.Error(),
|
ExpectedError: vm.ErrBlake2FInvalidFinalFlag.Error(),
|
||||||
Name: "vector 3: malformed final block indicator flag",
|
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)
|
in := common.Hex2Bytes(test.Input)
|
||||||
gas := p.RequiredGas(in)
|
gas := p.RequiredGas(in)
|
||||||
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
|
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)
|
t.Error(err)
|
||||||
} else if common.Bytes2Hex(res) != test.Expected {
|
} else if common.Bytes2Hex(res) != test.Expected {
|
||||||
t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
|
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
|
gas := p.RequiredGas(in) - 1
|
||||||
|
|
||||||
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
|
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" {
|
if err.Error() != "out of gas" {
|
||||||
t.Errorf("Expected error [out of gas], got [%v]", err)
|
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)
|
in := common.Hex2Bytes(test.Input)
|
||||||
gas := p.RequiredGas(in)
|
gas := p.RequiredGas(in)
|
||||||
t.Run(test.Name, func(t *testing.T) {
|
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 {
|
if err.Error() != test.ExpectedError {
|
||||||
t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err)
|
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()
|
bench.ResetTimer()
|
||||||
for i := 0; i < bench.N; i++ {
|
for i := 0; i < bench.N; i++ {
|
||||||
copy(data, in)
|
copy(data, in)
|
||||||
res, _, err = RunPrecompiledContract(p, nil, data, reqGas)
|
res, _, err = vm.RunPrecompiledContract(p, nil, data, reqGas)
|
||||||
}
|
}
|
||||||
bench.StopTimer()
|
bench.StopTimer()
|
||||||
elapsed := uint64(time.Since(start))
|
elapsed := uint64(time.Since(start))
|
||||||
|
|
@ -237,8 +238,8 @@ func BenchmarkPrecompiledIdentity(bench *testing.B) {
|
||||||
func TestPrecompiledModExp(t *testing.T) { testJson("modexp", "05", t) }
|
func TestPrecompiledModExp(t *testing.T) { testJson("modexp", "05", t) }
|
||||||
func BenchmarkPrecompiledModExp(b *testing.B) { benchJson("modexp", "05", b) }
|
func BenchmarkPrecompiledModExp(b *testing.B) { benchJson("modexp", "05", b) }
|
||||||
|
|
||||||
func TestPrecompiledModExpEip2565(t *testing.T) { testJson("modexp_eip2565", "f5", t) }
|
func TestPrecompiledModExpEip2565(t *testing.T) { testJson("modexp_Eip2565", "f5", t) }
|
||||||
func BenchmarkPrecompiledModExpEip2565(b *testing.B) { benchJson("modexp_eip2565", "f5", b) }
|
func BenchmarkPrecompiledModExpEip2565(b *testing.B) { benchJson("modexp_Eip2565", "f5", b) }
|
||||||
|
|
||||||
// Tests the sample inputs from the elliptic curve addition EIP 213.
|
// Tests the sample inputs from the elliptic curve addition EIP 213.
|
||||||
func TestPrecompiledBn256Add(t *testing.T) { testJson("bn256Add", "06", t) }
|
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 TestPrecompiledBn256Pairing(t *testing.T) { testJson("bn256Pairing", "08", t) }
|
||||||
func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJson("bn256Pairing", "08", b) }
|
func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJson("bn256Pairing", "08", b) }
|
||||||
|
|
||||||
func TestPrecompiledBlake2F(t *testing.T) { testJson("blake2F", "09", t) }
|
func TestPrecompiledBlake2F(t *testing.T) { testJson("Blake2F", "09", t) }
|
||||||
func BenchmarkPrecompiledBlake2F(b *testing.B) { benchJson("blake2F", "09", b) }
|
func BenchmarkPrecompiledBlake2F(b *testing.B) { benchJson("Blake2F", "09", b) }
|
||||||
|
|
||||||
func TestPrecompileBlake2FMalformedInput(t *testing.T) {
|
func TestPrecompileBlake2FMalformedInput(t *testing.T) {
|
||||||
for _, test := range blake2FMalformedInputTests {
|
for _, test := range Blake2FMalformedInputTests {
|
||||||
testPrecompiledFailure("09", test, t)
|
testPrecompiledFailure("09", test, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,14 +71,14 @@ func ActivateableEips() []string {
|
||||||
// - Define SELFBALANCE, with cost GasFastStep (5)
|
// - Define SELFBALANCE, with cost GasFastStep (5)
|
||||||
func enable1884(jt *JumpTable) {
|
func enable1884(jt *JumpTable) {
|
||||||
// Gas cost changes
|
// Gas cost changes
|
||||||
jt[SLOAD].constantGas = params.SloadGasEIP1884
|
jt[SLOAD].ConstantGas = params.SloadGasEIP1884
|
||||||
jt[BALANCE].constantGas = params.BalanceGasEIP1884
|
jt[BALANCE].ConstantGas = params.BalanceGasEIP1884
|
||||||
jt[EXTCODEHASH].constantGas = params.ExtcodeHashGasEIP1884
|
jt[EXTCODEHASH].ConstantGas = params.ExtcodeHashGasEIP1884
|
||||||
|
|
||||||
// New opcode
|
// New opcode
|
||||||
jt[SELFBALANCE] = &operation{
|
jt[SELFBALANCE] = &operation{
|
||||||
execute: opSelfBalance,
|
execute: opSelfBalance,
|
||||||
constantGas: GasFastStep,
|
ConstantGas: GasFastStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +96,7 @@ func enable1344(jt *JumpTable) {
|
||||||
// New opcode
|
// New opcode
|
||||||
jt[CHAINID] = &operation{
|
jt[CHAINID] = &operation{
|
||||||
execute: opChainID,
|
execute: opChainID,
|
||||||
constantGas: GasQuickStep,
|
ConstantGas: GasQuickStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(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)
|
// enable2200 applies EIP-2200 (Rebalance net-metered SSTORE)
|
||||||
func enable2200(jt *JumpTable) {
|
func enable2200(jt *JumpTable) {
|
||||||
jt[SLOAD].constantGas = params.SloadGasEIP2200
|
jt[SLOAD].ConstantGas = params.SloadGasEIP2200
|
||||||
jt[SSTORE].dynamicGas = gasSStoreEIP2200
|
jt[SSTORE].dynamicGas = gasSStoreEIP2200
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,36 +120,36 @@ func enable2200(jt *JumpTable) {
|
||||||
func enable2929(jt *JumpTable) {
|
func enable2929(jt *JumpTable) {
|
||||||
jt[SSTORE].dynamicGas = gasSStoreEIP2929
|
jt[SSTORE].dynamicGas = gasSStoreEIP2929
|
||||||
|
|
||||||
jt[SLOAD].constantGas = 0
|
jt[SLOAD].ConstantGas = 0
|
||||||
jt[SLOAD].dynamicGas = gasSLoadEIP2929
|
jt[SLOAD].dynamicGas = gasSLoadEIP2929
|
||||||
|
|
||||||
jt[EXTCODECOPY].constantGas = params.WarmStorageReadCostEIP2929
|
jt[EXTCODECOPY].ConstantGas = params.WarmStorageReadCostEIP2929
|
||||||
jt[EXTCODECOPY].dynamicGas = gasExtCodeCopyEIP2929
|
jt[EXTCODECOPY].dynamicGas = gasExtCodeCopyEIP2929
|
||||||
|
|
||||||
jt[EXTCODESIZE].constantGas = params.WarmStorageReadCostEIP2929
|
jt[EXTCODESIZE].ConstantGas = params.WarmStorageReadCostEIP2929
|
||||||
jt[EXTCODESIZE].dynamicGas = gasEip2929AccountCheck
|
jt[EXTCODESIZE].dynamicGas = gasEip2929AccountCheck
|
||||||
|
|
||||||
jt[EXTCODEHASH].constantGas = params.WarmStorageReadCostEIP2929
|
jt[EXTCODEHASH].ConstantGas = params.WarmStorageReadCostEIP2929
|
||||||
jt[EXTCODEHASH].dynamicGas = gasEip2929AccountCheck
|
jt[EXTCODEHASH].dynamicGas = gasEip2929AccountCheck
|
||||||
|
|
||||||
jt[BALANCE].constantGas = params.WarmStorageReadCostEIP2929
|
jt[BALANCE].ConstantGas = params.WarmStorageReadCostEIP2929
|
||||||
jt[BALANCE].dynamicGas = gasEip2929AccountCheck
|
jt[BALANCE].dynamicGas = gasEip2929AccountCheck
|
||||||
|
|
||||||
jt[CALL].constantGas = params.WarmStorageReadCostEIP2929
|
jt[CALL].ConstantGas = params.WarmStorageReadCostEIP2929
|
||||||
jt[CALL].dynamicGas = gasCallEIP2929
|
jt[CALL].dynamicGas = gasCallEIP2929
|
||||||
|
|
||||||
jt[CALLCODE].constantGas = params.WarmStorageReadCostEIP2929
|
jt[CALLCODE].ConstantGas = params.WarmStorageReadCostEIP2929
|
||||||
jt[CALLCODE].dynamicGas = gasCallCodeEIP2929
|
jt[CALLCODE].dynamicGas = gasCallCodeEIP2929
|
||||||
|
|
||||||
jt[STATICCALL].constantGas = params.WarmStorageReadCostEIP2929
|
jt[STATICCALL].ConstantGas = params.WarmStorageReadCostEIP2929
|
||||||
jt[STATICCALL].dynamicGas = gasStaticCallEIP2929
|
jt[STATICCALL].dynamicGas = gasStaticCallEIP2929
|
||||||
|
|
||||||
jt[DELEGATECALL].constantGas = params.WarmStorageReadCostEIP2929
|
jt[DELEGATECALL].ConstantGas = params.WarmStorageReadCostEIP2929
|
||||||
jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP2929
|
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
|
// factor here
|
||||||
jt[SELFDESTRUCT].constantGas = params.SelfdestructGasEIP150
|
jt[SELFDESTRUCT].ConstantGas = params.SelfdestructGasEIP150
|
||||||
jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP2929
|
jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP2929
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +168,7 @@ func enable3198(jt *JumpTable) {
|
||||||
// New opcode
|
// New opcode
|
||||||
jt[BASEFEE] = &operation{
|
jt[BASEFEE] = &operation{
|
||||||
execute: opBaseFee,
|
execute: opBaseFee,
|
||||||
constantGas: GasQuickStep,
|
ConstantGas: GasQuickStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
}
|
}
|
||||||
|
|
@ -179,22 +179,22 @@ func enable3198(jt *JumpTable) {
|
||||||
// - Adds TSTORE that writes to transient storage
|
// - Adds TSTORE that writes to transient storage
|
||||||
func enable1153(jt *JumpTable) {
|
func enable1153(jt *JumpTable) {
|
||||||
jt[TLOAD] = &operation{
|
jt[TLOAD] = &operation{
|
||||||
execute: opTload,
|
execute: OpTload,
|
||||||
constantGas: params.WarmStorageReadCostEIP2929,
|
ConstantGas: params.WarmStorageReadCostEIP2929,
|
||||||
minStack: minStack(1, 1),
|
minStack: minStack(1, 1),
|
||||||
maxStack: maxStack(1, 1),
|
maxStack: maxStack(1, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
jt[TSTORE] = &operation{
|
jt[TSTORE] = &operation{
|
||||||
execute: opTstore,
|
execute: OpTstore,
|
||||||
constantGas: params.WarmStorageReadCostEIP2929,
|
ConstantGas: params.WarmStorageReadCostEIP2929,
|
||||||
minStack: minStack(2, 0),
|
minStack: minStack(2, 0),
|
||||||
maxStack: maxStack(2, 0),
|
maxStack: maxStack(2, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// opTload implements TLOAD opcode
|
// OpTload implements TLOAD opcode
|
||||||
func opTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
func OpTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
loc := scope.Stack.peek()
|
loc := scope.Stack.peek()
|
||||||
hash := common.Hash(loc.Bytes32())
|
hash := common.Hash(loc.Bytes32())
|
||||||
val := interpreter.evm.StateDB.GetTransientState(scope.Contract.Address(), hash)
|
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
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// opTstore implements TSTORE opcode
|
// OpTstore implements TSTORE opcode
|
||||||
func opTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
func OpTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
if interpreter.readOnly {
|
if interpreter.readOnly {
|
||||||
return nil, ErrWriteProtection
|
return nil, ErrWriteProtection
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +225,7 @@ func enable3855(jt *JumpTable) {
|
||||||
// New opcode
|
// New opcode
|
||||||
jt[PUSH0] = &operation{
|
jt[PUSH0] = &operation{
|
||||||
execute: opPush0,
|
execute: opPush0,
|
||||||
constantGas: GasQuickStep,
|
ConstantGas: GasQuickStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
}
|
}
|
||||||
|
|
@ -248,17 +248,17 @@ func enable3860(jt *JumpTable) {
|
||||||
// https://eips.ethereum.org/EIPS/eip-5656
|
// https://eips.ethereum.org/EIPS/eip-5656
|
||||||
func enable5656(jt *JumpTable) {
|
func enable5656(jt *JumpTable) {
|
||||||
jt[MCOPY] = &operation{
|
jt[MCOPY] = &operation{
|
||||||
execute: opMcopy,
|
execute: OpMcopy,
|
||||||
constantGas: GasFastestStep,
|
ConstantGas: GasFastestStep,
|
||||||
dynamicGas: gasMcopy,
|
dynamicGas: GasMcopy,
|
||||||
minStack: minStack(3, 0),
|
minStack: minStack(3, 0),
|
||||||
maxStack: maxStack(3, 0),
|
maxStack: maxStack(3, 0),
|
||||||
memorySize: memoryMcopy,
|
memorySize: MemoryMcopy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// opMcopy implements the MCOPY opcode (https://eips.ethereum.org/EIPS/eip-5656)
|
// OpMcopy implements the MCOPY opcode (https://eips.ethereum.org/EIPS/eip-5656)
|
||||||
func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
func OpMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
var (
|
var (
|
||||||
dst = scope.Stack.pop()
|
dst = scope.Stack.pop()
|
||||||
src = scope.Stack.pop()
|
src = scope.Stack.pop()
|
||||||
|
|
@ -270,8 +270,8 @@ func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// opBlobHash implements the BLOBHASH opcode
|
// OpBlobHash implements the BLOBHASH opcode
|
||||||
func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
func OpBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
index := scope.Stack.peek()
|
index := scope.Stack.peek()
|
||||||
if index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) {
|
if index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) {
|
||||||
blobHash := interpreter.evm.TxContext.BlobHashes[index.Uint64()]
|
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)
|
// enable4844 applies EIP-4844 (BLOBHASH opcode)
|
||||||
func enable4844(jt *JumpTable) {
|
func enable4844(jt *JumpTable) {
|
||||||
jt[BLOBHASH] = &operation{
|
jt[BLOBHASH] = &operation{
|
||||||
execute: opBlobHash,
|
execute: OpBlobHash,
|
||||||
constantGas: GasFastestStep,
|
ConstantGas: GasFastestStep,
|
||||||
minStack: minStack(1, 1),
|
minStack: minStack(1, 1),
|
||||||
maxStack: maxStack(1, 1),
|
maxStack: maxStack(1, 1),
|
||||||
}
|
}
|
||||||
|
|
@ -303,7 +303,7 @@ func enable4844(jt *JumpTable) {
|
||||||
func enable7516(jt *JumpTable) {
|
func enable7516(jt *JumpTable) {
|
||||||
jt[BLOBBASEFEE] = &operation{
|
jt[BLOBBASEFEE] = &operation{
|
||||||
execute: opBlobBaseFee,
|
execute: opBlobBaseFee,
|
||||||
constantGas: GasQuickStep,
|
ConstantGas: GasQuickStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
}
|
}
|
||||||
|
|
@ -314,7 +314,7 @@ func enable6780(jt *JumpTable) {
|
||||||
jt[SELFDESTRUCT] = &operation{
|
jt[SELFDESTRUCT] = &operation{
|
||||||
execute: opSelfdestruct6780,
|
execute: opSelfdestruct6780,
|
||||||
dynamicGas: gasSelfdestructEIP3529,
|
dynamicGas: gasSelfdestructEIP3529,
|
||||||
constantGas: params.SelfdestructGasEIP150,
|
ConstantGas: params.SelfdestructGasEIP150,
|
||||||
minStack: minStack(1, 0),
|
minStack: minStack(1, 0),
|
||||||
maxStack: maxStack(1, 0),
|
maxStack: maxStack(1, 0),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,10 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
|
||||||
return evm
|
return evm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (evm *EVM) GetInterpreter() *EVMInterpreter {
|
||||||
|
return evm.interpreter
|
||||||
|
}
|
||||||
|
|
||||||
// Reset resets the EVM with a new transaction context.Reset
|
// Reset resets the EVM with a new transaction context.Reset
|
||||||
// This is not threadsafe and should only be done very cautiously.
|
// This is not threadsafe and should only be done very cautiously.
|
||||||
func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) {
|
func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) {
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"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.
|
// 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 {
|
if newMemSize == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
|
||||||
if newMemSize > 0x1FFFFFFFE0 {
|
if newMemSize > 0x1FFFFFFFE0 {
|
||||||
return 0, ErrGasUintOverflow
|
return 0, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
newMemSizeWords := toWordSize(newMemSize)
|
newMemSizeWords := ToWordSize(newMemSize)
|
||||||
newMemSize = newMemSizeWords * 32
|
newMemSize = newMemSizeWords * 32
|
||||||
|
|
||||||
if newMemSize > uint64(mem.Len()) {
|
if newMemSize > uint64(mem.Len()) {
|
||||||
|
|
@ -66,7 +66,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
|
||||||
func memoryCopierGas(stackpos int) gasFunc {
|
func memoryCopierGas(stackpos int) gasFunc {
|
||||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
// Gas for expanding the memory
|
// Gas for expanding the memory
|
||||||
gas, err := memoryGasCost(mem, memorySize)
|
gas, err := MemoryGasCost(mem, memorySize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ func memoryCopierGas(stackpos int) gasFunc {
|
||||||
return 0, ErrGasUintOverflow
|
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
|
return 0, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ func memoryCopierGas(stackpos int) gasFunc {
|
||||||
var (
|
var (
|
||||||
gasCallDataCopy = memoryCopierGas(2)
|
gasCallDataCopy = memoryCopierGas(2)
|
||||||
gasCodeCopy = memoryCopierGas(2)
|
gasCodeCopy = memoryCopierGas(2)
|
||||||
gasMcopy = memoryCopierGas(2)
|
GasMcopy = memoryCopierGas(2)
|
||||||
gasExtCodeCopy = memoryCopierGas(3)
|
gasExtCodeCopy = memoryCopierGas(3)
|
||||||
gasReturnDataCopy = memoryCopierGas(2)
|
gasReturnDataCopy = memoryCopierGas(2)
|
||||||
)
|
)
|
||||||
|
|
@ -229,7 +229,7 @@ func makeGasLog(n uint64) gasFunc {
|
||||||
return 0, ErrGasUintOverflow
|
return 0, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
|
|
||||||
gas, err := memoryGasCost(mem, memorySize)
|
gas, err := MemoryGasCost(mem, memorySize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
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) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +261,7 @@ func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor
|
||||||
if overflow {
|
if overflow {
|
||||||
return 0, ErrGasUintOverflow
|
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
|
return 0, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
|
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
|
// static cost have a dynamic cost which is solely based on the memory
|
||||||
// expansion
|
// expansion
|
||||||
func pureMemoryGascost(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func pureMemoryGascost(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
return memoryGasCost(mem, memorySize)
|
return MemoryGasCost(mem, memorySize)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -287,7 +287,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -295,7 +295,7 @@ func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memoryS
|
||||||
if overflow {
|
if overflow {
|
||||||
return 0, ErrGasUintOverflow
|
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
|
return 0, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
|
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) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -321,7 +321,7 @@ func gasCreateEip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
func gasCreate2Eip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -379,7 +379,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize
|
||||||
if transfersValue {
|
if transfersValue {
|
||||||
gas += params.CallValueTransferGas
|
gas += params.CallValueTransferGas
|
||||||
}
|
}
|
||||||
memoryGas, err := memoryGasCost(mem, memorySize)
|
memoryGas, err := MemoryGasCost(mem, memorySize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
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) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
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) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
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) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package vm
|
package vm_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -41,9 +42,9 @@ func TestMemoryGasCost(t *testing.T) {
|
||||||
{0x1fffffffe1, 0, true},
|
{0x1fffffffe1, 0, true},
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
v, err := memoryGasCost(&Memory{}, tt.size)
|
v, err := vm.MemoryGasCost(&vm.Memory{}, tt.size)
|
||||||
if (err == ErrGasUintOverflow) != tt.overflow {
|
if (err == vm.ErrGasUintOverflow) != tt.overflow {
|
||||||
t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == ErrGasUintOverflow, tt.overflow)
|
t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == vm.ErrGasUintOverflow, tt.overflow)
|
||||||
}
|
}
|
||||||
if v != tt.cost {
|
if v != tt.cost {
|
||||||
t.Errorf("test %d: gas cost mismatch: have %v, want %v", i, 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
|
{1, math.MaxUint64, "0x60016000556001600055", 1612, 0, nil}, // 1 -> 1 -> 1
|
||||||
{0, math.MaxUint64, "0x600160005560006000556001600055", 40818, 19200, nil}, // 0 -> 1 -> 0 -> 1
|
{0, math.MaxUint64, "0x600160005560006000556001600055", 40818, 19200, nil}, // 0 -> 1 -> 0 -> 1
|
||||||
{1, math.MaxUint64, "0x600060005560016000556000600055", 10818, 19200, nil}, // 1 -> 0 -> 1 -> 0
|
{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)
|
{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.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
|
||||||
statedb.Finalise(true) // Push the state into the "original" slot
|
statedb.Finalise(true) // Push the state into the "original" slot
|
||||||
|
|
||||||
vmctx := BlockContext{
|
vmctx := vm.BlockContext{
|
||||||
CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
|
CanTransfer: func(vm.StateDB, common.Address, *big.Int) bool { return true },
|
||||||
Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
|
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 {
|
if err != tt.failure {
|
||||||
t.Errorf("test %d: failure mismatch: have %v, want %v", i, 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.CreateAccount(address)
|
||||||
statedb.SetCode(address, hexutil.MustDecode(tt.code))
|
statedb.SetCode(address, hexutil.MustDecode(tt.code))
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
vmctx := BlockContext{
|
vmctx := vm.BlockContext{
|
||||||
CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
|
CanTransfer: func(vm.StateDB, common.Address, *big.Int) bool { return true },
|
||||||
Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
|
Transfer: func(vm.StateDB, common.Address, common.Address, *big.Int) {},
|
||||||
BlockNumber: big.NewInt(0),
|
BlockNumber: big.NewInt(0),
|
||||||
}
|
}
|
||||||
config := Config{}
|
config := vm.Config{}
|
||||||
if tt.eip3860 {
|
if tt.eip3860 {
|
||||||
config.ExtraEips = []int{3860}
|
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)
|
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 {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,55 +24,55 @@ import (
|
||||||
"github.com/holiman/uint256"
|
"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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.Add(&x, y)
|
y.Add(&x, y)
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.Sub(&x, y)
|
y.Sub(&x, y)
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.Mul(&x, y)
|
y.Mul(&x, y)
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.Div(&x, y)
|
y.Div(&x, y)
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.SDiv(&x, y)
|
y.SDiv(&x, y)
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.Mod(&x, y)
|
y.Mod(&x, y)
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.SMod(&x, y)
|
y.SMod(&x, y)
|
||||||
return nil, nil
|
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()
|
base, exponent := scope.Stack.pop(), scope.Stack.peek()
|
||||||
exponent.Exp(&base, exponent)
|
exponent.Exp(&base, exponent)
|
||||||
return nil, nil
|
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()
|
back, num := scope.Stack.pop(), scope.Stack.peek()
|
||||||
num.ExtendSign(num, &back)
|
num.ExtendSign(num, &back)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -84,7 +84,7 @@ func opNot(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
if x.Lt(y) {
|
if x.Lt(y) {
|
||||||
y.SetOne()
|
y.SetOne()
|
||||||
|
|
@ -94,7 +94,7 @@ func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte,
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
if x.Gt(y) {
|
if x.Gt(y) {
|
||||||
y.SetOne()
|
y.SetOne()
|
||||||
|
|
@ -104,7 +104,7 @@ func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte,
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
if x.Slt(y) {
|
if x.Slt(y) {
|
||||||
y.SetOne()
|
y.SetOne()
|
||||||
|
|
@ -114,7 +114,7 @@ func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
if x.Sgt(y) {
|
if x.Sgt(y) {
|
||||||
y.SetOne()
|
y.SetOne()
|
||||||
|
|
@ -124,7 +124,7 @@ func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
if x.Eq(y) {
|
if x.Eq(y) {
|
||||||
y.SetOne()
|
y.SetOne()
|
||||||
|
|
@ -134,7 +134,7 @@ func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte,
|
||||||
return nil, nil
|
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()
|
x := scope.Stack.peek()
|
||||||
if x.IsZero() {
|
if x.IsZero() {
|
||||||
x.SetOne()
|
x.SetOne()
|
||||||
|
|
@ -144,31 +144,31 @@ func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.And(&x, y)
|
y.And(&x, y)
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.Or(&x, y)
|
y.Or(&x, y)
|
||||||
return nil, nil
|
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()
|
x, y := scope.Stack.pop(), scope.Stack.peek()
|
||||||
y.Xor(&x, y)
|
y.Xor(&x, y)
|
||||||
return nil, nil
|
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()
|
th, val := scope.Stack.pop(), scope.Stack.peek()
|
||||||
val.Byte(&th)
|
val.Byte(&th)
|
||||||
return nil, nil
|
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()
|
x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek()
|
||||||
if z.IsZero() {
|
if z.IsZero() {
|
||||||
z.Clear()
|
z.Clear()
|
||||||
|
|
@ -178,16 +178,16 @@ func opAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
|
||||||
return nil, nil
|
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()
|
x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek()
|
||||||
z.MulMod(&x, &y, z)
|
z.MulMod(&x, &y, z)
|
||||||
return nil, nil
|
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,
|
// 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.
|
// 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
|
// 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()
|
shift, value := scope.Stack.pop(), scope.Stack.peek()
|
||||||
if shift.LtUint64(256) {
|
if shift.LtUint64(256) {
|
||||||
|
|
@ -198,10 +198,10 @@ func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
||||||
return nil, nil
|
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,
|
// 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.
|
// 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
|
// 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()
|
shift, value := scope.Stack.pop(), scope.Stack.peek()
|
||||||
if shift.LtUint64(256) {
|
if shift.LtUint64(256) {
|
||||||
|
|
@ -212,10 +212,10 @@ func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
||||||
return nil, nil
|
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,
|
// 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.
|
// 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()
|
shift, value := scope.Stack.pop(), scope.Stack.peek()
|
||||||
if shift.GtUint64(256) {
|
if shift.GtUint64(256) {
|
||||||
if value.Sign() >= 0 {
|
if value.Sign() >= 0 {
|
||||||
|
|
@ -231,7 +231,7 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
||||||
return nil, nil
|
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()
|
offset, size := scope.Stack.pop(), scope.Stack.peek()
|
||||||
data := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64()))
|
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
|
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()))
|
scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes()))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -264,7 +264,7 @@ func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
|
||||||
return nil, nil
|
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()))
|
scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes()))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -476,7 +476,7 @@ func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
||||||
return nil, nil
|
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())
|
v := new(uint256.Int).SetBytes(interpreter.evm.Context.Random.Bytes())
|
||||||
scope.Stack.push(v)
|
scope.Stack.push(v)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -499,14 +499,14 @@ func opMload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
||||||
return nil, nil
|
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
|
// pop value of the stack
|
||||||
mStart, val := scope.Stack.pop(), scope.Stack.pop()
|
mStart, val := scope.Stack.pop(), scope.Stack.pop()
|
||||||
scope.Memory.Set32(mStart.Uint64(), &val)
|
scope.Memory.Set32(mStart.Uint64(), &val)
|
||||||
return nil, nil
|
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()
|
off, val := scope.Stack.pop(), scope.Stack.pop()
|
||||||
scope.Memory.store[off.Uint64()] = byte(val.Uint64())
|
scope.Memory.store[off.Uint64()] = byte(val.Uint64())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -850,7 +850,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
|
||||||
// following functions are used by the instruction jump table
|
// following functions are used by the instruction jump table
|
||||||
|
|
||||||
// make log instruction function
|
// make log instruction function
|
||||||
func makeLog(size int) executionFunc {
|
func makeLog(size int) ExecutionFunc {
|
||||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
if interpreter.readOnly {
|
if interpreter.readOnly {
|
||||||
return nil, ErrWriteProtection
|
return nil, ErrWriteProtection
|
||||||
|
|
@ -893,7 +893,7 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
||||||
}
|
}
|
||||||
|
|
||||||
// make push instruction function
|
// 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) {
|
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
codeLen := len(scope.Contract.Code)
|
codeLen := len(scope.Contract.Code)
|
||||||
|
|
||||||
|
|
@ -917,7 +917,7 @@ func makePush(size uint64, pushByteSize int) executionFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// make dup instruction function
|
// make dup instruction function
|
||||||
func makeDup(size int64) executionFunc {
|
func makeDup(size int64) ExecutionFunc {
|
||||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
scope.Stack.dup(int(size))
|
scope.Stack.dup(int(size))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -925,7 +925,7 @@ func makeDup(size int64) executionFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// make swap instruction function
|
// make swap instruction function
|
||||||
func makeSwap(size int64) executionFunc {
|
func makeSwap(size int64) ExecutionFunc {
|
||||||
// switch n + 1 otherwise n would be swapped with n
|
// switch n + 1 otherwise n would be swapped with n
|
||||||
size++
|
size++
|
||||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package vm
|
package vm_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
@ -48,7 +49,7 @@ type twoOperandParams struct {
|
||||||
|
|
||||||
var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
|
var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
|
||||||
var commonParams []*twoOperandParams
|
var commonParams []*twoOperandParams
|
||||||
var twoOpMethods map[string]executionFunc
|
var twoOpMethods map[string]vm.ExecutionFunc
|
||||||
|
|
||||||
type contractRef struct {
|
type contractRef struct {
|
||||||
addr common.Address
|
addr common.Address
|
||||||
|
|
@ -78,50 +79,50 @@ func init() {
|
||||||
commonParams[i*len(params)+j] = &twoOperandParams{x, y}
|
commonParams[i*len(params)+j] = &twoOperandParams{x, y}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
twoOpMethods = map[string]executionFunc{
|
twoOpMethods = map[string]vm.ExecutionFunc{
|
||||||
"add": opAdd,
|
"add": vm.OpAdd,
|
||||||
"sub": opSub,
|
"sub": vm.OpSub,
|
||||||
"mul": opMul,
|
"mul": vm.OpMul,
|
||||||
"div": opDiv,
|
"div": vm.OpDiv,
|
||||||
"sdiv": opSdiv,
|
"sdiv": vm.OpSdiv,
|
||||||
"mod": opMod,
|
"mod": vm.OpMod,
|
||||||
"smod": opSmod,
|
"smod": vm.OpSmod,
|
||||||
"exp": opExp,
|
"exp": vm.OpExp,
|
||||||
"signext": opSignExtend,
|
"signext": vm.OpSignExtend,
|
||||||
"lt": opLt,
|
"lt": vm.OpLt,
|
||||||
"gt": opGt,
|
"gt": vm.OpGt,
|
||||||
"slt": opSlt,
|
"slt": vm.OpSlt,
|
||||||
"sgt": opSgt,
|
"sgt": vm.OpSgt,
|
||||||
"eq": opEq,
|
"eq": vm.OpEq,
|
||||||
"and": opAnd,
|
"and": vm.OpAnd,
|
||||||
"or": opOr,
|
"or": vm.OpOr,
|
||||||
"xor": opXor,
|
"xor": vm.OpXor,
|
||||||
"byte": opByte,
|
"byte": vm.OpByte,
|
||||||
"shl": opSHL,
|
"shl": vm.OpSHL,
|
||||||
"shr": opSHR,
|
"shr": vm.OpSHR,
|
||||||
"sar": opSAR,
|
"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 (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
evmInterpreter = env.interpreter
|
evmInterpreter = env.GetInterpreter()
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X))
|
x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X))
|
||||||
y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y))
|
y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y))
|
||||||
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
|
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
|
||||||
stack.push(x)
|
stack.Push(x)
|
||||||
stack.push(y)
|
stack.Push(y)
|
||||||
opFn(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
|
opFn(&pc, evmInterpreter, &vm.ScopeContext{nil, stack, nil})
|
||||||
if len(stack.data) != 1 {
|
if len(stack.Data()) != 1 {
|
||||||
t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data))
|
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 {
|
if actual.Cmp(expected) != 0 {
|
||||||
t.Errorf("Testcase %v %d, %v(%x, %x): expected %x, got %x", name, i, name, x, y, expected, actual)
|
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", "20", "00"},
|
||||||
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "FFFFFFFFFFFFFFFF", "00"},
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "FFFFFFFFFFFFFFFF", "00"},
|
||||||
}
|
}
|
||||||
testTwoOperandOp(t, tests, opByte, "byte")
|
testTwoOperandOp(t, tests, vm.OpByte, "byte")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSHL(t *testing.T) {
|
func TestSHL(t *testing.T) {
|
||||||
|
|
@ -157,7 +158,7 @@ func TestSHL(t *testing.T) {
|
||||||
{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},
|
||||||
}
|
}
|
||||||
testTwoOperandOp(t, tests, opSHL, "shl")
|
testTwoOperandOp(t, tests, vm.OpSHL, "shl")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSHR(t *testing.T) {
|
func TestSHR(t *testing.T) {
|
||||||
|
|
@ -175,7 +176,7 @@ func TestSHR(t *testing.T) {
|
||||||
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
}
|
}
|
||||||
testTwoOperandOp(t, tests, opSHR, "shr")
|
testTwoOperandOp(t, tests, vm.OpSHR, "shr")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSAR(t *testing.T) {
|
func TestSAR(t *testing.T) {
|
||||||
|
|
@ -199,14 +200,14 @@ func TestSAR(t *testing.T) {
|
||||||
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
}
|
}
|
||||||
|
|
||||||
testTwoOperandOp(t, tests, opSAR, "sar")
|
testTwoOperandOp(t, tests, vm.OpSAR, "sar")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddMod(t *testing.T) {
|
func TestAddMod(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
evmInterpreter = vm.NewEVMInterpreter(env)
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
)
|
)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
|
@ -229,11 +230,11 @@ func TestAddMod(t *testing.T) {
|
||||||
y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.y))
|
y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.y))
|
||||||
z := new(uint256.Int).SetBytes(common.Hex2Bytes(test.z))
|
z := new(uint256.Int).SetBytes(common.Hex2Bytes(test.z))
|
||||||
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.expected))
|
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.expected))
|
||||||
stack.push(z)
|
stack.Push(z)
|
||||||
stack.push(y)
|
stack.Push(y)
|
||||||
stack.push(x)
|
stack.Push(x)
|
||||||
opAddmod(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
|
vm.OpAddmod(&pc, evmInterpreter, &vm.ScopeContext{nil, stack, nil})
|
||||||
actual := stack.pop()
|
actual := stack.Pop()
|
||||||
if actual.Cmp(expected) != 0 {
|
if actual.Cmp(expected) != 0 {
|
||||||
t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual)
|
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.")
|
t.Skip("Enable this test to create json test cases.")
|
||||||
|
|
||||||
// getResult is a convenience function to generate the expected values
|
// 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 (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
interpreter = env.interpreter
|
interpreter = env.Interpreter()
|
||||||
)
|
)
|
||||||
result := make([]TwoOperandTestcase, len(args))
|
result := make([]TwoOperandTestcase, len(args))
|
||||||
for i, param := range args {
|
for i, param := range args {
|
||||||
x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x))
|
x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x))
|
||||||
y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
|
y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
|
||||||
stack.push(x)
|
stack.Push(x)
|
||||||
stack.push(y)
|
stack.Push(y)
|
||||||
opFn(&pc, interpreter, &ScopeContext{nil, stack, nil})
|
opFn(&pc, interpreter, &vm.ScopeContext{nil, stack, nil})
|
||||||
actual := stack.pop()
|
actual := stack.Pop()
|
||||||
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
|
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
|
||||||
}
|
}
|
||||||
return result
|
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 (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
scope = &ScopeContext{nil, stack, nil}
|
scope = &vm.ScopeContext{nil, stack, nil}
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
evmInterpreter = vm.NewEVMInterpreter(env)
|
||||||
)
|
)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
env.SetInterpreter(evmInterpreter)
|
||||||
// convert args
|
// convert args
|
||||||
intArgs := make([]*uint256.Int, len(args))
|
intArgs := make([]*uint256.Int, len(args))
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
|
|
@ -309,10 +310,10 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
||||||
bench.ResetTimer()
|
bench.ResetTimer()
|
||||||
for i := 0; i < bench.N; i++ {
|
for i := 0; i < bench.N; i++ {
|
||||||
for _, arg := range intArgs {
|
for _, arg := range intArgs {
|
||||||
stack.push(arg)
|
stack.Push(arg)
|
||||||
}
|
}
|
||||||
op(&pc, evmInterpreter, scope)
|
op(&pc, evmInterpreter, scope)
|
||||||
stack.pop()
|
stack.Pop()
|
||||||
}
|
}
|
||||||
bench.StopTimer()
|
bench.StopTimer()
|
||||||
|
|
||||||
|
|
@ -328,169 +329,169 @@ func BenchmarkOpAdd64(b *testing.B) {
|
||||||
x := "ffffffff"
|
x := "ffffffff"
|
||||||
y := "fd37f3e2bba2c4f"
|
y := "fd37f3e2bba2c4f"
|
||||||
|
|
||||||
opBenchmark(b, opAdd, x, y)
|
opBenchmark(b, vm.OpAdd, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpAdd128(b *testing.B) {
|
func BenchmarkOpAdd128(b *testing.B) {
|
||||||
x := "ffffffffffffffff"
|
x := "ffffffffffffffff"
|
||||||
y := "f5470b43c6549b016288e9a65629687"
|
y := "f5470b43c6549b016288e9a65629687"
|
||||||
|
|
||||||
opBenchmark(b, opAdd, x, y)
|
opBenchmark(b, vm.OpAdd, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpAdd256(b *testing.B) {
|
func BenchmarkOpAdd256(b *testing.B) {
|
||||||
x := "0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9"
|
x := "0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9"
|
||||||
y := "a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57"
|
y := "a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57"
|
||||||
|
|
||||||
opBenchmark(b, opAdd, x, y)
|
opBenchmark(b, vm.OpAdd, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpSub64(b *testing.B) {
|
func BenchmarkOpSub64(b *testing.B) {
|
||||||
x := "51022b6317003a9d"
|
x := "51022b6317003a9d"
|
||||||
y := "a20456c62e00753a"
|
y := "a20456c62e00753a"
|
||||||
|
|
||||||
opBenchmark(b, opSub, x, y)
|
opBenchmark(b, vm.OpSub, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpSub128(b *testing.B) {
|
func BenchmarkOpSub128(b *testing.B) {
|
||||||
x := "4dde30faaacdc14d00327aac314e915d"
|
x := "4dde30faaacdc14d00327aac314e915d"
|
||||||
y := "9bbc61f5559b829a0064f558629d22ba"
|
y := "9bbc61f5559b829a0064f558629d22ba"
|
||||||
|
|
||||||
opBenchmark(b, opSub, x, y)
|
opBenchmark(b, vm.OpSub, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpSub256(b *testing.B) {
|
func BenchmarkOpSub256(b *testing.B) {
|
||||||
x := "4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37"
|
x := "4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37"
|
||||||
y := "97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e"
|
y := "97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e"
|
||||||
|
|
||||||
opBenchmark(b, opSub, x, y)
|
opBenchmark(b, vm.OpSub, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpMul(b *testing.B) {
|
func BenchmarkOpMul(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opMul, x, y)
|
opBenchmark(b, vm.OpMul, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpDiv256(b *testing.B) {
|
func BenchmarkOpDiv256(b *testing.B) {
|
||||||
x := "ff3f9014f20db29ae04af2c2d265de17"
|
x := "ff3f9014f20db29ae04af2c2d265de17"
|
||||||
y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
|
y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
|
||||||
opBenchmark(b, opDiv, x, y)
|
opBenchmark(b, vm.OpDiv, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpDiv128(b *testing.B) {
|
func BenchmarkOpDiv128(b *testing.B) {
|
||||||
x := "fdedc7f10142ff97"
|
x := "fdedc7f10142ff97"
|
||||||
y := "fbdfda0e2ce356173d1993d5f70a2b11"
|
y := "fbdfda0e2ce356173d1993d5f70a2b11"
|
||||||
opBenchmark(b, opDiv, x, y)
|
opBenchmark(b, vm.OpDiv, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpDiv64(b *testing.B) {
|
func BenchmarkOpDiv64(b *testing.B) {
|
||||||
x := "fcb34eb3"
|
x := "fcb34eb3"
|
||||||
y := "f97180878e839129"
|
y := "f97180878e839129"
|
||||||
opBenchmark(b, opDiv, x, y)
|
opBenchmark(b, vm.OpDiv, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpSdiv(b *testing.B) {
|
func BenchmarkOpSdiv(b *testing.B) {
|
||||||
x := "ff3f9014f20db29ae04af2c2d265de17"
|
x := "ff3f9014f20db29ae04af2c2d265de17"
|
||||||
y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
|
y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
|
||||||
|
|
||||||
opBenchmark(b, opSdiv, x, y)
|
opBenchmark(b, vm.OpSdiv, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpMod(b *testing.B) {
|
func BenchmarkOpMod(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opMod, x, y)
|
opBenchmark(b, vm.OpMod, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpSmod(b *testing.B) {
|
func BenchmarkOpSmod(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opSmod, x, y)
|
opBenchmark(b, vm.OpSmod, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpExp(b *testing.B) {
|
func BenchmarkOpExp(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opExp, x, y)
|
opBenchmark(b, vm.OpExp, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpSignExtend(b *testing.B) {
|
func BenchmarkOpSignExtend(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opSignExtend, x, y)
|
opBenchmark(b, vm.OpSignExtend, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpLt(b *testing.B) {
|
func BenchmarkOpLt(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opLt, x, y)
|
opBenchmark(b, vm.OpLt, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpGt(b *testing.B) {
|
func BenchmarkOpGt(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opGt, x, y)
|
opBenchmark(b, vm.OpGt, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpSlt(b *testing.B) {
|
func BenchmarkOpSlt(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opSlt, x, y)
|
opBenchmark(b, vm.OpSlt, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpSgt(b *testing.B) {
|
func BenchmarkOpSgt(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opSgt, x, y)
|
opBenchmark(b, vm.OpSgt, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpEq(b *testing.B) {
|
func BenchmarkOpEq(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opEq, x, y)
|
opBenchmark(b, vm.OpEq, x, y)
|
||||||
}
|
}
|
||||||
func BenchmarkOpEq2(b *testing.B) {
|
func BenchmarkOpEq2(b *testing.B) {
|
||||||
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe"
|
y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe"
|
||||||
opBenchmark(b, opEq, x, y)
|
opBenchmark(b, vm.OpEq, x, y)
|
||||||
}
|
}
|
||||||
func BenchmarkOpAnd(b *testing.B) {
|
func BenchmarkOpAnd(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opAnd, x, y)
|
opBenchmark(b, vm.OpAnd, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpOr(b *testing.B) {
|
func BenchmarkOpOr(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opOr, x, y)
|
opBenchmark(b, vm.OpOr, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpXor(b *testing.B) {
|
func BenchmarkOpXor(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opXor, x, y)
|
opBenchmark(b, vm.OpXor, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpByte(b *testing.B) {
|
func BenchmarkOpByte(b *testing.B) {
|
||||||
x := alphabetSoup
|
x := alphabetSoup
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opByte, x, y)
|
opBenchmark(b, vm.OpByte, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpAddmod(b *testing.B) {
|
func BenchmarkOpAddmod(b *testing.B) {
|
||||||
|
|
@ -498,7 +499,7 @@ func BenchmarkOpAddmod(b *testing.B) {
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
z := alphabetSoup
|
z := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opAddmod, x, y, z)
|
opBenchmark(b, vm.OpAddmod, x, y, z)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpMulmod(b *testing.B) {
|
func BenchmarkOpMulmod(b *testing.B) {
|
||||||
|
|
@ -506,53 +507,53 @@ func BenchmarkOpMulmod(b *testing.B) {
|
||||||
y := alphabetSoup
|
y := alphabetSoup
|
||||||
z := alphabetSoup
|
z := alphabetSoup
|
||||||
|
|
||||||
opBenchmark(b, opMulmod, x, y, z)
|
opBenchmark(b, vm.OpMulmod, x, y, z)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOpSHL(b *testing.B) {
|
func BenchmarkOpSHL(b *testing.B) {
|
||||||
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
y := "ff"
|
y := "ff"
|
||||||
|
|
||||||
opBenchmark(b, opSHL, x, y)
|
opBenchmark(b, vm.OpSHL, x, y)
|
||||||
}
|
}
|
||||||
func BenchmarkOpSHR(b *testing.B) {
|
func BenchmarkOpSHR(b *testing.B) {
|
||||||
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
y := "ff"
|
y := "ff"
|
||||||
|
|
||||||
opBenchmark(b, opSHR, x, y)
|
opBenchmark(b, vm.OpSHR, x, y)
|
||||||
}
|
}
|
||||||
func BenchmarkOpSAR(b *testing.B) {
|
func BenchmarkOpSAR(b *testing.B) {
|
||||||
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
y := "ff"
|
y := "ff"
|
||||||
|
|
||||||
opBenchmark(b, opSAR, x, y)
|
opBenchmark(b, vm.OpSAR, x, y)
|
||||||
}
|
}
|
||||||
func BenchmarkOpIsZero(b *testing.B) {
|
func BenchmarkOpIsZero(b *testing.B) {
|
||||||
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
opBenchmark(b, opIszero, x)
|
opBenchmark(b, vm.OpIszero, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOpMstore(t *testing.T) {
|
func TestOpMstore(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
mem = NewMemory()
|
mem = vm.NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
evmInterpreter = vm.NewEVMInterpreter(env)
|
||||||
)
|
)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
env.SetInterpreter(evmInterpreter)
|
||||||
mem.Resize(64)
|
mem.Resize(64)
|
||||||
pc := uint64(0)
|
pc := uint64(0)
|
||||||
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
|
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
|
||||||
stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
|
stack.Push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
|
||||||
stack.push(new(uint256.Int))
|
stack.Push(new(uint256.Int))
|
||||||
opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
|
vm.OpMstore(&pc, evmInterpreter, &vm.ScopeContext{mem, stack, nil})
|
||||||
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
|
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
|
||||||
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
|
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
|
||||||
}
|
}
|
||||||
stack.push(new(uint256.Int).SetUint64(0x1))
|
stack.Push(new(uint256.Int).SetUint64(0x1))
|
||||||
stack.push(new(uint256.Int))
|
stack.Push(new(uint256.Int))
|
||||||
opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
|
vm.OpMstore(&pc, evmInterpreter, &vm.ScopeContext{mem, stack, nil})
|
||||||
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
|
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
|
||||||
t.Fatalf("Mstore failed to overwrite previous value")
|
t.Fatalf("Mstore failed to overwrite previous value")
|
||||||
}
|
}
|
||||||
|
|
@ -560,13 +561,13 @@ func TestOpMstore(t *testing.T) {
|
||||||
|
|
||||||
func BenchmarkOpMstore(bench *testing.B) {
|
func BenchmarkOpMstore(bench *testing.B) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
mem = NewMemory()
|
mem = vm.NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
evmInterpreter = vm.NewEVMInterpreter(env)
|
||||||
)
|
)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
env.SetInterpreter(evmInterpreter)
|
||||||
mem.Resize(64)
|
mem.Resize(64)
|
||||||
pc := uint64(0)
|
pc := uint64(0)
|
||||||
memStart := new(uint256.Int)
|
memStart := new(uint256.Int)
|
||||||
|
|
@ -574,24 +575,24 @@ func BenchmarkOpMstore(bench *testing.B) {
|
||||||
|
|
||||||
bench.ResetTimer()
|
bench.ResetTimer()
|
||||||
for i := 0; i < bench.N; i++ {
|
for i := 0; i < bench.N; i++ {
|
||||||
stack.push(value)
|
stack.Push(value)
|
||||||
stack.push(memStart)
|
stack.Push(memStart)
|
||||||
opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
|
vm.OpMstore(&pc, evmInterpreter, &vm.ScopeContext{mem, stack, nil})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOpTstore(t *testing.T) {
|
func TestOpTstore(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, statedb, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
mem = NewMemory()
|
mem = vm.NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
evmInterpreter = vm.NewEVMInterpreter(env)
|
||||||
caller = common.Address{}
|
caller = common.Address{}
|
||||||
to = common.Address{1}
|
to = common.Address{1}
|
||||||
contractRef = contractRef{caller}
|
contractRef = contractRef{caller}
|
||||||
contract = NewContract(contractRef, AccountRef(to), new(big.Int), 0)
|
contract = vm.NewContract(contractRef, vm.AccountRef(to), new(big.Int), 0)
|
||||||
scopeContext = ScopeContext{mem, stack, contract}
|
scopeContext = vm.ScopeContext{mem, stack, contract}
|
||||||
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
|
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -599,25 +600,25 @@ func TestOpTstore(t *testing.T) {
|
||||||
statedb.CreateAccount(caller)
|
statedb.CreateAccount(caller)
|
||||||
statedb.CreateAccount(to)
|
statedb.CreateAccount(to)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
env.SetInterpreter(evmInterpreter)
|
||||||
pc := uint64(0)
|
pc := uint64(0)
|
||||||
// push the value to the stack
|
// 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
|
// push the location to the stack
|
||||||
stack.push(new(uint256.Int))
|
stack.Push(new(uint256.Int))
|
||||||
opTstore(&pc, evmInterpreter, &scopeContext)
|
vm.OpTstore(&pc, evmInterpreter, &scopeContext)
|
||||||
// there should be no elements on the stack after TSTORE
|
// there should be no elements on the stack after TSTORE
|
||||||
if stack.len() != 0 {
|
if stack.Len() != 0 {
|
||||||
t.Fatal("stack wrong size")
|
t.Fatal("stack wrong size")
|
||||||
}
|
}
|
||||||
// push the location to the stack
|
// push the location to the stack
|
||||||
stack.push(new(uint256.Int))
|
stack.Push(new(uint256.Int))
|
||||||
opTload(&pc, evmInterpreter, &scopeContext)
|
vm.OpTload(&pc, evmInterpreter, &scopeContext)
|
||||||
// there should be one element on the stack after TLOAD
|
// there should be one element on the stack after TLOAD
|
||||||
if stack.len() != 1 {
|
if stack.Len() != 1 {
|
||||||
t.Fatal("stack wrong size")
|
t.Fatal("stack wrong size")
|
||||||
}
|
}
|
||||||
val := stack.peek()
|
val := stack.Peek()
|
||||||
if !bytes.Equal(val.Bytes(), value) {
|
if !bytes.Equal(val.Bytes(), value) {
|
||||||
t.Fatal("incorrect element read from transient storage")
|
t.Fatal("incorrect element read from transient storage")
|
||||||
}
|
}
|
||||||
|
|
@ -625,21 +626,21 @@ func TestOpTstore(t *testing.T) {
|
||||||
|
|
||||||
func BenchmarkOpKeccak256(bench *testing.B) {
|
func BenchmarkOpKeccak256(bench *testing.B) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
mem = NewMemory()
|
mem = vm.NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
evmInterpreter = vm.NewEVMInterpreter(env)
|
||||||
)
|
)
|
||||||
env.interpreter = evmInterpreter
|
env.SetInterpreter(evmInterpreter)
|
||||||
mem.Resize(32)
|
mem.Resize(32)
|
||||||
pc := uint64(0)
|
pc := uint64(0)
|
||||||
start := new(uint256.Int)
|
start := new(uint256.Int)
|
||||||
|
|
||||||
bench.ResetTimer()
|
bench.ResetTimer()
|
||||||
for i := 0; i < bench.N; i++ {
|
for i := 0; i < bench.N; i++ {
|
||||||
stack.push(uint256.NewInt(32))
|
stack.Push(uint256.NewInt(32))
|
||||||
stack.push(start)
|
stack.Push(start)
|
||||||
opKeccak256(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
|
vm.OpKeccak256(&pc, evmInterpreter, &vm.ScopeContext{mem, stack, nil})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -701,11 +702,11 @@ func TestCreate2Addreses(t *testing.T) {
|
||||||
codeHash := crypto.Keccak256(code)
|
codeHash := crypto.Keccak256(code)
|
||||||
address := crypto.CreateAddress2(origin, salt, codeHash)
|
address := crypto.CreateAddress2(origin, salt, codeHash)
|
||||||
/*
|
/*
|
||||||
stack := newstack()
|
stack :=vm.Newstack()
|
||||||
// salt, but we don't need that for this test
|
// salt, but we don't need that for this test
|
||||||
stack.push(big.NewInt(int64(len(code)))) //size
|
stack.Push(big.NewInt(int64(len(code)))) //size
|
||||||
stack.push(big.NewInt(0)) // memstart
|
stack.Push(big.NewInt(0)) // memstart
|
||||||
stack.push(big.NewInt(0)) // value
|
stack.Push(big.NewInt(0)) // value
|
||||||
gas, _ := gasCreate2(params.GasTable{}, nil, nil, stack, nil, 0)
|
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())
|
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})},
|
{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
|
||||||
} {
|
} {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{Random: &tt.random}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
evmInterpreter = env.interpreter
|
evmInterpreter = env.Interpreter()
|
||||||
)
|
)
|
||||||
opRandom(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
|
vm.OpRandom(&pc, evmInterpreter, &vm.ScopeContext{nil, stack, nil})
|
||||||
if len(stack.data) != 1 {
|
if len(stack.Data()) != 1 {
|
||||||
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
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()))
|
expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.random.Bytes()))
|
||||||
if overflow {
|
if overflow {
|
||||||
t.Errorf("Testcase %v: invalid overflow", tt.name)
|
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},
|
{name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil},
|
||||||
} {
|
} {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{BlobHashes: tt.hashes}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{BlobHashes: tt.hashes}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
evmInterpreter = env.interpreter
|
evmInterpreter = env.Interpreter()
|
||||||
)
|
)
|
||||||
stack.push(uint256.NewInt(tt.idx))
|
stack.Push(uint256.NewInt(tt.idx))
|
||||||
opBlobHash(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
|
vm.OpBlobHash(&pc, evmInterpreter, &vm.ScopeContext{nil, stack, nil})
|
||||||
if len(stack.data) != 1 {
|
if len(stack.Data()) != 1 {
|
||||||
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
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()))
|
expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.expect.Bytes()))
|
||||||
if overflow {
|
if overflow {
|
||||||
t.Errorf("Testcase %v: invalid overflow", tt.name)
|
t.Errorf("Testcase %v: invalid overflow", tt.name)
|
||||||
|
|
@ -873,14 +874,14 @@ func TestOpMCopy(t *testing.T) {
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, nil, params.TestChainConfig, vm.Config{})
|
||||||
stack = newstack()
|
stack = vm.Newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
evmInterpreter = env.interpreter
|
evmInterpreter = env.Interpreter()
|
||||||
)
|
)
|
||||||
data := common.FromHex(strings.ReplaceAll(tc.pre, " ", ""))
|
data := common.FromHex(strings.ReplaceAll(tc.pre, " ", ""))
|
||||||
// Set pre
|
// Set pre
|
||||||
mem := NewMemory()
|
mem := vm.NewMemory()
|
||||||
mem.Resize(uint64(len(data)))
|
mem.Resize(uint64(len(data)))
|
||||||
mem.Set(0, uint64(len(data)), data)
|
mem.Set(0, uint64(len(data)), data)
|
||||||
// Push stack args
|
// Push stack args
|
||||||
|
|
@ -888,38 +889,38 @@ func TestOpMCopy(t *testing.T) {
|
||||||
src, _ := uint256.FromHex(tc.src)
|
src, _ := uint256.FromHex(tc.src)
|
||||||
dst, _ := uint256.FromHex(tc.dst)
|
dst, _ := uint256.FromHex(tc.dst)
|
||||||
|
|
||||||
stack.push(len)
|
stack.Push(len)
|
||||||
stack.push(src)
|
stack.Push(src)
|
||||||
stack.push(dst)
|
stack.Push(dst)
|
||||||
wantErr := (tc.wantGas == 0)
|
wantErr := (tc.wantGas == 0)
|
||||||
// Calc mem expansion
|
// Calc mem expansion
|
||||||
var memorySize uint64
|
var memorySize uint64
|
||||||
if memSize, overflow := memoryMcopy(stack); overflow {
|
if memSize, overflow := vm.MemoryMcopy(stack); overflow {
|
||||||
if wantErr {
|
if wantErr {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t.Errorf("overflow")
|
t.Errorf("overflow")
|
||||||
} else {
|
} else {
|
||||||
var overflow bool
|
var overflow bool
|
||||||
if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow {
|
if memorySize, overflow = math.SafeMul(vm.ToWordSize(memSize), 32); overflow {
|
||||||
t.Error(ErrGasUintOverflow)
|
t.Error(vm.ErrGasUintOverflow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// and the dynamic cost
|
// and the dynamic cost
|
||||||
var haveGas uint64
|
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)
|
t.Error(err)
|
||||||
} else {
|
} else {
|
||||||
haveGas = GasFastestStep + dynamicCost
|
haveGas = vm.GasFastestStep + dynamicCost
|
||||||
}
|
}
|
||||||
// Expand mem
|
// Expand mem
|
||||||
if memorySize > 0 {
|
if memorySize > 0 {
|
||||||
mem.Resize(memorySize)
|
mem.Resize(memorySize)
|
||||||
}
|
}
|
||||||
// Do the copy
|
// 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, " ", ""))
|
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)
|
t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have)
|
||||||
}
|
}
|
||||||
wantGas := tc.wantGas
|
wantGas := tc.wantGas
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
@ -88,7 +87,7 @@ type StateDB interface {
|
||||||
Finalise(deleteEmptyObjects bool)
|
Finalise(deleteEmptyObjects bool)
|
||||||
Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error)
|
Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error)
|
||||||
SetTxContext(thash common.Hash, ti int)
|
SetTxContext(thash common.Hash, ti int)
|
||||||
Copy() *state.StateDB
|
Copy() StateDB
|
||||||
IntermediateRoot(deleteEmptyObjects bool) common.Hash
|
IntermediateRoot(deleteEmptyObjects bool) common.Hash
|
||||||
GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log
|
GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log
|
||||||
TxIndex() int
|
TxIndex() int
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
||||||
var extraEips []int
|
var extraEips []int
|
||||||
if len(evm.Config.ExtraEips) > 0 {
|
if len(evm.Config.ExtraEips) > 0 {
|
||||||
// Deep-copy jumptable to prevent modification of opcodes in other tables
|
// Deep-copy jumptable to prevent modification of opcodes in other tables
|
||||||
table = copyJumpTable(table)
|
table = CopyJumpTable(table)
|
||||||
}
|
}
|
||||||
for _, eip := range evm.Config.ExtraEips {
|
for _, eip := range evm.Config.ExtraEips {
|
||||||
if err := EnableEIP(eip, table); err != nil {
|
if err := EnableEIP(eip, table); err != nil {
|
||||||
|
|
@ -128,7 +128,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||||
var (
|
var (
|
||||||
op OpCode // current opcode
|
op OpCode // current opcode
|
||||||
mem = NewMemory() // bound memory
|
mem = NewMemory() // bound memory
|
||||||
stack = newstack() // local stack
|
stack = Newstack() // local stack
|
||||||
callContext = &ScopeContext{
|
callContext = &ScopeContext{
|
||||||
Memory: mem,
|
Memory: mem,
|
||||||
Stack: stack,
|
Stack: stack,
|
||||||
|
|
@ -178,7 +178,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||||
// enough stack items available to perform the operation.
|
// enough stack items available to perform the operation.
|
||||||
op = contract.GetOp(pc)
|
op = contract.GetOp(pc)
|
||||||
operation := in.table[op]
|
operation := in.table[op]
|
||||||
cost = operation.constantGas // For tracing
|
cost = operation.ConstantGas // For tracing
|
||||||
// Validate stack
|
// Validate stack
|
||||||
if sLen := stack.len(); sLen < operation.minStack {
|
if sLen := stack.len(); sLen < operation.minStack {
|
||||||
return nil, &ErrStackUnderflow{stackLen: sLen, required: 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
|
// memory is expanded in words of 32 bytes. Gas
|
||||||
// is also calculated in words.
|
// 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
|
return nil, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package vm
|
package vm_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -38,8 +39,8 @@ var loopInterruptTests = []string{
|
||||||
|
|
||||||
func TestLoopInterrupt(t *testing.T) {
|
func TestLoopInterrupt(t *testing.T) {
|
||||||
address := common.BytesToAddress([]byte("contract"))
|
address := common.BytesToAddress([]byte("contract"))
|
||||||
vmctx := BlockContext{
|
vmctx := vm.BlockContext{
|
||||||
Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
|
Transfer: func(vm.StateDB, common.Address, common.Address, *big.Int) {},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range loopInterruptTests {
|
for i, tt := range loopInterruptTests {
|
||||||
|
|
@ -48,13 +49,13 @@ func TestLoopInterrupt(t *testing.T) {
|
||||||
statedb.SetCode(address, common.Hex2Bytes(tt))
|
statedb.SetCode(address, common.Hex2Bytes(tt))
|
||||||
statedb.Finalise(true)
|
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)
|
errChannel := make(chan error)
|
||||||
timeout := make(chan bool)
|
timeout := make(chan bool)
|
||||||
|
|
||||||
go func(evm *EVM) {
|
go func(evm *vm.EVM) {
|
||||||
_, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(big.Int))
|
_, _, err := evm.Call(vm.AccountRef(common.Address{}), address, nil, math.MaxUint64, new(big.Int))
|
||||||
errChannel <- err
|
errChannel <- err
|
||||||
}(evm)
|
}(evm)
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -35,7 +35,7 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) {
|
||||||
case rules.IsShanghai:
|
case rules.IsShanghai:
|
||||||
return newShanghaiInstructionSet(), nil
|
return newShanghaiInstructionSet(), nil
|
||||||
case rules.IsMerge:
|
case rules.IsMerge:
|
||||||
return newMergeInstructionSet(), nil
|
return NewMergeInstructionSet(), nil
|
||||||
case rules.IsLondon:
|
case rules.IsLondon:
|
||||||
return newLondonInstructionSet(), nil
|
return newLondonInstructionSet(), nil
|
||||||
case rules.IsBerlin:
|
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
|
// 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
|
// 'indicators' that this is an invalid op. Alas, STOP is impossible to
|
||||||
// filter out
|
// filter out
|
||||||
return op.dynamicGas != nil || op.constantGas != 0
|
return op.dynamicGas != nil || op.ConstantGas != 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,22 +14,23 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package vm
|
package vm_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestJumpTableCopy tests that deep copy is necessery to prevent modify shared jump table
|
// TestJumpTableCopy tests that deep copy is necessery to prevent modify shared jump table
|
||||||
func TestJumpTableCopy(t *testing.T) {
|
func TestJumpTableCopy(t *testing.T) {
|
||||||
tbl := newMergeInstructionSet()
|
tbl := vm.NewMergeInstructionSet()
|
||||||
require.Equal(t, uint64(0), tbl[SLOAD].constantGas)
|
require.Equal(t, uint64(0), tbl[vm.SLOAD].ConstantGas)
|
||||||
|
|
||||||
// a deep copy won't modify the shared jump table
|
// a deep copy won't modify the shared jump table
|
||||||
deepCopy := copyJumpTable(&tbl)
|
deepCopy := vm.CopyJumpTable(&tbl)
|
||||||
deepCopy[SLOAD].constantGas = 100
|
deepCopy[vm.SLOAD].ConstantGas = 100
|
||||||
require.Equal(t, uint64(100), deepCopy[SLOAD].constantGas)
|
require.Equal(t, uint64(100), deepCopy[vm.SLOAD].ConstantGas)
|
||||||
require.Equal(t, uint64(0), tbl[SLOAD].constantGas)
|
require.Equal(t, uint64(0), tbl[vm.SLOAD].ConstantGas)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,3 +114,7 @@ func (m *Memory) Copy(dst, src, len uint64) {
|
||||||
}
|
}
|
||||||
copy(m.store[dst:], m.store[src:src+len])
|
copy(m.store[dst:], m.store[src:src+len])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Memory) GetStore() []byte {
|
||||||
|
return m.store
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ func memoryMStore(stack *Stack) (uint64, bool) {
|
||||||
return calcMemSize64WithUint(stack.Back(0), 32)
|
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
|
mStart := stack.Back(0) // stack[0]: dest
|
||||||
if stack.Back(1).Gt(mStart) {
|
if stack.Back(1).Gt(mStart) {
|
||||||
mStart = stack.Back(1) // stack[1]: source
|
mStart = stack.Back(1) // stack[1]: source
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package vm
|
package vm_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMemoryCopy(t *testing.T) {
|
func TestMemoryCopy(t *testing.T) {
|
||||||
|
|
@ -53,7 +54,7 @@ func TestMemoryCopy(t *testing.T) {
|
||||||
"11",
|
"11",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
m := NewMemory()
|
m := vm.NewMemory()
|
||||||
// Clean spaces
|
// Clean spaces
|
||||||
data := common.FromHex(strings.ReplaceAll(tc.pre, " ", ""))
|
data := common.FromHex(strings.ReplaceAll(tc.pre, " ", ""))
|
||||||
// Set pre
|
// Set pre
|
||||||
|
|
@ -62,7 +63,7 @@ func TestMemoryCopy(t *testing.T) {
|
||||||
// Do the copy
|
// Do the copy
|
||||||
m.Copy(tc.dst, tc.src, tc.len)
|
m.Copy(tc.dst, tc.src, tc.len)
|
||||||
want := common.FromHex(strings.ReplaceAll(tc.want, " ", ""))
|
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)
|
t.Errorf("case %d: want: %#x\nhave: %#x\n", i, want, have)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
|
||||||
if !evm.StateDB.AddressInAccessList(addr) {
|
if !evm.StateDB.AddressInAccessList(addr) {
|
||||||
evm.StateDB.AddAddressToAccessList(addr)
|
evm.StateDB.AddAddressToAccessList(addr)
|
||||||
var overflow bool
|
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 {
|
if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow {
|
||||||
return 0, ErrGasUintOverflow
|
return 0, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +151,7 @@ func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Mem
|
||||||
if !evm.StateDB.AddressInAccessList(addr) {
|
if !evm.StateDB.AddressInAccessList(addr) {
|
||||||
// If the caller cannot afford the cost, this change will be rolled back
|
// If the caller cannot afford the cost, this change will be rolled back
|
||||||
evm.StateDB.AddAddressToAccessList(addr)
|
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 params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929, nil
|
||||||
}
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ type Stack struct {
|
||||||
data []uint256.Int
|
data []uint256.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newstack() *Stack {
|
func Newstack() *Stack {
|
||||||
return stackPool.Get().(*Stack)
|
return stackPool.Get().(*Stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,3 +80,27 @@ func (st *Stack) peek() *uint256.Int {
|
||||||
func (st *Stack) Back(n int) *uint256.Int {
|
func (st *Stack) Back(n int) *uint256.Int {
|
||||||
return &st.data[st.len()-n-1]
|
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()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ type txTraceResult struct {
|
||||||
// blockTraceTask represents a single block trace task when an entire chain is
|
// blockTraceTask represents a single block trace task when an entire chain is
|
||||||
// being traced.
|
// being traced.
|
||||||
type blockTraceTask struct {
|
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
|
block *types.Block // Block to trace the transactions from
|
||||||
release StateReleaseFunc // The function to release the held resource for this task
|
release StateReleaseFunc // The function to release the held resource for this task
|
||||||
results []*txTraceResult // Trace results produced by the task
|
results []*txTraceResult // Trace results produced by the task
|
||||||
|
|
@ -201,8 +201,8 @@ type blockTraceResult struct {
|
||||||
// txTraceTask represents a single transaction trace task when an entire block
|
// txTraceTask represents a single transaction trace task when an entire block
|
||||||
// is being traced.
|
// is being traced.
|
||||||
type txTraceTask struct {
|
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
|
index int // Transaction offset in the block
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraceChain returns the structured logs created during the execution of EVM
|
// TraceChain returns the structured logs created during the execution of EVM
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ type worker struct {
|
||||||
snapshotMu sync.RWMutex // The lock used to protect the snapshots below
|
snapshotMu sync.RWMutex // The lock used to protect the snapshots below
|
||||||
snapshotBlock *types.Block
|
snapshotBlock *types.Block
|
||||||
snapshotReceipts types.Receipts
|
snapshotReceipts types.Receipts
|
||||||
snapshotState *state.StateDB
|
snapshotState vm.StateDB
|
||||||
|
|
||||||
// atomic status counters
|
// atomic status counters
|
||||||
running atomic.Bool // The indicator whether the consensus engine is running or not.
|
running atomic.Bool // The indicator whether the consensus engine is running or not.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue