Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
ethtracer
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nebula
ethtracer
Commits
1fff77e7
Commit
1fff77e7
authored
Jul 07, 2025
by
luxq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update code
parent
323d4af7
Changes
23
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
184 additions
and
2463 deletions
+184
-2463
README.md
README.md
+1
-0
analysis_legacy_test.go
evm/vm/analysis_legacy_test.go
+1
-2
contracts_fuzz_test.go
evm/vm/contracts_fuzz_test.go
+2
-3
contracts_test.go
evm/vm/contracts_test.go
+36
-37
eof_test.go
evm/vm/eof_test.go
+8
-9
eof_validation_test.go
evm/vm/eof_validation_test.go
+3
-4
gas_table_test.go
evm/vm/gas_table_test.go
+0
-181
instructions.go
evm/vm/instructions.go
+7
-2
instructions_test.go
evm/vm/instructions_test.go
+0
-974
interface.go
evm/vm/interface.go
+2
-3
interpreter_test.go
evm/vm/interpreter_test.go
+0
-76
memory_test.go
evm/vm/memory_test.go
+3
-4
runtime.go
evm/vm/runtime/runtime.go
+14
-15
runtime_example_test.go
evm/vm/runtime/runtime_example_test.go
+0
-34
runtime_fuzz_test.go
evm/vm/runtime/runtime_fuzz_test.go
+0
-29
runtime_test.go
evm/vm/runtime/runtime_test.go
+0
-939
go.mod
go.mod
+7
-13
go.sum
go.sum
+10
-46
encoding.go
stateless/encoding.go
+2
-2
witness.go
stateless/witness.go
+11
-12
hooks.go
tracing/hooks.go
+9
-9
journal.go
tracing/journal.go
+2
-2
types.go
types/types.go
+66
-67
No files found.
README.md
View file @
1fff77e7
# ethtracer
# todo: modify types/transaction types/receipt types/block types/header to evm/evmtypes.
\ No newline at end of file
evm/vm/analysis_legacy_test.go
View file @
1fff77e7
...
...
@@ -17,10 +17,9 @@
package
vm
import
(
"code.wuban.net.cn/cmpchain/ethcrypto/crypto"
"math/bits"
"testing"
"github.com/ethereum/go-ethereum/crypto"
)
func
TestJumpDestAnalysis
(
t
*
testing
.
T
)
{
...
...
evm/vm/contracts_fuzz_test.go
View file @
1fff77e7
...
...
@@ -17,14 +17,13 @@
package
vm
import
(
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"testing"
"github.com/ethereum/go-ethereum/common"
)
func
FuzzPrecompiledContracts
(
f
*
testing
.
F
)
{
// Create list of addresses
var
addrs
[]
common
.
Address
var
addrs
[]
metatypes
.
Address
for
k
:=
range
allPrecompiles
{
addrs
=
append
(
addrs
,
k
)
}
...
...
evm/vm/contracts_test.go
View file @
1fff77e7
...
...
@@ -20,11 +20,10 @@ import (
"bytes"
"encoding/json"
"fmt"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"os"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
)
// precompiledTest defines the input/output pairs for precompiled contract tests.
...
...
@@ -45,26 +44,26 @@ type precompiledFailureTest struct {
// allPrecompiles does not map to the actual set of precompiles, as it also contains
// repriced versions of precompiles at certain slots
var
allPrecompiles
=
map
[
common
.
Address
]
PrecompiledContract
{
common
.
BytesToAddress
([]
byte
{
1
})
:
&
ecrecover
{},
common
.
BytesToAddress
([]
byte
{
2
})
:
&
sha256hash
{},
common
.
BytesToAddress
([]
byte
{
3
})
:
&
ripemd160hash
{},
common
.
BytesToAddress
([]
byte
{
4
})
:
&
dataCopy
{},
common
.
BytesToAddress
([]
byte
{
5
})
:
&
bigModExp
{
eip2565
:
false
},
common
.
BytesToAddress
([]
byte
{
0xf5
})
:
&
bigModExp
{
eip2565
:
true
},
common
.
BytesToAddress
([]
byte
{
6
})
:
&
bn256AddIstanbul
{},
common
.
BytesToAddress
([]
byte
{
7
})
:
&
bn256ScalarMulIstanbul
{},
common
.
BytesToAddress
([]
byte
{
8
})
:
&
bn256PairingIstanbul
{},
common
.
BytesToAddress
([]
byte
{
9
})
:
&
blake2F
{},
common
.
BytesToAddress
([]
byte
{
0x0a
})
:
&
kzgPointEvaluation
{},
common
.
BytesToAddress
([]
byte
{
0x0f
,
0x0a
})
:
&
bls12381G1Add
{},
common
.
BytesToAddress
([]
byte
{
0x0f
,
0x0b
})
:
&
bls12381G1MultiExp
{},
common
.
BytesToAddress
([]
byte
{
0x0f
,
0x0c
})
:
&
bls12381G2Add
{},
common
.
BytesToAddress
([]
byte
{
0x0f
,
0x0d
})
:
&
bls12381G2MultiExp
{},
common
.
BytesToAddress
([]
byte
{
0x0f
,
0x0e
})
:
&
bls12381Pairing
{},
common
.
BytesToAddress
([]
byte
{
0x0f
,
0x0f
})
:
&
bls12381MapG1
{},
common
.
BytesToAddress
([]
byte
{
0x0f
,
0x10
})
:
&
bls12381MapG2
{},
var
allPrecompiles
=
map
[
metatypes
.
Address
]
PrecompiledContract
{
metatypes
.
BytesToAddress
([]
byte
{
1
})
:
&
ecrecover
{},
metatypes
.
BytesToAddress
([]
byte
{
2
})
:
&
sha256hash
{},
metatypes
.
BytesToAddress
([]
byte
{
3
})
:
&
ripemd160hash
{},
metatypes
.
BytesToAddress
([]
byte
{
4
})
:
&
dataCopy
{},
metatypes
.
BytesToAddress
([]
byte
{
5
})
:
&
bigModExp
{
eip2565
:
false
},
metatypes
.
BytesToAddress
([]
byte
{
0xf5
})
:
&
bigModExp
{
eip2565
:
true
},
metatypes
.
BytesToAddress
([]
byte
{
6
})
:
&
bn256AddIstanbul
{},
metatypes
.
BytesToAddress
([]
byte
{
7
})
:
&
bn256ScalarMulIstanbul
{},
metatypes
.
BytesToAddress
([]
byte
{
8
})
:
&
bn256PairingIstanbul
{},
metatypes
.
BytesToAddress
([]
byte
{
9
})
:
&
blake2F
{},
metatypes
.
BytesToAddress
([]
byte
{
0x0a
})
:
&
kzgPointEvaluation
{},
metatypes
.
BytesToAddress
([]
byte
{
0x0f
,
0x0a
})
:
&
bls12381G1Add
{},
metatypes
.
BytesToAddress
([]
byte
{
0x0f
,
0x0b
})
:
&
bls12381G1MultiExp
{},
metatypes
.
BytesToAddress
([]
byte
{
0x0f
,
0x0c
})
:
&
bls12381G2Add
{},
metatypes
.
BytesToAddress
([]
byte
{
0x0f
,
0x0d
})
:
&
bls12381G2MultiExp
{},
metatypes
.
BytesToAddress
([]
byte
{
0x0f
,
0x0e
})
:
&
bls12381Pairing
{},
metatypes
.
BytesToAddress
([]
byte
{
0x0f
,
0x0f
})
:
&
bls12381MapG1
{},
metatypes
.
BytesToAddress
([]
byte
{
0x0f
,
0x10
})
:
&
bls12381MapG2
{},
}
// EIP-152 test vectors
...
...
@@ -92,20 +91,20 @@ var blake2FMalformedInputTests = []precompiledFailureTest{
}
func
testPrecompiled
(
addr
string
,
test
precompiledTest
,
t
*
testing
.
T
)
{
p
:=
allPrecompiles
[
common
.
HexToAddress
(
addr
)]
in
:=
common
.
Hex2Bytes
(
test
.
Input
)
p
:=
allPrecompiles
[
metatypes
.
HexToAddress
(
addr
)]
in
:=
metatypes
.
Hex2Bytes
(
test
.
Input
)
gas
:=
p
.
RequiredGas
(
in
)
t
.
Run
(
fmt
.
Sprintf
(
"%s-Gas=%d"
,
test
.
Name
,
gas
),
func
(
t
*
testing
.
T
)
{
if
res
,
_
,
err
:=
RunPrecompiledContract
(
p
,
in
,
gas
,
nil
);
err
!=
nil
{
t
.
Error
(
err
)
}
else
if
common
.
Bytes2Hex
(
res
)
!=
test
.
Expected
{
t
.
Errorf
(
"Expected %v, got %v"
,
test
.
Expected
,
common
.
Bytes2Hex
(
res
))
}
else
if
metatypes
.
Bytes2Hex
(
res
)
!=
test
.
Expected
{
t
.
Errorf
(
"Expected %v, got %v"
,
test
.
Expected
,
metatypes
.
Bytes2Hex
(
res
))
}
if
expGas
:=
test
.
Gas
;
expGas
!=
gas
{
t
.
Errorf
(
"%v: gas wrong, expected %d, got %d"
,
test
.
Name
,
expGas
,
gas
)
}
// Verify that the precompile did not touch the input buffer
exp
:=
common
.
Hex2Bytes
(
test
.
Input
)
exp
:=
metatypes
.
Hex2Bytes
(
test
.
Input
)
if
!
bytes
.
Equal
(
in
,
exp
)
{
t
.
Errorf
(
"Precompiled %v modified input data"
,
addr
)
}
...
...
@@ -113,8 +112,8 @@ func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
}
func
testPrecompiledOOG
(
addr
string
,
test
precompiledTest
,
t
*
testing
.
T
)
{
p
:=
allPrecompiles
[
common
.
HexToAddress
(
addr
)]
in
:=
common
.
Hex2Bytes
(
test
.
Input
)
p
:=
allPrecompiles
[
metatypes
.
HexToAddress
(
addr
)]
in
:=
metatypes
.
Hex2Bytes
(
test
.
Input
)
gas
:=
p
.
RequiredGas
(
in
)
-
1
t
.
Run
(
fmt
.
Sprintf
(
"%s-Gas=%d"
,
test
.
Name
,
gas
),
func
(
t
*
testing
.
T
)
{
...
...
@@ -123,7 +122,7 @@ func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
t
.
Errorf
(
"Expected error [out of gas], got [%v]"
,
err
)
}
// Verify that the precompile did not touch the input buffer
exp
:=
common
.
Hex2Bytes
(
test
.
Input
)
exp
:=
metatypes
.
Hex2Bytes
(
test
.
Input
)
if
!
bytes
.
Equal
(
in
,
exp
)
{
t
.
Errorf
(
"Precompiled %v modified input data"
,
addr
)
}
...
...
@@ -131,8 +130,8 @@ func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
}
func
testPrecompiledFailure
(
addr
string
,
test
precompiledFailureTest
,
t
*
testing
.
T
)
{
p
:=
allPrecompiles
[
common
.
HexToAddress
(
addr
)]
in
:=
common
.
Hex2Bytes
(
test
.
Input
)
p
:=
allPrecompiles
[
metatypes
.
HexToAddress
(
addr
)]
in
:=
metatypes
.
Hex2Bytes
(
test
.
Input
)
gas
:=
p
.
RequiredGas
(
in
)
t
.
Run
(
test
.
Name
,
func
(
t
*
testing
.
T
)
{
_
,
_
,
err
:=
RunPrecompiledContract
(
p
,
in
,
gas
,
nil
)
...
...
@@ -140,7 +139,7 @@ func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing
t
.
Errorf
(
"Expected error [%v], got [%v]"
,
test
.
ExpectedError
,
err
)
}
// Verify that the precompile did not touch the input buffer
exp
:=
common
.
Hex2Bytes
(
test
.
Input
)
exp
:=
metatypes
.
Hex2Bytes
(
test
.
Input
)
if
!
bytes
.
Equal
(
in
,
exp
)
{
t
.
Errorf
(
"Precompiled %v modified input data"
,
addr
)
}
...
...
@@ -151,8 +150,8 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
if
test
.
NoBenchmark
{
return
}
p
:=
allPrecompiles
[
common
.
HexToAddress
(
addr
)]
in
:=
common
.
Hex2Bytes
(
test
.
Input
)
p
:=
allPrecompiles
[
metatypes
.
HexToAddress
(
addr
)]
in
:=
metatypes
.
Hex2Bytes
(
test
.
Input
)
reqGas
:=
p
.
RequiredGas
(
in
)
var
(
...
...
@@ -184,8 +183,8 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
bench
.
Error
(
err
)
return
}
if
common
.
Bytes2Hex
(
res
)
!=
test
.
Expected
{
bench
.
Errorf
(
"Expected %v, got %v"
,
test
.
Expected
,
common
.
Bytes2Hex
(
res
))
if
metatypes
.
Bytes2Hex
(
res
)
!=
test
.
Expected
{
bench
.
Errorf
(
"Expected %v, got %v"
,
test
.
Expected
,
metatypes
.
Bytes2Hex
(
res
))
return
}
})
...
...
evm/vm/eof_test.go
View file @
1fff77e7
...
...
@@ -18,10 +18,9 @@ package vm
import
(
"encoding/hex"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"reflect"
"testing"
"github.com/ethereum/go-ethereum/common"
)
func
TestEOFMarshaling
(
t
*
testing
.
T
)
{
...
...
@@ -32,7 +31,7 @@ func TestEOFMarshaling(t *testing.T) {
{
want
:
Container
{
types
:
[]
*
functionMetadata
{{
inputs
:
0
,
outputs
:
0x80
,
maxStackHeight
:
1
}},
codeSections
:
[][]
byte
{
common
.
Hex2Bytes
(
"604200"
)},
codeSections
:
[][]
byte
{
metatypes
.
Hex2Bytes
(
"604200"
)},
data
:
[]
byte
{
0x01
,
0x02
,
0x03
},
dataSize
:
3
,
},
...
...
@@ -40,7 +39,7 @@ func TestEOFMarshaling(t *testing.T) {
{
want
:
Container
{
types
:
[]
*
functionMetadata
{{
inputs
:
0
,
outputs
:
0x80
,
maxStackHeight
:
1
}},
codeSections
:
[][]
byte
{
common
.
Hex2Bytes
(
"604200"
)},
codeSections
:
[][]
byte
{
metatypes
.
Hex2Bytes
(
"604200"
)},
data
:
[]
byte
{
0x01
,
0x02
,
0x03
},
dataSize
:
3
,
},
...
...
@@ -53,9 +52,9 @@ func TestEOFMarshaling(t *testing.T) {
{
inputs
:
1
,
outputs
:
1
,
maxStackHeight
:
1
},
},
codeSections
:
[][]
byte
{
common
.
Hex2Bytes
(
"604200"
),
common
.
Hex2Bytes
(
"6042604200"
),
common
.
Hex2Bytes
(
"00"
),
metatypes
.
Hex2Bytes
(
"604200"
),
metatypes
.
Hex2Bytes
(
"6042604200"
),
metatypes
.
Hex2Bytes
(
"00"
),
},
data
:
[]
byte
{},
},
...
...
@@ -77,12 +76,12 @@ func TestEOFMarshaling(t *testing.T) {
func
TestEOFSubcontainer
(
t
*
testing
.
T
)
{
var
subcontainer
=
new
(
Container
)
if
err
:=
subcontainer
.
UnmarshalBinary
(
common
.
Hex2Bytes
(
"ef000101000402000100010400000000800000fe"
),
true
);
err
!=
nil
{
if
err
:=
subcontainer
.
UnmarshalBinary
(
metatypes
.
Hex2Bytes
(
"ef000101000402000100010400000000800000fe"
),
true
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
container
:=
Container
{
types
:
[]
*
functionMetadata
{{
inputs
:
0
,
outputs
:
0x80
,
maxStackHeight
:
1
}},
codeSections
:
[][]
byte
{
common
.
Hex2Bytes
(
"604200"
)},
codeSections
:
[][]
byte
{
metatypes
.
Hex2Bytes
(
"604200"
)},
subContainers
:
[]
*
Container
{
subcontainer
},
data
:
[]
byte
{
0x01
,
0x02
,
0x03
},
dataSize
:
3
,
...
...
evm/vm/eof_validation_test.go
View file @
1fff77e7
...
...
@@ -17,12 +17,11 @@
package
vm
import
(
"code.wuban.net.cn/cmpchain/ethtracer/params"
"encoding/binary"
"errors"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
func
TestValidateCode
(
t
*
testing
.
T
)
{
...
...
@@ -253,7 +252,7 @@ func TestValidateCode(t *testing.T) {
}
_
,
err
:=
validateCode
(
test
.
code
,
test
.
section
,
container
,
&
eofInstructionSet
,
false
)
if
!
errors
.
Is
(
err
,
test
.
err
)
{
t
.
Errorf
(
"test %d (%s): unexpected error (want: %v, got: %v)"
,
i
,
common
.
Bytes2Hex
(
test
.
code
),
test
.
err
,
err
)
t
.
Errorf
(
"test %d (%s): unexpected error (want: %v, got: %v)"
,
i
,
metatypes
.
Bytes2Hex
(
test
.
code
),
test
.
err
,
err
)
}
}
}
...
...
evm/vm/gas_table_test.go
deleted
100644 → 0
View file @
323d4af7
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
vm
import
(
"bytes"
"errors"
"math"
"math/big"
"sort"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)
func
TestMemoryGasCost
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
size
uint64
cost
uint64
overflow
bool
}{
{
0x1fffffffe0
,
36028809887088637
,
false
},
{
0x1fffffffe1
,
0
,
true
},
}
for
i
,
tt
:=
range
tests
{
v
,
err
:=
memoryGasCost
(
&
Memory
{},
tt
.
size
)
if
(
err
==
ErrGasUintOverflow
)
!=
tt
.
overflow
{
t
.
Errorf
(
"test %d: overflow mismatch: have %v, want %v"
,
i
,
err
==
ErrGasUintOverflow
,
tt
.
overflow
)
}
if
v
!=
tt
.
cost
{
t
.
Errorf
(
"test %d: gas cost mismatch: have %v, want %v"
,
i
,
v
,
tt
.
cost
)
}
}
}
var
eip2200Tests
=
[]
struct
{
original
byte
gaspool
uint64
input
string
used
uint64
refund
uint64
failure
error
}{
{
0
,
math
.
MaxUint64
,
"0x60006000556000600055"
,
1612
,
0
,
nil
},
// 0 -> 0 -> 0
{
0
,
math
.
MaxUint64
,
"0x60006000556001600055"
,
20812
,
0
,
nil
},
// 0 -> 0 -> 1
{
0
,
math
.
MaxUint64
,
"0x60016000556000600055"
,
20812
,
19200
,
nil
},
// 0 -> 1 -> 0
{
0
,
math
.
MaxUint64
,
"0x60016000556002600055"
,
20812
,
0
,
nil
},
// 0 -> 1 -> 2
{
0
,
math
.
MaxUint64
,
"0x60016000556001600055"
,
20812
,
0
,
nil
},
// 0 -> 1 -> 1
{
1
,
math
.
MaxUint64
,
"0x60006000556000600055"
,
5812
,
15000
,
nil
},
// 1 -> 0 -> 0
{
1
,
math
.
MaxUint64
,
"0x60006000556001600055"
,
5812
,
4200
,
nil
},
// 1 -> 0 -> 1
{
1
,
math
.
MaxUint64
,
"0x60006000556002600055"
,
5812
,
0
,
nil
},
// 1 -> 0 -> 2
{
1
,
math
.
MaxUint64
,
"0x60026000556000600055"
,
5812
,
15000
,
nil
},
// 1 -> 2 -> 0
{
1
,
math
.
MaxUint64
,
"0x60026000556003600055"
,
5812
,
0
,
nil
},
// 1 -> 2 -> 3
{
1
,
math
.
MaxUint64
,
"0x60026000556001600055"
,
5812
,
4200
,
nil
},
// 1 -> 2 -> 1
{
1
,
math
.
MaxUint64
,
"0x60026000556002600055"
,
5812
,
0
,
nil
},
// 1 -> 2 -> 2
{
1
,
math
.
MaxUint64
,
"0x60016000556000600055"
,
5812
,
15000
,
nil
},
// 1 -> 1 -> 0
{
1
,
math
.
MaxUint64
,
"0x60016000556002600055"
,
5812
,
0
,
nil
},
// 1 -> 1 -> 2
{
1
,
math
.
MaxUint64
,
"0x60016000556001600055"
,
1612
,
0
,
nil
},
// 1 -> 1 -> 1
{
0
,
math
.
MaxUint64
,
"0x600160005560006000556001600055"
,
40818
,
19200
,
nil
},
// 0 -> 1 -> 0 -> 1
{
1
,
math
.
MaxUint64
,
"0x600060005560016000556000600055"
,
10818
,
19200
,
nil
},
// 1 -> 0 -> 1 -> 0
{
1
,
2306
,
"0x6001600055"
,
2306
,
0
,
ErrOutOfGas
},
// 1 -> 1 (2300 sentry + 2xPUSH)
{
1
,
2307
,
"0x6001600055"
,
806
,
0
,
nil
},
// 1 -> 1 (2301 sentry + 2xPUSH)
}
func
TestEIP2200
(
t
*
testing
.
T
)
{
for
i
,
tt
:=
range
eip2200Tests
{
address
:=
common
.
BytesToAddress
([]
byte
(
"contract"
))
statedb
,
_
:=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
statedb
.
CreateAccount
(
address
)
statedb
.
SetCode
(
address
,
hexutil
.
MustDecode
(
tt
.
input
))
statedb
.
SetState
(
address
,
common
.
Hash
{},
common
.
BytesToHash
([]
byte
{
tt
.
original
}))
statedb
.
Finalise
(
true
)
// Push the state into the "original" slot
vmctx
:=
BlockContext
{
CanTransfer
:
func
(
StateDB
,
common
.
Address
,
*
uint256
.
Int
)
bool
{
return
true
},
Transfer
:
func
(
StateDB
,
common
.
Address
,
common
.
Address
,
*
uint256
.
Int
)
{},
}
evm
:=
NewEVM
(
vmctx
,
statedb
,
params
.
AllEthashProtocolChanges
,
Config
{
ExtraEips
:
[]
int
{
2200
}})
_
,
gas
,
err
:=
evm
.
Call
(
common
.
Address
{},
address
,
nil
,
tt
.
gaspool
,
new
(
uint256
.
Int
))
if
!
errors
.
Is
(
err
,
tt
.
failure
)
{
t
.
Errorf
(
"test %d: failure mismatch: have %v, want %v"
,
i
,
err
,
tt
.
failure
)
}
if
used
:=
tt
.
gaspool
-
gas
;
used
!=
tt
.
used
{
t
.
Errorf
(
"test %d: gas used mismatch: have %v, want %v"
,
i
,
used
,
tt
.
used
)
}
if
refund
:=
evm
.
StateDB
.
GetRefund
();
refund
!=
tt
.
refund
{
t
.
Errorf
(
"test %d: gas refund mismatch: have %v, want %v"
,
i
,
refund
,
tt
.
refund
)
}
}
}
var
createGasTests
=
[]
struct
{
code
string
eip3860
bool
gasUsed
uint64
minimumGas
uint64
}{
// legacy create(0, 0, 0xc000) without 3860 used
{
"0x61C00060006000f0"
+
"600052"
+
"60206000F3"
,
false
,
41237
,
41237
},
// legacy create(0, 0, 0xc000) _with_ 3860
{
"0x61C00060006000f0"
+
"600052"
+
"60206000F3"
,
true
,
44309
,
44309
},
// create2(0, 0, 0xc001, 0) without 3860
{
"0x600061C00160006000f5"
+
"600052"
+
"60206000F3"
,
false
,
50471
,
50471
},
// create2(0, 0, 0xc001, 0) (too large), with 3860
{
"0x600061C00160006000f5"
+
"600052"
+
"60206000F3"
,
true
,
32012
,
100
_000
},
// create2(0, 0, 0xc000, 0)
// This case is trying to deploy code at (within) the limit
{
"0x600061C00060006000f5"
+
"600052"
+
"60206000F3"
,
true
,
53528
,
53528
},
// create2(0, 0, 0xc001, 0)
// This case is trying to deploy code exceeding the limit
{
"0x600061C00160006000f5"
+
"600052"
+
"60206000F3"
,
true
,
32024
,
100000
},
}
func
TestCreateGas
(
t
*
testing
.
T
)
{
for
i
,
tt
:=
range
createGasTests
{
var
gasUsed
=
uint64
(
0
)
doCheck
:=
func
(
testGas
int
)
bool
{
address
:=
common
.
BytesToAddress
([]
byte
(
"contract"
))
statedb
,
_
:=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
statedb
.
CreateAccount
(
address
)
statedb
.
SetCode
(
address
,
hexutil
.
MustDecode
(
tt
.
code
))
statedb
.
Finalise
(
true
)
vmctx
:=
BlockContext
{
CanTransfer
:
func
(
StateDB
,
common
.
Address
,
*
uint256
.
Int
)
bool
{
return
true
},
Transfer
:
func
(
StateDB
,
common
.
Address
,
common
.
Address
,
*
uint256
.
Int
)
{},
BlockNumber
:
big
.
NewInt
(
0
),
}
config
:=
Config
{}
if
tt
.
eip3860
{
config
.
ExtraEips
=
[]
int
{
3860
}
}
evm
:=
NewEVM
(
vmctx
,
statedb
,
params
.
AllEthashProtocolChanges
,
config
)
var
startGas
=
uint64
(
testGas
)
ret
,
gas
,
err
:=
evm
.
Call
(
common
.
Address
{},
address
,
nil
,
startGas
,
new
(
uint256
.
Int
))
if
err
!=
nil
{
return
false
}
gasUsed
=
startGas
-
gas
if
len
(
ret
)
!=
32
{
t
.
Fatalf
(
"test %d: expected 32 bytes returned, have %d"
,
i
,
len
(
ret
))
}
if
bytes
.
Equal
(
ret
,
make
([]
byte
,
32
))
{
// Failure
return
false
}
return
true
}
minGas
:=
sort
.
Search
(
100
_000
,
doCheck
)
if
uint64
(
minGas
)
!=
tt
.
minimumGas
{
t
.
Fatalf
(
"test %d: min gas error, want %d, have %d"
,
i
,
tt
.
minimumGas
,
minGas
)
}
// If the deployment succeeded, we also check the gas used
if
minGas
<
100
_000
{
if
gasUsed
!=
tt
.
gasUsed
{
t
.
Errorf
(
"test %d: gas used mismatch: have %v, want %v"
,
i
,
gasUsed
,
tt
.
gasUsed
)
}
}
}
}
evm/vm/instructions.go
View file @
1fff77e7
...
...
@@ -18,9 +18,9 @@ package vm
import
(
"code.wuban.net.cn/cmpchain/ethcrypto/crypto"
"code.wuban.net.cn/cmpchain/ethtracer/evm/evmtypes"
"code.wuban.net.cn/cmpchain/ethtracer/params"
"code.wuban.net.cn/cmpchain/ethtracer/tracing"
"code.wuban.net.cn/cmpchain/ethtracer/types"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"math"
...
...
@@ -943,7 +943,12 @@ func makeLog(size int) executionFunc {
}
d
:=
scope
.
Memory
.
GetCopy
(
mStart
.
Uint64
(),
mSize
.
Uint64
())
interpreter
.
evm
.
StateDB
.
AddLog
(
types
.
NewLog
(
scope
.
Contract
.
Address
(),
topics
,
d
,
interpreter
.
evm
.
Context
.
BlockNumber
.
Uint64
()))
interpreter
.
evm
.
StateDB
.
AddLog
(
&
evmtypes
.
Log
{
Address
:
scope
.
Contract
.
Address
(),
Topics
:
topics
,
Data
:
d
,
BlockNumber
:
interpreter
.
evm
.
Context
.
BlockNumber
.
Uint64
(),
})
return
nil
,
nil
}
...
...
evm/vm/instructions_test.go
deleted
100644 → 0
View file @
323d4af7
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
vm
import
(
"bytes"
"encoding/json"
"fmt"
"math/big"
"os"
"strings"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)
type
TwoOperandTestcase
struct
{
X
string
Y
string
Expected
string
}
type
twoOperandParams
struct
{
x
string
y
string
}
var
alphabetSoup
=
"ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
var
commonParams
[]
*
twoOperandParams
var
twoOpMethods
map
[
string
]
executionFunc
func
init
()
{
// Params is a list of common edgecases that should be used for some common tests
params
:=
[]
string
{
"0000000000000000000000000000000000000000000000000000000000000000"
,
// 0
"0000000000000000000000000000000000000000000000000000000000000001"
,
// +1
"0000000000000000000000000000000000000000000000000000000000000005"
,
// +5
"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
,
// + max -1
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
// + max
"8000000000000000000000000000000000000000000000000000000000000000"
,
// - max
"8000000000000000000000000000000000000000000000000000000000000001"
,
// - max+1
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"
,
// - 5
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
// - 1
}
// Params are combined so each param is used on each 'side'
commonParams
=
make
([]
*
twoOperandParams
,
len
(
params
)
*
len
(
params
))
for
i
,
x
:=
range
params
{
for
j
,
y
:=
range
params
{
commonParams
[
i
*
len
(
params
)
+
j
]
=
&
twoOperandParams
{
x
,
y
}
}
}
twoOpMethods
=
map
[
string
]
executionFunc
{
"add"
:
opAdd
,
"sub"
:
opSub
,
"mul"
:
opMul
,
"div"
:
opDiv
,
"sdiv"
:
opSdiv
,
"mod"
:
opMod
,
"smod"
:
opSmod
,
"exp"
:
opExp
,
"signext"
:
opSignExtend
,
"lt"
:
opLt
,
"gt"
:
opGt
,
"slt"
:
opSlt
,
"sgt"
:
opSgt
,
"eq"
:
opEq
,
"and"
:
opAnd
,
"or"
:
opOr
,
"xor"
:
opXor
,
"byte"
:
opByte
,
"shl"
:
opSHL
,
"shr"
:
opSHR
,
"sar"
:
opSAR
,
}
}
func
testTwoOperandOp
(
t
*
testing
.
T
,
tests
[]
TwoOperandTestcase
,
opFn
executionFunc
,
name
string
)
{
var
(
evm
=
NewEVM
(
BlockContext
{},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
pc
=
uint64
(
0
)
)
for
i
,
test
:=
range
tests
{
x
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
X
))
y
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
Y
))
expected
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
Expected
))
stack
.
push
(
x
)
stack
.
push
(
y
)
opFn
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
nil
,
stack
,
nil
})
if
len
(
stack
.
data
)
!=
1
{
t
.
Errorf
(
"Expected one item on stack after %v, got %d: "
,
name
,
len
(
stack
.
data
))
}
actual
:=
stack
.
pop
()
if
actual
.
Cmp
(
expected
)
!=
0
{
t
.
Errorf
(
"Testcase %v %d, %v(%x, %x): expected %x, got %x"
,
name
,
i
,
name
,
x
,
y
,
expected
,
actual
)
}
}
}
func
TestByteOp
(
t
*
testing
.
T
)
{
tests
:=
[]
TwoOperandTestcase
{
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
"00"
,
"AB"
},
{
"ABCDEF0908070605040302010000000000000000000000000000000000000000"
,
"01"
,
"CD"
},
{
"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
,
"00"
,
"00"
},
{
"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
,
"01"
,
"CD"
},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
"1F"
,
"30"
},
{
"0000000000000000000000000000000000000000000000000000000000102030"
,
"1E"
,
"20"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"20"
,
"00"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"FFFFFFFFFFFFFFFF"
,
"00"
},
}
testTwoOperandOp
(
t
,
tests
,
opByte
,
"byte"
)
}
func
TestSHL
(
t
*
testing
.
T
)
{
// Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shl-shift-left
tests
:=
[]
TwoOperandTestcase
{
{
"0000000000000000000000000000000000000000000000000000000000000001"
,
"01"
,
"0000000000000000000000000000000000000000000000000000000000000002"
},
{
"0000000000000000000000000000000000000000000000000000000000000001"
,
"ff"
,
"8000000000000000000000000000000000000000000000000000000000000000"
},
{
"0000000000000000000000000000000000000000000000000000000000000001"
,
"0100"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"0000000000000000000000000000000000000000000000000000000000000001"
,
"0101"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"00"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"01"
,
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"ff"
,
"8000000000000000000000000000000000000000000000000000000000000000"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"0100"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"0000000000000000000000000000000000000000000000000000000000000000"
,
"01"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"01"
,
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
},
}
testTwoOperandOp
(
t
,
tests
,
opSHL
,
"shl"
)
}
func
TestSHR
(
t
*
testing
.
T
)
{
// Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shr-logical-shift-right
tests
:=
[]
TwoOperandTestcase
{
{
"0000000000000000000000000000000000000000000000000000000000000001"
,
"00"
,
"0000000000000000000000000000000000000000000000000000000000000001"
},
{
"0000000000000000000000000000000000000000000000000000000000000001"
,
"01"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"8000000000000000000000000000000000000000000000000000000000000000"
,
"01"
,
"4000000000000000000000000000000000000000000000000000000000000000"
},
{
"8000000000000000000000000000000000000000000000000000000000000000"
,
"ff"
,
"0000000000000000000000000000000000000000000000000000000000000001"
},
{
"8000000000000000000000000000000000000000000000000000000000000000"
,
"0100"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"8000000000000000000000000000000000000000000000000000000000000000"
,
"0101"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"00"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"01"
,
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"ff"
,
"0000000000000000000000000000000000000000000000000000000000000001"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"0100"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"0000000000000000000000000000000000000000000000000000000000000000"
,
"01"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
}
testTwoOperandOp
(
t
,
tests
,
opSHR
,
"shr"
)
}
func
TestSAR
(
t
*
testing
.
T
)
{
// Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#sar-arithmetic-shift-right
tests
:=
[]
TwoOperandTestcase
{
{
"0000000000000000000000000000000000000000000000000000000000000001"
,
"00"
,
"0000000000000000000000000000000000000000000000000000000000000001"
},
{
"0000000000000000000000000000000000000000000000000000000000000001"
,
"01"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"8000000000000000000000000000000000000000000000000000000000000000"
,
"01"
,
"c000000000000000000000000000000000000000000000000000000000000000"
},
{
"8000000000000000000000000000000000000000000000000000000000000000"
,
"ff"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"8000000000000000000000000000000000000000000000000000000000000000"
,
"0100"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"8000000000000000000000000000000000000000000000000000000000000000"
,
"0101"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"00"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"01"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"ff"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"0100"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
},
{
"0000000000000000000000000000000000000000000000000000000000000000"
,
"01"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"4000000000000000000000000000000000000000000000000000000000000000"
,
"fe"
,
"0000000000000000000000000000000000000000000000000000000000000001"
},
{
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"f8"
,
"000000000000000000000000000000000000000000000000000000000000007f"
},
{
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"fe"
,
"0000000000000000000000000000000000000000000000000000000000000001"
},
{
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"ff"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
{
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"0100"
,
"0000000000000000000000000000000000000000000000000000000000000000"
},
}
testTwoOperandOp
(
t
,
tests
,
opSAR
,
"sar"
)
}
func
TestAddMod
(
t
*
testing
.
T
)
{
var
(
evm
=
NewEVM
(
BlockContext
{},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
pc
=
uint64
(
0
)
)
tests
:=
[]
struct
{
x
string
y
string
z
string
expected
string
}{
{
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
,
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
,
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
,
},
}
// x + y = 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
// in 256 bit repr, fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
for
i
,
test
:=
range
tests
{
x
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
x
))
y
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
y
))
z
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
z
))
expected
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
test
.
expected
))
stack
.
push
(
z
)
stack
.
push
(
y
)
stack
.
push
(
x
)
opAddmod
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
nil
,
stack
,
nil
})
actual
:=
stack
.
pop
()
if
actual
.
Cmp
(
expected
)
!=
0
{
t
.
Errorf
(
"Testcase %d, expected %x, got %x"
,
i
,
expected
,
actual
)
}
}
}
// utility function to fill the json-file with testcases
// Enable this test to generate the 'testcases_xx.json' files
func
TestWriteExpectedValues
(
t
*
testing
.
T
)
{
t
.
Skip
(
"Enable this test to create json test cases."
)
// getResult is a convenience function to generate the expected values
getResult
:=
func
(
args
[]
*
twoOperandParams
,
opFn
executionFunc
)
[]
TwoOperandTestcase
{
var
(
evm
=
NewEVM
(
BlockContext
{},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
pc
=
uint64
(
0
)
)
result
:=
make
([]
TwoOperandTestcase
,
len
(
args
))
for
i
,
param
:=
range
args
{
x
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
param
.
x
))
y
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
param
.
y
))
stack
.
push
(
x
)
stack
.
push
(
y
)
opFn
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
nil
,
stack
,
nil
})
actual
:=
stack
.
pop
()
result
[
i
]
=
TwoOperandTestcase
{
param
.
x
,
param
.
y
,
fmt
.
Sprintf
(
"%064x"
,
actual
)}
}
return
result
}
for
name
,
method
:=
range
twoOpMethods
{
data
,
err
:=
json
.
Marshal
(
getResult
(
commonParams
,
method
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
_
=
os
.
WriteFile
(
fmt
.
Sprintf
(
"testdata/testcases_%v.json"
,
name
),
data
,
0644
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
}
}
// TestJsonTestcases runs through all the testcases defined as json-files
func
TestJsonTestcases
(
t
*
testing
.
T
)
{
for
name
:=
range
twoOpMethods
{
data
,
err
:=
os
.
ReadFile
(
fmt
.
Sprintf
(
"testdata/testcases_%v.json"
,
name
))
if
err
!=
nil
{
t
.
Fatal
(
"Failed to read file"
,
err
)
}
var
testcases
[]
TwoOperandTestcase
json
.
Unmarshal
(
data
,
&
testcases
)
testTwoOperandOp
(
t
,
testcases
,
twoOpMethods
[
name
],
name
)
}
}
func
opBenchmark
(
bench
*
testing
.
B
,
op
executionFunc
,
args
...
string
)
{
var
(
evm
=
NewEVM
(
BlockContext
{},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
scope
=
&
ScopeContext
{
nil
,
stack
,
nil
}
)
// convert args
intArgs
:=
make
([]
*
uint256
.
Int
,
len
(
args
))
for
i
,
arg
:=
range
args
{
intArgs
[
i
]
=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
arg
))
}
pc
:=
uint64
(
0
)
bench
.
ResetTimer
()
for
i
:=
0
;
i
<
bench
.
N
;
i
++
{
for
_
,
arg
:=
range
intArgs
{
stack
.
push
(
arg
)
}
op
(
&
pc
,
evm
.
interpreter
,
scope
)
stack
.
pop
()
}
bench
.
StopTimer
()
for
i
,
arg
:=
range
args
{
want
:=
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
arg
))
if
have
:=
intArgs
[
i
];
!
want
.
Eq
(
have
)
{
bench
.
Fatalf
(
"input #%d mutated, have %x want %x"
,
i
,
have
,
want
)
}
}
}
func
BenchmarkOpAdd64
(
b
*
testing
.
B
)
{
x
:=
"ffffffff"
y
:=
"fd37f3e2bba2c4f"
opBenchmark
(
b
,
opAdd
,
x
,
y
)
}
func
BenchmarkOpAdd128
(
b
*
testing
.
B
)
{
x
:=
"ffffffffffffffff"
y
:=
"f5470b43c6549b016288e9a65629687"
opBenchmark
(
b
,
opAdd
,
x
,
y
)
}
func
BenchmarkOpAdd256
(
b
*
testing
.
B
)
{
x
:=
"0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9"
y
:=
"a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57"
opBenchmark
(
b
,
opAdd
,
x
,
y
)
}
func
BenchmarkOpSub64
(
b
*
testing
.
B
)
{
x
:=
"51022b6317003a9d"
y
:=
"a20456c62e00753a"
opBenchmark
(
b
,
opSub
,
x
,
y
)
}
func
BenchmarkOpSub128
(
b
*
testing
.
B
)
{
x
:=
"4dde30faaacdc14d00327aac314e915d"
y
:=
"9bbc61f5559b829a0064f558629d22ba"
opBenchmark
(
b
,
opSub
,
x
,
y
)
}
func
BenchmarkOpSub256
(
b
*
testing
.
B
)
{
x
:=
"4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37"
y
:=
"97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e"
opBenchmark
(
b
,
opSub
,
x
,
y
)
}
func
BenchmarkOpMul
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opMul
,
x
,
y
)
}
func
BenchmarkOpDiv256
(
b
*
testing
.
B
)
{
x
:=
"ff3f9014f20db29ae04af2c2d265de17"
y
:=
"fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
opBenchmark
(
b
,
opDiv
,
x
,
y
)
}
func
BenchmarkOpDiv128
(
b
*
testing
.
B
)
{
x
:=
"fdedc7f10142ff97"
y
:=
"fbdfda0e2ce356173d1993d5f70a2b11"
opBenchmark
(
b
,
opDiv
,
x
,
y
)
}
func
BenchmarkOpDiv64
(
b
*
testing
.
B
)
{
x
:=
"fcb34eb3"
y
:=
"f97180878e839129"
opBenchmark
(
b
,
opDiv
,
x
,
y
)
}
func
BenchmarkOpSdiv
(
b
*
testing
.
B
)
{
x
:=
"ff3f9014f20db29ae04af2c2d265de17"
y
:=
"fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
opBenchmark
(
b
,
opSdiv
,
x
,
y
)
}
func
BenchmarkOpMod
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opMod
,
x
,
y
)
}
func
BenchmarkOpSmod
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opSmod
,
x
,
y
)
}
func
BenchmarkOpExp
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opExp
,
x
,
y
)
}
func
BenchmarkOpSignExtend
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opSignExtend
,
x
,
y
)
}
func
BenchmarkOpLt
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opLt
,
x
,
y
)
}
func
BenchmarkOpGt
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opGt
,
x
,
y
)
}
func
BenchmarkOpSlt
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opSlt
,
x
,
y
)
}
func
BenchmarkOpSgt
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opSgt
,
x
,
y
)
}
func
BenchmarkOpEq
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opEq
,
x
,
y
)
}
func
BenchmarkOpEq2
(
b
*
testing
.
B
)
{
x
:=
"FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
y
:=
"FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe"
opBenchmark
(
b
,
opEq
,
x
,
y
)
}
func
BenchmarkOpAnd
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opAnd
,
x
,
y
)
}
func
BenchmarkOpOr
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opOr
,
x
,
y
)
}
func
BenchmarkOpXor
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opXor
,
x
,
y
)
}
func
BenchmarkOpByte
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
opBenchmark
(
b
,
opByte
,
x
,
y
)
}
func
BenchmarkOpAddmod
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
z
:=
alphabetSoup
opBenchmark
(
b
,
opAddmod
,
x
,
y
,
z
)
}
func
BenchmarkOpMulmod
(
b
*
testing
.
B
)
{
x
:=
alphabetSoup
y
:=
alphabetSoup
z
:=
alphabetSoup
opBenchmark
(
b
,
opMulmod
,
x
,
y
,
z
)
}
func
BenchmarkOpSHL
(
b
*
testing
.
B
)
{
x
:=
"FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
y
:=
"ff"
opBenchmark
(
b
,
opSHL
,
x
,
y
)
}
func
BenchmarkOpSHR
(
b
*
testing
.
B
)
{
x
:=
"FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
y
:=
"ff"
opBenchmark
(
b
,
opSHR
,
x
,
y
)
}
func
BenchmarkOpSAR
(
b
*
testing
.
B
)
{
x
:=
"FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
y
:=
"ff"
opBenchmark
(
b
,
opSAR
,
x
,
y
)
}
func
BenchmarkOpIsZero
(
b
*
testing
.
B
)
{
x
:=
"FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
opBenchmark
(
b
,
opIszero
,
x
)
}
func
TestOpMstore
(
t
*
testing
.
T
)
{
var
(
evm
=
NewEVM
(
BlockContext
{},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
mem
=
NewMemory
()
)
mem
.
Resize
(
64
)
pc
:=
uint64
(
0
)
v
:=
"abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
stack
.
push
(
new
(
uint256
.
Int
)
.
SetBytes
(
common
.
Hex2Bytes
(
v
)))
stack
.
push
(
new
(
uint256
.
Int
))
opMstore
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
mem
,
stack
,
nil
})
if
got
:=
common
.
Bytes2Hex
(
mem
.
GetCopy
(
0
,
32
));
got
!=
v
{
t
.
Fatalf
(
"Mstore fail, got %v, expected %v"
,
got
,
v
)
}
stack
.
push
(
new
(
uint256
.
Int
)
.
SetUint64
(
0x1
))
stack
.
push
(
new
(
uint256
.
Int
))
opMstore
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
mem
,
stack
,
nil
})
if
common
.
Bytes2Hex
(
mem
.
GetCopy
(
0
,
32
))
!=
"0000000000000000000000000000000000000000000000000000000000000001"
{
t
.
Fatalf
(
"Mstore failed to overwrite previous value"
)
}
}
func
BenchmarkOpMstore
(
bench
*
testing
.
B
)
{
var
(
evm
=
NewEVM
(
BlockContext
{},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
mem
=
NewMemory
()
)
mem
.
Resize
(
64
)
pc
:=
uint64
(
0
)
memStart
:=
new
(
uint256
.
Int
)
value
:=
new
(
uint256
.
Int
)
.
SetUint64
(
0x1337
)
bench
.
ResetTimer
()
for
i
:=
0
;
i
<
bench
.
N
;
i
++
{
stack
.
push
(
value
)
stack
.
push
(
memStart
)
opMstore
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
mem
,
stack
,
nil
})
}
}
func
TestOpTstore
(
t
*
testing
.
T
)
{
var
(
statedb
,
_
=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
evm
=
NewEVM
(
BlockContext
{},
statedb
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
mem
=
NewMemory
()
caller
=
common
.
Address
{}
to
=
common
.
Address
{
1
}
contract
=
NewContract
(
caller
,
to
,
new
(
uint256
.
Int
),
0
,
nil
)
scopeContext
=
ScopeContext
{
mem
,
stack
,
contract
}
value
=
common
.
Hex2Bytes
(
"abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
)
)
// Add a stateObject for the caller and the contract being called
statedb
.
CreateAccount
(
caller
)
statedb
.
CreateAccount
(
to
)
pc
:=
uint64
(
0
)
// push the value to the stack
stack
.
push
(
new
(
uint256
.
Int
)
.
SetBytes
(
value
))
// push the location to the stack
stack
.
push
(
new
(
uint256
.
Int
))
opTstore
(
&
pc
,
evm
.
interpreter
,
&
scopeContext
)
// there should be no elements on the stack after TSTORE
if
stack
.
len
()
!=
0
{
t
.
Fatal
(
"stack wrong size"
)
}
// push the location to the stack
stack
.
push
(
new
(
uint256
.
Int
))
opTload
(
&
pc
,
evm
.
interpreter
,
&
scopeContext
)
// there should be one element on the stack after TLOAD
if
stack
.
len
()
!=
1
{
t
.
Fatal
(
"stack wrong size"
)
}
val
:=
stack
.
peek
()
if
!
bytes
.
Equal
(
val
.
Bytes
(),
value
)
{
t
.
Fatal
(
"incorrect element read from transient storage"
)
}
}
func
BenchmarkOpKeccak256
(
bench
*
testing
.
B
)
{
var
(
evm
=
NewEVM
(
BlockContext
{},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
mem
=
NewMemory
()
)
mem
.
Resize
(
32
)
pc
:=
uint64
(
0
)
start
:=
new
(
uint256
.
Int
)
bench
.
ResetTimer
()
for
i
:=
0
;
i
<
bench
.
N
;
i
++
{
stack
.
push
(
uint256
.
NewInt
(
32
))
stack
.
push
(
start
)
opKeccak256
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
mem
,
stack
,
nil
})
}
}
func
TestCreate2Addresses
(
t
*
testing
.
T
)
{
type
testcase
struct
{
origin
string
salt
string
code
string
expected
string
}
for
i
,
tt
:=
range
[]
testcase
{
{
origin
:
"0x0000000000000000000000000000000000000000"
,
salt
:
"0x0000000000000000000000000000000000000000"
,
code
:
"0x00"
,
expected
:
"0x4d1a2e2bb4f88f0250f26ffff098b0b30b26bf38"
,
},
{
origin
:
"0xdeadbeef00000000000000000000000000000000"
,
salt
:
"0x0000000000000000000000000000000000000000"
,
code
:
"0x00"
,
expected
:
"0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3"
,
},
{
origin
:
"0xdeadbeef00000000000000000000000000000000"
,
salt
:
"0xfeed000000000000000000000000000000000000"
,
code
:
"0x00"
,
expected
:
"0xD04116cDd17beBE565EB2422F2497E06cC1C9833"
,
},
{
origin
:
"0x0000000000000000000000000000000000000000"
,
salt
:
"0x0000000000000000000000000000000000000000"
,
code
:
"0xdeadbeef"
,
expected
:
"0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e"
,
},
{
origin
:
"0x00000000000000000000000000000000deadbeef"
,
salt
:
"0xcafebabe"
,
code
:
"0xdeadbeef"
,
expected
:
"0x60f3f640a8508fC6a86d45DF051962668E1e8AC7"
,
},
{
origin
:
"0x00000000000000000000000000000000deadbeef"
,
salt
:
"0xcafebabe"
,
code
:
"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
,
expected
:
"0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C"
,
},
{
origin
:
"0x0000000000000000000000000000000000000000"
,
salt
:
"0x0000000000000000000000000000000000000000"
,
code
:
"0x"
,
expected
:
"0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0"
,
},
}
{
origin
:=
common
.
BytesToAddress
(
common
.
FromHex
(
tt
.
origin
))
salt
:=
common
.
BytesToHash
(
common
.
FromHex
(
tt
.
salt
))
code
:=
common
.
FromHex
(
tt
.
code
)
codeHash
:=
crypto
.
Keccak256
(
code
)
address
:=
crypto
.
CreateAddress2
(
origin
,
salt
,
codeHash
)
/*
stack := newstack()
// salt, but we don't need that for this test
stack.push(big.NewInt(int64(len(code)))) //size
stack.push(big.NewInt(0)) // memstart
stack.push(big.NewInt(0)) // value
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())
*/
expected
:=
common
.
BytesToAddress
(
common
.
FromHex
(
tt
.
expected
))
if
!
bytes
.
Equal
(
expected
.
Bytes
(),
address
.
Bytes
())
{
t
.
Errorf
(
"test %d: expected %s, got %s"
,
i
,
expected
.
String
(),
address
.
String
())
}
}
}
func
TestRandom
(
t
*
testing
.
T
)
{
type
testcase
struct
{
name
string
random
common
.
Hash
}
for
_
,
tt
:=
range
[]
testcase
{
{
name
:
"empty hash"
,
random
:
common
.
Hash
{}},
{
name
:
"1"
,
random
:
common
.
Hash
{
0
}},
{
name
:
"emptyCodeHash"
,
random
:
types
.
EmptyCodeHash
},
{
name
:
"hash(0x010203)"
,
random
:
crypto
.
Keccak256Hash
([]
byte
{
0x01
,
0x02
,
0x03
})},
}
{
var
(
evm
=
NewEVM
(
BlockContext
{
Random
:
&
tt
.
random
},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
pc
=
uint64
(
0
)
)
opRandom
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
nil
,
stack
,
nil
})
if
len
(
stack
.
data
)
!=
1
{
t
.
Errorf
(
"Expected one item on stack after %v, got %d: "
,
tt
.
name
,
len
(
stack
.
data
))
}
actual
:=
stack
.
pop
()
expected
,
overflow
:=
uint256
.
FromBig
(
new
(
big
.
Int
)
.
SetBytes
(
tt
.
random
.
Bytes
()))
if
overflow
{
t
.
Errorf
(
"Testcase %v: invalid overflow"
,
tt
.
name
)
}
if
actual
.
Cmp
(
expected
)
!=
0
{
t
.
Errorf
(
"Testcase %v: expected %x, got %x"
,
tt
.
name
,
expected
,
actual
)
}
}
}
func
TestBlobHash
(
t
*
testing
.
T
)
{
type
testcase
struct
{
name
string
idx
uint64
expect
common
.
Hash
hashes
[]
common
.
Hash
}
var
(
zero
=
common
.
Hash
{
0
}
one
=
common
.
Hash
{
1
}
two
=
common
.
Hash
{
2
}
three
=
common
.
Hash
{
3
}
)
for
_
,
tt
:=
range
[]
testcase
{
{
name
:
"[{1}]"
,
idx
:
0
,
expect
:
one
,
hashes
:
[]
common
.
Hash
{
one
}},
{
name
:
"[1,{2},3]"
,
idx
:
2
,
expect
:
three
,
hashes
:
[]
common
.
Hash
{
one
,
two
,
three
}},
{
name
:
"out-of-bounds (empty)"
,
idx
:
10
,
expect
:
zero
,
hashes
:
[]
common
.
Hash
{}},
{
name
:
"out-of-bounds"
,
idx
:
25
,
expect
:
zero
,
hashes
:
[]
common
.
Hash
{
one
,
two
,
three
}},
{
name
:
"out-of-bounds (nil)"
,
idx
:
25
,
expect
:
zero
,
hashes
:
nil
},
}
{
var
(
evm
=
NewEVM
(
BlockContext
{},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
pc
=
uint64
(
0
)
)
evm
.
SetTxContext
(
TxContext
{
BlobHashes
:
tt
.
hashes
})
stack
.
push
(
uint256
.
NewInt
(
tt
.
idx
))
opBlobHash
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
nil
,
stack
,
nil
})
if
len
(
stack
.
data
)
!=
1
{
t
.
Errorf
(
"Expected one item on stack after %v, got %d: "
,
tt
.
name
,
len
(
stack
.
data
))
}
actual
:=
stack
.
pop
()
expected
,
overflow
:=
uint256
.
FromBig
(
new
(
big
.
Int
)
.
SetBytes
(
tt
.
expect
.
Bytes
()))
if
overflow
{
t
.
Errorf
(
"Testcase %v: invalid overflow"
,
tt
.
name
)
}
if
actual
.
Cmp
(
expected
)
!=
0
{
t
.
Errorf
(
"Testcase %v: expected %x, got %x"
,
tt
.
name
,
expected
,
actual
)
}
}
}
func
TestOpMCopy
(
t
*
testing
.
T
)
{
// Test cases from https://eips.ethereum.org/EIPS/eip-5656#test-cases
for
i
,
tc
:=
range
[]
struct
{
dst
,
src
,
len
string
pre
string
want
string
wantGas
uint64
}{
{
// MCOPY 0 32 32 - copy 32 bytes from offset 32 to offset 0.
dst
:
"0x0"
,
src
:
"0x20"
,
len
:
"0x20"
,
pre
:
"0000000000000000000000000000000000000000000000000000000000000000 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
,
want
:
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
,
wantGas
:
6
,
},
{
// MCOPY 0 0 32 - copy 32 bytes from offset 0 to offset 0.
dst
:
"0x0"
,
src
:
"0x0"
,
len
:
"0x20"
,
pre
:
"0101010101010101010101010101010101010101010101010101010101010101"
,
want
:
"0101010101010101010101010101010101010101010101010101010101010101"
,
wantGas
:
6
,
},
{
// MCOPY 0 1 8 - copy 8 bytes from offset 1 to offset 0 (overlapping).
dst
:
"0x0"
,
src
:
"0x1"
,
len
:
"0x8"
,
pre
:
"000102030405060708 000000000000000000000000000000000000000000000000"
,
want
:
"010203040506070808 000000000000000000000000000000000000000000000000"
,
wantGas
:
6
,
},
{
// MCOPY 1 0 8 - copy 8 bytes from offset 0 to offset 1 (overlapping).
dst
:
"0x1"
,
src
:
"0x0"
,
len
:
"0x8"
,
pre
:
"000102030405060708 000000000000000000000000000000000000000000000000"
,
want
:
"000001020304050607 000000000000000000000000000000000000000000000000"
,
wantGas
:
6
,
},
// Tests below are not in the EIP, but maybe should be added
{
// MCOPY 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF 0 - copy zero bytes from out-of-bounds index(overlapping).
dst
:
"0xFFFFFFFFFFFF"
,
src
:
"0xFFFFFFFFFFFF"
,
len
:
"0x0"
,
pre
:
"11"
,
want
:
"11"
,
wantGas
:
3
,
},
{
// MCOPY 0xFFFFFFFFFFFF 0 0 - copy zero bytes from start of mem to out-of-bounds.
dst
:
"0xFFFFFFFFFFFF"
,
src
:
"0x0"
,
len
:
"0x0"
,
pre
:
"11"
,
want
:
"11"
,
wantGas
:
3
,
},
{
// MCOPY 0 0xFFFFFFFFFFFF 0 - copy zero bytes from out-of-bounds to start of mem
dst
:
"0x0"
,
src
:
"0xFFFFFFFFFFFF"
,
len
:
"0x0"
,
pre
:
"11"
,
want
:
"11"
,
wantGas
:
3
,
},
{
// MCOPY - copy 1 from space outside of uint64 space
dst
:
"0x0"
,
src
:
"0x10000000000000000"
,
len
:
"0x1"
,
pre
:
"0"
,
},
{
// MCOPY - copy 1 from 0 to space outside of uint64
dst
:
"0x10000000000000000"
,
src
:
"0x0"
,
len
:
"0x1"
,
pre
:
"0"
,
},
{
// MCOPY - copy nothing from 0 to space outside of uint64
dst
:
"0x10000000000000000"
,
src
:
"0x0"
,
len
:
"0x0"
,
pre
:
""
,
want
:
""
,
wantGas
:
3
,
},
{
// MCOPY - copy 1 from 0x20 to 0x10, with no prior allocated mem
dst
:
"0x10"
,
src
:
"0x20"
,
len
:
"0x1"
,
pre
:
""
,
// 64 bytes
want
:
"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
,
wantGas
:
12
,
},
{
// MCOPY - copy 1 from 0x19 to 0x10, with no prior allocated mem
dst
:
"0x10"
,
src
:
"0x19"
,
len
:
"0x1"
,
pre
:
""
,
// 32 bytes
want
:
"0x0000000000000000000000000000000000000000000000000000000000000000"
,
wantGas
:
9
,
},
}
{
var
(
evm
=
NewEVM
(
BlockContext
{},
nil
,
params
.
TestChainConfig
,
Config
{})
stack
=
newstack
()
pc
=
uint64
(
0
)
)
data
:=
common
.
FromHex
(
strings
.
ReplaceAll
(
tc
.
pre
,
" "
,
""
))
// Set pre
mem
:=
NewMemory
()
mem
.
Resize
(
uint64
(
len
(
data
)))
mem
.
Set
(
0
,
uint64
(
len
(
data
)),
data
)
// Push stack args
len
,
_
:=
uint256
.
FromHex
(
tc
.
len
)
src
,
_
:=
uint256
.
FromHex
(
tc
.
src
)
dst
,
_
:=
uint256
.
FromHex
(
tc
.
dst
)
stack
.
push
(
len
)
stack
.
push
(
src
)
stack
.
push
(
dst
)
wantErr
:=
(
tc
.
wantGas
==
0
)
// Calc mem expansion
var
memorySize
uint64
if
memSize
,
overflow
:=
memoryMcopy
(
stack
);
overflow
{
if
wantErr
{
continue
}
t
.
Errorf
(
"overflow"
)
}
else
{
var
overflow
bool
if
memorySize
,
overflow
=
math
.
SafeMul
(
toWordSize
(
memSize
),
32
);
overflow
{
t
.
Error
(
ErrGasUintOverflow
)
}
}
// and the dynamic cost
var
haveGas
uint64
if
dynamicCost
,
err
:=
gasMcopy
(
evm
,
nil
,
stack
,
mem
,
memorySize
);
err
!=
nil
{
t
.
Error
(
err
)
}
else
{
haveGas
=
GasFastestStep
+
dynamicCost
}
// Expand mem
if
memorySize
>
0
{
mem
.
Resize
(
memorySize
)
}
// Do the copy
opMcopy
(
&
pc
,
evm
.
interpreter
,
&
ScopeContext
{
mem
,
stack
,
nil
})
want
:=
common
.
FromHex
(
strings
.
ReplaceAll
(
tc
.
want
,
" "
,
""
))
if
have
:=
mem
.
store
;
!
bytes
.
Equal
(
want
,
have
)
{
t
.
Errorf
(
"case %d:
\n
want: %#x
\n
have: %#x
\n
"
,
i
,
want
,
have
)
}
wantGas
:=
tc
.
wantGas
if
haveGas
!=
wantGas
{
t
.
Errorf
(
"case %d: gas wrong, want %d have %d
\n
"
,
i
,
wantGas
,
haveGas
)
}
}
}
// TestPush sanity-checks how code with immediates are handled when the code size is
// smaller than the size of the immediate.
func
TestPush
(
t
*
testing
.
T
)
{
code
:=
common
.
FromHex
(
"0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121"
)
push32
:=
makePush
(
32
,
32
)
scope
:=
&
ScopeContext
{
Memory
:
nil
,
Stack
:
newstack
(),
Contract
:
&
Contract
{
Code
:
code
,
},
}
for
i
,
want
:=
range
[]
string
{
"0x11223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1"
,
"0x223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1"
,
"0x3344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1"
,
"0x44556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1"
,
"0x556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1"
,
"0x6677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1"
,
"0x77889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191"
,
"0x889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181"
,
"0x9900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171"
,
"0xaabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191817161"
,
"0xaabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151"
,
"0xbbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141"
,
"0xccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191817161514131"
,
"0xddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121"
,
"0xeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100"
,
"0xff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a191817161514131210000"
,
"0x102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121000000"
,
"0x2030405060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100000000"
,
"0x30405060708090a0b0c0d0e0ff1e1d1c1b1a191817161514131210000000000"
,
"0x405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121000000000000"
,
"0x5060708090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100000000000000"
,
"0x60708090a0b0c0d0e0ff1e1d1c1b1a191817161514131210000000000000000"
,
"0x708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121000000000000000000"
,
"0x8090a0b0c0d0e0ff1e1d1c1b1a1918171615141312100000000000000000000"
,
"0x90a0b0c0d0e0ff1e1d1c1b1a191817161514131210000000000000000000000"
,
"0xa0b0c0d0e0ff1e1d1c1b1a19181716151413121000000000000000000000000"
,
"0xb0c0d0e0ff1e1d1c1b1a1918171615141312100000000000000000000000000"
,
"0xc0d0e0ff1e1d1c1b1a191817161514131210000000000000000000000000000"
,
"0xd0e0ff1e1d1c1b1a19181716151413121000000000000000000000000000000"
,
"0xe0ff1e1d1c1b1a1918171615141312100000000000000000000000000000000"
,
"0xff1e1d1c1b1a191817161514131210000000000000000000000000000000000"
,
"0xf1e1d1c1b1a19181716151413121000000000000000000000000000000000000"
,
"0xe1d1c1b1a1918171615141312100000000000000000000000000000000000000"
,
"0xd1c1b1a191817161514131210000000000000000000000000000000000000000"
,
"0xc1b1a19181716151413121000000000000000000000000000000000000000000"
,
"0xb1a1918171615141312100000000000000000000000000000000000000000000"
,
"0xa191817161514131210000000000000000000000000000000000000000000000"
,
"0x9181716151413121000000000000000000000000000000000000000000000000"
,
"0x8171615141312100000000000000000000000000000000000000000000000000"
,
"0x7161514131210000000000000000000000000000000000000000000000000000"
,
"0x6151413121000000000000000000000000000000000000000000000000000000"
,
"0x5141312100000000000000000000000000000000000000000000000000000000"
,
"0x4131210000000000000000000000000000000000000000000000000000000000"
,
"0x3121000000000000000000000000000000000000000000000000000000000000"
,
"0x2100000000000000000000000000000000000000000000000000000000000000"
,
"0x0"
,
}
{
pc
:=
new
(
uint64
)
*
pc
=
uint64
(
i
)
push32
(
pc
,
nil
,
scope
)
res
:=
scope
.
Stack
.
pop
()
if
have
:=
res
.
Hex
();
have
!=
want
{
t
.
Fatalf
(
"case %d, have %v want %v"
,
i
,
have
,
want
)
}
}
}
evm/vm/interface.go
View file @
1fff77e7
...
...
@@ -22,7 +22,6 @@ import (
"code.wuban.net.cn/cmpchain/ethtracer/state"
"code.wuban.net.cn/cmpchain/ethtracer/stateless"
"code.wuban.net.cn/cmpchain/ethtracer/tracing"
"code.wuban.net.cn/cmpchain/ethtracer/types"
"code.wuban.net.cn/cmpchain/ethtracer/utils"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
...
...
@@ -96,9 +95,9 @@ type StateDB interface {
RevertToSnapshot
(
int
)
Snapshot
()
int
AddLog
(
*
types
.
Log
)
AddLog
(
*
evm
types
.
Log
)
AddPreimage
(
metatypes
.
Hash
,
[]
byte
)
Witness
()
*
stateless
.
Witness
AccessEvents
()
*
state
.
AccessEvents
...
...
evm/vm/interpreter_test.go
deleted
100644 → 0
View file @
323d4af7
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
vm
import
(
"code.wuban.net.cn/cmpchain/ethtracer/params"
"code.wuban.net.cn/cmpchain/ethtracer/types"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"github.com/ethereum/go-ethereum/core/state"
"math"
"testing"
"time"
"github.com/holiman/uint256"
)
var
loopInterruptTests
=
[]
string
{
// infinite loop using JUMP: push(2) jumpdest dup1 jump
"60025b8056"
,
// infinite loop using JUMPI: push(1) push(4) jumpdest dup2 dup2 jumpi
"600160045b818157"
,
}
func
TestLoopInterrupt
(
t
*
testing
.
T
)
{
address
:=
metatypes
.
BytesToAddress
([]
byte
(
"contract"
))
vmctx
:=
BlockContext
{
Transfer
:
func
(
StateDB
,
metatypes
.
Address
,
metatypes
.
Address
,
*
uint256
.
Int
)
{},
}
for
i
,
tt
:=
range
loopInterruptTests
{
statedb
,
_
:=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
statedb
.
CreateAccount
(
address
)
statedb
.
SetCode
(
address
,
metatypes
.
Hex2Bytes
(
tt
))
statedb
.
Finalise
(
true
)
evm
:=
NewEVM
(
vmctx
,
statedb
,
params
.
AllEthashProtocolChanges
,
Config
{})
errChannel
:=
make
(
chan
error
)
timeout
:=
make
(
chan
bool
)
go
func
(
evm
*
EVM
)
{
_
,
_
,
err
:=
evm
.
Call
(
metatypes
.
Address
{},
address
,
nil
,
math
.
MaxUint64
,
new
(
uint256
.
Int
))
errChannel
<-
err
}(
evm
)
go
func
()
{
<-
time
.
After
(
time
.
Second
)
timeout
<-
true
}()
evm
.
Cancel
()
select
{
case
<-
timeout
:
t
.
Errorf
(
"test %d timed out"
,
i
)
case
err
:=
<-
errChannel
:
if
err
!=
nil
{
t
.
Errorf
(
"test %d failure: %v"
,
i
,
err
)
}
}
}
}
evm/vm/memory_test.go
View file @
1fff77e7
...
...
@@ -18,10 +18,9 @@ package vm
import
(
"bytes"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"strings"
"testing"
"github.com/ethereum/go-ethereum/common"
)
func
TestMemoryCopy
(
t
*
testing
.
T
)
{
...
...
@@ -71,13 +70,13 @@ func TestMemoryCopy(t *testing.T) {
}
{
m
:=
NewMemory
()
// Clean spaces
data
:=
common
.
FromHex
(
strings
.
ReplaceAll
(
tc
.
pre
,
" "
,
""
))
data
:=
metatypes
.
FromHex
(
strings
.
ReplaceAll
(
tc
.
pre
,
" "
,
""
))
// Set pre
m
.
Resize
(
uint64
(
len
(
data
)))
m
.
Set
(
0
,
uint64
(
len
(
data
)),
data
)
// Do the copy
m
.
Copy
(
tc
.
dst
,
tc
.
src
,
tc
.
len
)
want
:=
common
.
FromHex
(
strings
.
ReplaceAll
(
tc
.
want
,
" "
,
""
))
want
:=
metatypes
.
FromHex
(
strings
.
ReplaceAll
(
tc
.
want
,
" "
,
""
))
if
have
:=
m
.
store
;
!
bytes
.
Equal
(
want
,
have
)
{
t
.
Errorf
(
"case %d: want: %#x
\n
have: %#x
\n
"
,
i
,
want
,
have
)
}
...
...
evm/vm/runtime/runtime.go
View file @
1fff77e7
...
...
@@ -21,11 +21,8 @@ import (
"code.wuban.net.cn/cmpchain/ethtracer/evm/evmtypes"
"code.wuban.net.cn/cmpchain/ethtracer/evm/vm"
"code.wuban.net.cn/cmpchain/ethtracer/params"
"code.wuban.net.cn/cmpchain/ethtracer/types"
"errors"
basetype
"github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"github.com/ethereum/go-ethereum/core/state"
"math"
"math/big"
...
...
@@ -153,7 +150,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, vm.StateDB, error) {
uint256
.
MustFromBig
(
cfg
.
Value
),
)
if
cfg
.
EVMConfig
.
Tracer
!=
nil
&&
cfg
.
EVMConfig
.
Tracer
.
OnTxEnd
!=
nil
{
cfg
.
EVMConfig
.
Tracer
.
OnTxEnd
(
&
types
.
Receipt
{
GasUsed
:
cfg
.
GasLimit
-
leftOverGas
},
err
)
cfg
.
EVMConfig
.
Tracer
.
OnTxEnd
(
&
evm
types
.
Receipt
{
GasUsed
:
cfg
.
GasLimit
-
leftOverGas
},
err
)
}
return
ret
,
cfg
.
State
,
err
}
...
...
@@ -166,14 +163,15 @@ func Create(input []byte, cfg *Config) ([]byte, metatypes.Address, uint64, error
setDefaults
(
cfg
)
if
cfg
.
State
==
nil
{
cfg
.
State
,
_
=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
return
nil
,
metatypes
.
Address
{},
0
,
errors
.
New
(
"state must be set in config for Create"
)
//cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
}
var
(
vmenv
=
NewEnv
(
cfg
)
rules
=
cfg
.
ChainConfig
.
Rules
(
vmenv
.
Context
.
BlockNumber
,
vmenv
.
Context
.
Random
!=
nil
,
vmenv
.
Context
.
Time
)
)
if
cfg
.
EVMConfig
.
Tracer
!=
nil
&&
cfg
.
EVMConfig
.
Tracer
.
OnTxStart
!=
nil
{
cfg
.
EVMConfig
.
Tracer
.
OnTxStart
(
vmenv
.
GetVMContext
(),
types
.
NewTx
(
&
types
.
LegacyTx
{
Data
:
input
,
Value
:
cfg
.
Value
,
Gas
:
cfg
.
GasLimit
}),
cfg
.
Origin
)
cfg
.
EVMConfig
.
Tracer
.
OnTxStart
(
vmenv
.
GetVMContext
(),
evmtypes
.
NewTx
(
&
evm
types
.
LegacyTx
{
Data
:
input
,
Value
:
cfg
.
Value
,
Gas
:
cfg
.
GasLimit
}),
cfg
.
Origin
)
}
// Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin)
...
...
@@ -187,10 +185,8 @@ func Create(input []byte, cfg *Config) ([]byte, metatypes.Address, uint64, error
uint256
.
MustFromBig
(
cfg
.
Value
),
)
if
cfg
.
EVMConfig
.
Tracer
!=
nil
&&
cfg
.
EVMConfig
.
Tracer
.
OnTxEnd
!=
nil
{
cfg
.
EVMConfig
.
Tracer
.
OnTxEnd
(
&
types
.
Receipt
{
MetaReceipt
:
&
basetype
.
MetaReceipt
{
GasUsed
:
cfg
.
GasLimit
-
leftOverGas
,
},
cfg
.
EVMConfig
.
Tracer
.
OnTxEnd
(
&
evmtypes
.
Receipt
{
GasUsed
:
cfg
.
GasLimit
-
leftOverGas
,
},
err
)
}
return
code
,
address
,
leftOverGas
,
err
...
...
@@ -210,7 +206,7 @@ func Call(address metatypes.Address, input []byte, cfg *Config) ([]byte, uint64,
rules
=
cfg
.
ChainConfig
.
Rules
(
vmenv
.
Context
.
BlockNumber
,
vmenv
.
Context
.
Random
!=
nil
,
vmenv
.
Context
.
Time
)
)
if
cfg
.
EVMConfig
.
Tracer
!=
nil
&&
cfg
.
EVMConfig
.
Tracer
.
OnTxStart
!=
nil
{
cfg
.
EVMConfig
.
Tracer
.
OnTxStart
(
vmenv
.
GetVMContext
(),
types
.
NewTx
(
&
types
.
LegacyTx
{
To
:
&
address
,
Data
:
input
,
Value
:
cfg
.
Value
,
Gas
:
cfg
.
GasLimit
}),
cfg
.
Origin
)
cfg
.
EVMConfig
.
Tracer
.
OnTxStart
(
vmenv
.
GetVMContext
(),
evmtypes
.
NewTx
(
&
evm
types
.
LegacyTx
{
To
:
&
address
,
Data
:
input
,
Value
:
cfg
.
Value
,
Gas
:
cfg
.
GasLimit
}),
cfg
.
Origin
)
}
// Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin)
...
...
@@ -226,11 +222,14 @@ func Call(address metatypes.Address, input []byte, cfg *Config) ([]byte, uint64,
uint256
.
MustFromBig
(
cfg
.
Value
),
)
if
cfg
.
EVMConfig
.
Tracer
!=
nil
&&
cfg
.
EVMConfig
.
Tracer
.
OnTxEnd
!=
nil
{
cfg
.
EVMConfig
.
Tracer
.
OnTxEnd
(
&
types
.
Receipt
{
MetaReceipt
:
&
basetype
.
MetaReceipt
{
GasUsed
:
cfg
.
GasLimit
-
leftOverGas
,
},
cfg
.
EVMConfig
.
Tracer
.
OnTxEnd
(
&
evmtypes
.
Receipt
{
GasUsed
:
cfg
.
GasLimit
-
leftOverGas
,
},
err
)
//cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{
// MetaReceipt: &basetype.MetaReceipt{
// GasUsed: cfg.GasLimit - leftOverGas,
// },
//}, err)
}
return
ret
,
leftOverGas
,
err
}
evm/vm/runtime/runtime_example_test.go
deleted
100644 → 0
View file @
323d4af7
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
runtime_test
import
(
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm/runtime"
)
func
ExampleExecute
()
{
ret
,
_
,
err
:=
runtime
.
Execute
(
common
.
Hex2Bytes
(
"6060604052600a8060106000396000f360606040526008565b00"
),
nil
,
nil
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
fmt
.
Println
(
ret
)
// Output:
// [96 96 96 64 82 96 8 86 91 0]
}
evm/vm/runtime/runtime_fuzz_test.go
deleted
100644 → 0
View file @
323d4af7
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
runtime
import
(
"testing"
)
func
FuzzVmRuntime
(
f
*
testing
.
F
)
{
f
.
Fuzz
(
func
(
t
*
testing
.
T
,
code
,
input
[]
byte
)
{
Execute
(
code
,
input
,
&
Config
{
GasLimit
:
12000000
,
})
})
}
evm/vm/runtime/runtime_test.go
deleted
100644 → 0
View file @
323d4af7
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
runtime
import
(
"encoding/binary"
"fmt"
"math/big"
"os"
"strconv"
"strings"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/vm/program"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/params"
// force-load js tracers to trigger registration
_
"github.com/ethereum/go-ethereum/eth/tracers/js"
)
func
TestDefaults
(
t
*
testing
.
T
)
{
cfg
:=
new
(
Config
)
setDefaults
(
cfg
)
if
cfg
.
Difficulty
==
nil
{
t
.
Error
(
"expected difficulty to be non nil"
)
}
if
cfg
.
GasLimit
==
0
{
t
.
Error
(
"didn't expect gaslimit to be zero"
)
}
if
cfg
.
GasPrice
==
nil
{
t
.
Error
(
"expected time to be non nil"
)
}
if
cfg
.
Value
==
nil
{
t
.
Error
(
"expected time to be non nil"
)
}
if
cfg
.
GetHashFn
==
nil
{
t
.
Error
(
"expected time to be non nil"
)
}
if
cfg
.
BlockNumber
==
nil
{
t
.
Error
(
"expected block number to be non nil"
)
}
}
func
TestEVM
(
t
*
testing
.
T
)
{
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
t
.
Fatalf
(
"crashed with: %v"
,
r
)
}
}()
Execute
([]
byte
{
byte
(
vm
.
DIFFICULTY
),
byte
(
vm
.
TIMESTAMP
),
byte
(
vm
.
GASLIMIT
),
byte
(
vm
.
PUSH1
),
byte
(
vm
.
ORIGIN
),
byte
(
vm
.
BLOCKHASH
),
byte
(
vm
.
COINBASE
),
},
nil
,
nil
)
}
func
TestExecute
(
t
*
testing
.
T
)
{
ret
,
_
,
err
:=
Execute
([]
byte
{
byte
(
vm
.
PUSH1
),
10
,
byte
(
vm
.
PUSH1
),
0
,
byte
(
vm
.
MSTORE
),
byte
(
vm
.
PUSH1
),
32
,
byte
(
vm
.
PUSH1
),
0
,
byte
(
vm
.
RETURN
),
},
nil
,
nil
)
if
err
!=
nil
{
t
.
Fatal
(
"didn't expect error"
,
err
)
}
num
:=
new
(
big
.
Int
)
.
SetBytes
(
ret
)
if
num
.
Cmp
(
big
.
NewInt
(
10
))
!=
0
{
t
.
Error
(
"Expected 10, got"
,
num
)
}
}
func
TestCall
(
t
*
testing
.
T
)
{
state
,
_
:=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
address
:=
common
.
HexToAddress
(
"0xaa"
)
state
.
SetCode
(
address
,
[]
byte
{
byte
(
vm
.
PUSH1
),
10
,
byte
(
vm
.
PUSH1
),
0
,
byte
(
vm
.
MSTORE
),
byte
(
vm
.
PUSH1
),
32
,
byte
(
vm
.
PUSH1
),
0
,
byte
(
vm
.
RETURN
),
})
ret
,
_
,
err
:=
Call
(
address
,
nil
,
&
Config
{
State
:
state
})
if
err
!=
nil
{
t
.
Fatal
(
"didn't expect error"
,
err
)
}
num
:=
new
(
big
.
Int
)
.
SetBytes
(
ret
)
if
num
.
Cmp
(
big
.
NewInt
(
10
))
!=
0
{
t
.
Error
(
"Expected 10, got"
,
num
)
}
}
func
BenchmarkCall
(
b
*
testing
.
B
)
{
var
definition
=
`[{"constant":true,"inputs":[],"name":"seller","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[],"name":"abort","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[],"name":"refund","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"buyer","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[],"name":"confirmReceived","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"state","outputs":[{"name":"","type":"uint8"}],"type":"function"},{"constant":false,"inputs":[],"name":"confirmPurchase","outputs":[],"type":"function"},{"inputs":[],"type":"constructor"},{"anonymous":false,"inputs":[],"name":"Aborted","type":"event"},{"anonymous":false,"inputs":[],"name":"PurchaseConfirmed","type":"event"},{"anonymous":false,"inputs":[],"name":"ItemReceived","type":"event"},{"anonymous":false,"inputs":[],"name":"Refunded","type":"event"}]`
var
code
=
common
.
Hex2Bytes
(
"6060604052361561006c5760e060020a600035046308551a53811461007457806335a063b4146100865780633fa4f245146100a6578063590e1ae3146100af5780637150d8ae146100cf57806373fac6f0146100e1578063c19d93fb146100fe578063d696069714610112575b610131610002565b610133600154600160a060020a031681565b610131600154600160a060020a0390811633919091161461015057610002565b61014660005481565b610131600154600160a060020a039081163391909116146102d557610002565b610133600254600160a060020a031681565b610131600254600160a060020a0333811691161461023757610002565b61014660025460ff60a060020a9091041681565b61013160025460009060ff60a060020a9091041681146101cc57610002565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60025460009060a060020a900460ff16811461016b57610002565b600154600160a060020a03908116908290301631606082818181858883f150506002805460a060020a60ff02191660a160020a179055506040517f72c874aeff0b183a56e2b79c71b46e1aed4dee5e09862134b8821ba2fddbf8bf9250a150565b80546002023414806101dd57610002565b6002805460a060020a60ff021973ffffffffffffffffffffffffffffffffffffffff1990911633171660a060020a1790557fd5d55c8a68912e9a110618df8d5e2e83b8d83211c57a8ddd1203df92885dc881826060a15050565b60025460019060a060020a900460ff16811461025257610002565b60025460008054600160a060020a0390921691606082818181858883f150508354604051600160a060020a0391821694503090911631915082818181858883f150506002805460a060020a60ff02191660a160020a179055506040517fe89152acd703c9d8c7d28829d443260b411454d45394e7995815140c8cbcbcf79250a150565b60025460019060a060020a900460ff1681146102f057610002565b6002805460008054600160a060020a0390921692909102606082818181858883f150508354604051600160a060020a0391821694503090911631915082818181858883f150506002805460a060020a60ff02191660a160020a179055506040517f8616bbbbad963e4e65b1366f1d75dfb63f9e9704bbbf91fb01bec70849906cf79250a15056"
)
abi
,
err
:=
abi
.
JSON
(
strings
.
NewReader
(
definition
))
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
cpurchase
,
err
:=
abi
.
Pack
(
"confirmPurchase"
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
creceived
,
err
:=
abi
.
Pack
(
"confirmReceived"
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
refund
,
err
:=
abi
.
Pack
(
"refund"
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
j
:=
0
;
j
<
400
;
j
++
{
Execute
(
code
,
cpurchase
,
nil
)
Execute
(
code
,
creceived
,
nil
)
Execute
(
code
,
refund
,
nil
)
}
}
}
func
benchmarkEVM_Create
(
bench
*
testing
.
B
,
code
string
)
{
var
(
statedb
,
_
=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
sender
=
common
.
BytesToAddress
([]
byte
(
"sender"
))
receiver
=
common
.
BytesToAddress
([]
byte
(
"receiver"
))
)
statedb
.
CreateAccount
(
sender
)
statedb
.
SetCode
(
receiver
,
common
.
FromHex
(
code
))
runtimeConfig
:=
Config
{
Origin
:
sender
,
State
:
statedb
,
GasLimit
:
10000000
,
Difficulty
:
big
.
NewInt
(
0x200000
),
Time
:
0
,
Coinbase
:
common
.
Address
{},
BlockNumber
:
new
(
big
.
Int
)
.
SetUint64
(
1
),
ChainConfig
:
&
params
.
ChainConfig
{
ChainID
:
big
.
NewInt
(
1
),
HomesteadBlock
:
new
(
big
.
Int
),
ByzantiumBlock
:
new
(
big
.
Int
),
ConstantinopleBlock
:
new
(
big
.
Int
),
DAOForkBlock
:
new
(
big
.
Int
),
DAOForkSupport
:
false
,
EIP150Block
:
new
(
big
.
Int
),
EIP155Block
:
new
(
big
.
Int
),
EIP158Block
:
new
(
big
.
Int
),
},
EVMConfig
:
vm
.
Config
{},
}
// Warm up the intpools and stuff
bench
.
ResetTimer
()
for
i
:=
0
;
i
<
bench
.
N
;
i
++
{
Call
(
receiver
,
[]
byte
{},
&
runtimeConfig
)
}
bench
.
StopTimer
()
}
func
BenchmarkEVM_CREATE_500
(
bench
*
testing
.
B
)
{
// initcode size 500K, repeatedly calls CREATE and then modifies the mem contents
benchmarkEVM_Create
(
bench
,
"5b6207a120600080f0600152600056"
)
}
func
BenchmarkEVM_CREATE2_500
(
bench
*
testing
.
B
)
{
// initcode size 500K, repeatedly calls CREATE2 and then modifies the mem contents
benchmarkEVM_Create
(
bench
,
"5b586207a120600080f5600152600056"
)
}
func
BenchmarkEVM_CREATE_1200
(
bench
*
testing
.
B
)
{
// initcode size 1200K, repeatedly calls CREATE and then modifies the mem contents
benchmarkEVM_Create
(
bench
,
"5b62124f80600080f0600152600056"
)
}
func
BenchmarkEVM_CREATE2_1200
(
bench
*
testing
.
B
)
{
// initcode size 1200K, repeatedly calls CREATE2 and then modifies the mem contents
benchmarkEVM_Create
(
bench
,
"5b5862124f80600080f5600152600056"
)
}
func
BenchmarkEVM_SWAP1
(
b
*
testing
.
B
)
{
// returns a contract that does n swaps (SWAP1)
swapContract
:=
func
(
n
uint64
)
[]
byte
{
contract
:=
[]
byte
{
byte
(
vm
.
PUSH0
),
// PUSH0
byte
(
vm
.
PUSH0
),
// PUSH0
}
for
i
:=
uint64
(
0
);
i
<
n
;
i
++
{
contract
=
append
(
contract
,
byte
(
vm
.
SWAP1
))
}
return
contract
}
state
,
_
:=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
contractAddr
:=
common
.
BytesToAddress
([]
byte
(
"contract"
))
b
.
Run
(
"10k"
,
func
(
b
*
testing
.
B
)
{
contractCode
:=
swapContract
(
10
_000
)
state
.
SetCode
(
contractAddr
,
contractCode
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
_
,
_
,
err
:=
Call
(
contractAddr
,
[]
byte
{},
&
Config
{
State
:
state
})
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
}
})
}
func
BenchmarkEVM_RETURN
(
b
*
testing
.
B
)
{
// returns a contract that returns a zero-byte slice of len size
returnContract
:=
func
(
size
uint64
)
[]
byte
{
contract
:=
[]
byte
{
byte
(
vm
.
PUSH8
),
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
// PUSH8 0xXXXXXXXXXXXXXXXX
byte
(
vm
.
PUSH0
),
// PUSH0
byte
(
vm
.
RETURN
),
// RETURN
}
binary
.
BigEndian
.
PutUint64
(
contract
[
1
:
],
size
)
return
contract
}
state
,
_
:=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
contractAddr
:=
common
.
BytesToAddress
([]
byte
(
"contract"
))
for
_
,
n
:=
range
[]
uint64
{
1
_000
,
10
_000
,
100
_000
,
1
_000_000
}
{
b
.
Run
(
strconv
.
FormatUint
(
n
,
10
),
func
(
b
*
testing
.
B
)
{
b
.
ReportAllocs
()
contractCode
:=
returnContract
(
n
)
state
.
SetCode
(
contractAddr
,
contractCode
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
ret
,
_
,
err
:=
Call
(
contractAddr
,
[]
byte
{},
&
Config
{
State
:
state
})
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
if
uint64
(
len
(
ret
))
!=
n
{
b
.
Fatalf
(
"expected return size %d, got %d"
,
n
,
len
(
ret
))
}
}
})
}
}
func
fakeHeader
(
n
uint64
,
parentHash
common
.
Hash
)
*
types
.
Header
{
header
:=
types
.
Header
{
Coinbase
:
common
.
HexToAddress
(
"0x00000000000000000000000000000000deadbeef"
),
Number
:
big
.
NewInt
(
int64
(
n
)),
ParentHash
:
parentHash
,
Time
:
1000
,
Nonce
:
types
.
BlockNonce
{
0x1
},
Extra
:
[]
byte
{},
Difficulty
:
big
.
NewInt
(
0
),
GasLimit
:
100000
,
}
return
&
header
}
type
dummyChain
struct
{
counter
int
}
// Engine retrieves the chain's consensus engine.
func
(
d
*
dummyChain
)
Engine
()
consensus
.
Engine
{
return
nil
}
// GetHeader returns the hash corresponding to their hash.
func
(
d
*
dummyChain
)
GetHeader
(
h
common
.
Hash
,
n
uint64
)
*
types
.
Header
{
d
.
counter
++
parentHash
:=
common
.
Hash
{}
s
:=
common
.
LeftPadBytes
(
big
.
NewInt
(
int64
(
n
-
1
))
.
Bytes
(),
32
)
copy
(
parentHash
[
:
],
s
)
//parentHash := common.Hash{byte(n - 1)}
//fmt.Printf("GetHeader(%x, %d) => header with parent %x\n", h, n, parentHash)
return
fakeHeader
(
n
,
parentHash
)
}
func
(
d
*
dummyChain
)
Config
()
*
params
.
ChainConfig
{
return
nil
}
// TestBlockhash tests the blockhash operation. It's a bit special, since it internally
// requires access to a chain reader.
func
TestBlockhash
(
t
*
testing
.
T
)
{
// Current head
n
:=
uint64
(
1000
)
parentHash
:=
common
.
Hash
{}
s
:=
common
.
LeftPadBytes
(
big
.
NewInt
(
int64
(
n
-
1
))
.
Bytes
(),
32
)
copy
(
parentHash
[
:
],
s
)
header
:=
fakeHeader
(
n
,
parentHash
)
// This is the contract we're using. It requests the blockhash for current num (should be all zeroes),
// then iteratively fetches all blockhashes back to n-260.
// It returns
// 1. the first (should be zero)
// 2. the second (should be the parent hash)
// 3. the last non-zero hash
// By making the chain reader return hashes which correlate to the number, we can
// verify that it obtained the right hashes where it should
/*
pragma solidity ^0.5.3;
contract Hasher{
function test() public view returns (bytes32, bytes32, bytes32){
uint256 x = block.number;
bytes32 first;
bytes32 last;
bytes32 zero;
zero = blockhash(x); // Should be zeroes
first = blockhash(x-1);
for(uint256 i = 2 ; i < 260; i++){
bytes32 hash = blockhash(x - i);
if (uint256(hash) != 0){
last = hash;
}
}
return (zero, first, last);
}
}
*/
// The contract above
data
:=
common
.
Hex2Bytes
(
"6080604052348015600f57600080fd5b50600436106045576000357c010000000000000000000000000000000000000000000000000000000090048063f8a8fd6d14604a575b600080fd5b60506074565b60405180848152602001838152602001828152602001935050505060405180910390f35b600080600080439050600080600083409050600184034092506000600290505b61010481101560c35760008186034090506000816001900414151560b6578093505b5080806001019150506094565b508083839650965096505050505090919256fea165627a7a72305820462d71b510c1725ff35946c20b415b0d50b468ea157c8c77dff9466c9cb85f560029"
)
// The method call to 'test()'
input
:=
common
.
Hex2Bytes
(
"f8a8fd6d"
)
chain
:=
&
dummyChain
{}
ret
,
_
,
err
:=
Execute
(
data
,
input
,
&
Config
{
GetHashFn
:
core
.
GetHashFn
(
header
,
chain
),
BlockNumber
:
new
(
big
.
Int
)
.
Set
(
header
.
Number
),
})
if
err
!=
nil
{
t
.
Fatalf
(
"expected no error, got %v"
,
err
)
}
if
len
(
ret
)
!=
96
{
t
.
Fatalf
(
"expected returndata to be 96 bytes, got %d"
,
len
(
ret
))
}
zero
:=
new
(
big
.
Int
)
.
SetBytes
(
ret
[
0
:
32
])
first
:=
new
(
big
.
Int
)
.
SetBytes
(
ret
[
32
:
64
])
last
:=
new
(
big
.
Int
)
.
SetBytes
(
ret
[
64
:
96
])
if
zero
.
BitLen
()
!=
0
{
t
.
Fatalf
(
"expected zeroes, got %x"
,
ret
[
0
:
32
])
}
if
first
.
Uint64
()
!=
999
{
t
.
Fatalf
(
"second block should be 999, got %d (%x)"
,
first
,
ret
[
32
:
64
])
}
if
last
.
Uint64
()
!=
744
{
t
.
Fatalf
(
"last block should be 744, got %d (%x)"
,
last
,
ret
[
64
:
96
])
}
if
exp
,
got
:=
255
,
chain
.
counter
;
exp
!=
got
{
t
.
Errorf
(
"suboptimal; too much chain iteration, expected %d, got %d"
,
exp
,
got
)
}
}
// benchmarkNonModifyingCode benchmarks code, but if the code modifies the
// state, this should not be used, since it does not reset the state between runs.
func
benchmarkNonModifyingCode
(
gas
uint64
,
code
[]
byte
,
name
string
,
tracerCode
string
,
b
*
testing
.
B
)
{
cfg
:=
new
(
Config
)
setDefaults
(
cfg
)
cfg
.
State
,
_
=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
cfg
.
GasLimit
=
gas
if
len
(
tracerCode
)
>
0
{
tracer
,
err
:=
tracers
.
DefaultDirectory
.
New
(
tracerCode
,
new
(
tracers
.
Context
),
nil
,
cfg
.
ChainConfig
)
if
err
!=
nil
{
b
.
Fatal
(
err
)
}
cfg
.
EVMConfig
=
vm
.
Config
{
Tracer
:
tracer
.
Hooks
,
}
}
destination
:=
common
.
BytesToAddress
([]
byte
(
"contract"
))
cfg
.
State
.
CreateAccount
(
destination
)
eoa
:=
common
.
HexToAddress
(
"E0"
)
{
cfg
.
State
.
CreateAccount
(
eoa
)
cfg
.
State
.
SetNonce
(
eoa
,
100
,
tracing
.
NonceChangeUnspecified
)
}
reverting
:=
common
.
HexToAddress
(
"EE"
)
{
cfg
.
State
.
CreateAccount
(
reverting
)
cfg
.
State
.
SetCode
(
reverting
,
[]
byte
{
byte
(
vm
.
PUSH1
),
0x00
,
byte
(
vm
.
PUSH1
),
0x00
,
byte
(
vm
.
REVERT
),
})
}
//cfg.State.CreateAccount(cfg.Origin)
// set the receiver's (the executing contract) code for execution.
cfg
.
State
.
SetCode
(
destination
,
code
)
Call
(
destination
,
nil
,
cfg
)
b
.
Run
(
name
,
func
(
b
*
testing
.
B
)
{
b
.
ReportAllocs
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
Call
(
destination
,
nil
,
cfg
)
}
})
}
// BenchmarkSimpleLoop test a pretty simple loop which loops until OOG
// 55 ms
func
BenchmarkSimpleLoop
(
b
*
testing
.
B
)
{
p
,
lbl
:=
program
.
New
()
.
Jumpdest
()
// Call identity, and pop return value
staticCallIdentity
:=
p
.
StaticCall
(
nil
,
0x4
,
0
,
0
,
0
,
0
)
.
Op
(
vm
.
POP
)
.
Jump
(
lbl
)
.
Bytes
()
// pop return value and jump to label
p
,
lbl
=
program
.
New
()
.
Jumpdest
()
callIdentity
:=
p
.
Call
(
nil
,
0x4
,
0
,
0
,
0
,
0
,
0
)
.
Op
(
vm
.
POP
)
.
Jump
(
lbl
)
.
Bytes
()
// pop return value and jump to label
p
,
lbl
=
program
.
New
()
.
Jumpdest
()
callInexistant
:=
p
.
Call
(
nil
,
0xff
,
0
,
0
,
0
,
0
,
0
)
.
Op
(
vm
.
POP
)
.
Jump
(
lbl
)
.
Bytes
()
// pop return value and jump to label
p
,
lbl
=
program
.
New
()
.
Jumpdest
()
callEOA
:=
p
.
Call
(
nil
,
0xE0
,
0
,
0
,
0
,
0
,
0
)
.
// call addr of EOA
Op
(
vm
.
POP
)
.
Jump
(
lbl
)
.
Bytes
()
// pop return value and jump to label
p
,
lbl
=
program
.
New
()
.
Jumpdest
()
// Push as if we were making call, then pop it off again, and loop
loopingCode
:=
p
.
Push
(
0
)
.
Op
(
vm
.
DUP1
,
vm
.
DUP1
,
vm
.
DUP1
)
.
Push
(
0x4
)
.
Op
(
vm
.
GAS
,
vm
.
POP
,
vm
.
POP
,
vm
.
POP
,
vm
.
POP
,
vm
.
POP
,
vm
.
POP
)
.
Jump
(
lbl
)
.
Bytes
()
p
,
lbl
=
program
.
New
()
.
Jumpdest
()
loopingCode2
:=
p
.
Push
(
0x01020304
)
.
Push
(
uint64
(
0x0102030405
))
.
Op
(
vm
.
POP
,
vm
.
POP
)
.
Op
(
vm
.
PUSH6
)
.
Append
(
make
([]
byte
,
6
))
.
Op
(
vm
.
JUMP
)
.
// Jumpdest zero expressed in 6 bytes
Jump
(
lbl
)
.
Bytes
()
p
,
lbl
=
program
.
New
()
.
Jumpdest
()
callRevertingContractWithInput
:=
p
.
Call
(
nil
,
0xee
,
0
,
0
,
0x20
,
0x0
,
0x0
)
.
Op
(
vm
.
POP
)
.
Jump
(
lbl
)
.
Bytes
()
// pop return value and jump to label
//tracer := logger.NewJSONLogger(nil, os.Stdout)
//Execute(loopingCode, nil, &Config{
// EVMConfig: vm.Config{
// Debug: true,
// Tracer: tracer,
// }})
// 100M gas
benchmarkNonModifyingCode
(
100000000
,
staticCallIdentity
,
"staticcall-identity-100M"
,
""
,
b
)
benchmarkNonModifyingCode
(
100000000
,
callIdentity
,
"call-identity-100M"
,
""
,
b
)
benchmarkNonModifyingCode
(
100000000
,
loopingCode
,
"loop-100M"
,
""
,
b
)
benchmarkNonModifyingCode
(
100000000
,
loopingCode2
,
"loop2-100M"
,
""
,
b
)
benchmarkNonModifyingCode
(
100000000
,
callInexistant
,
"call-nonexist-100M"
,
""
,
b
)
benchmarkNonModifyingCode
(
100000000
,
callEOA
,
"call-EOA-100M"
,
""
,
b
)
benchmarkNonModifyingCode
(
100000000
,
callRevertingContractWithInput
,
"call-reverting-100M"
,
""
,
b
)
//benchmarkNonModifyingCode(10000000, staticCallIdentity, "staticcall-identity-10M", b)
//benchmarkNonModifyingCode(10000000, loopingCode, "loop-10M", b)
}
// TestEip2929Cases contains various testcases that are used for
// EIP-2929 about gas repricings
func
TestEip2929Cases
(
t
*
testing
.
T
)
{
t
.
Skip
(
"Test only useful for generating documentation"
)
id
:=
1
prettyPrint
:=
func
(
comment
string
,
code
[]
byte
)
{
fmt
.
Printf
(
"### Case %d
\n\n
"
,
id
)
id
++
fmt
.
Printf
(
"%v
\n\n
Bytecode:
\n
```
\n
%#x
\n
```
\n
"
,
comment
,
code
)
Execute
(
code
,
nil
,
&
Config
{
EVMConfig
:
vm
.
Config
{
Tracer
:
logger
.
NewMarkdownLogger
(
nil
,
os
.
Stdout
)
.
Hooks
(),
ExtraEips
:
[]
int
{
2929
},
},
})
}
{
// First eip testcase
code
:=
[]
byte
{
// Three checks against a precompile
byte
(
vm
.
PUSH1
),
1
,
byte
(
vm
.
EXTCODEHASH
),
byte
(
vm
.
POP
),
byte
(
vm
.
PUSH1
),
2
,
byte
(
vm
.
EXTCODESIZE
),
byte
(
vm
.
POP
),
byte
(
vm
.
PUSH1
),
3
,
byte
(
vm
.
BALANCE
),
byte
(
vm
.
POP
),
// Three checks against a non-precompile
byte
(
vm
.
PUSH1
),
0xf1
,
byte
(
vm
.
EXTCODEHASH
),
byte
(
vm
.
POP
),
byte
(
vm
.
PUSH1
),
0xf2
,
byte
(
vm
.
EXTCODESIZE
),
byte
(
vm
.
POP
),
byte
(
vm
.
PUSH1
),
0xf3
,
byte
(
vm
.
BALANCE
),
byte
(
vm
.
POP
),
// Same three checks (should be cheaper)
byte
(
vm
.
PUSH1
),
0xf2
,
byte
(
vm
.
EXTCODEHASH
),
byte
(
vm
.
POP
),
byte
(
vm
.
PUSH1
),
0xf3
,
byte
(
vm
.
EXTCODESIZE
),
byte
(
vm
.
POP
),
byte
(
vm
.
PUSH1
),
0xf1
,
byte
(
vm
.
BALANCE
),
byte
(
vm
.
POP
),
// Check the origin, and the 'this'
byte
(
vm
.
ORIGIN
),
byte
(
vm
.
BALANCE
),
byte
(
vm
.
POP
),
byte
(
vm
.
ADDRESS
),
byte
(
vm
.
BALANCE
),
byte
(
vm
.
POP
),
byte
(
vm
.
STOP
),
}
prettyPrint
(
"This checks `EXT`(codehash,codesize,balance) of precompiles, which should be `100`, "
+
"and later checks the same operations twice against some non-precompiles. "
+
"Those are cheaper second time they are accessed. Lastly, it checks the `BALANCE` of `origin` and `this`."
,
code
)
}
{
// EXTCODECOPY
code
:=
[]
byte
{
// extcodecopy( 0xff,0,0,0,0)
byte
(
vm
.
PUSH1
),
0x00
,
byte
(
vm
.
PUSH1
),
0x00
,
byte
(
vm
.
PUSH1
),
0x00
,
//length, codeoffset, memoffset
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
EXTCODECOPY
),
// extcodecopy( 0xff,0,0,0,0)
byte
(
vm
.
PUSH1
),
0x00
,
byte
(
vm
.
PUSH1
),
0x00
,
byte
(
vm
.
PUSH1
),
0x00
,
//length, codeoffset, memoffset
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
EXTCODECOPY
),
// extcodecopy( this,0,0,0,0)
byte
(
vm
.
PUSH1
),
0x00
,
byte
(
vm
.
PUSH1
),
0x00
,
byte
(
vm
.
PUSH1
),
0x00
,
//length, codeoffset, memoffset
byte
(
vm
.
ADDRESS
),
byte
(
vm
.
EXTCODECOPY
),
byte
(
vm
.
STOP
),
}
prettyPrint
(
"This checks `extcodecopy( 0xff,0,0,0,0)` twice, (should be expensive first time), "
+
"and then does `extcodecopy( this,0,0,0,0)`."
,
code
)
}
{
// SLOAD + SSTORE
code
:=
[]
byte
{
// Add slot `0x1` to access list
byte
(
vm
.
PUSH1
),
0x01
,
byte
(
vm
.
SLOAD
),
byte
(
vm
.
POP
),
// SLOAD( 0x1) (add to access list)
// Write to `0x1` which is already in access list
byte
(
vm
.
PUSH1
),
0x11
,
byte
(
vm
.
PUSH1
),
0x01
,
byte
(
vm
.
SSTORE
),
// SSTORE( loc: 0x01, val: 0x11)
// Write to `0x2` which is not in access list
byte
(
vm
.
PUSH1
),
0x11
,
byte
(
vm
.
PUSH1
),
0x02
,
byte
(
vm
.
SSTORE
),
// SSTORE( loc: 0x02, val: 0x11)
// Write again to `0x2`
byte
(
vm
.
PUSH1
),
0x11
,
byte
(
vm
.
PUSH1
),
0x02
,
byte
(
vm
.
SSTORE
),
// SSTORE( loc: 0x02, val: 0x11)
// Read slot in access list (0x2)
byte
(
vm
.
PUSH1
),
0x02
,
byte
(
vm
.
SLOAD
),
// SLOAD( 0x2)
// Read slot in access list (0x1)
byte
(
vm
.
PUSH1
),
0x01
,
byte
(
vm
.
SLOAD
),
// SLOAD( 0x1)
}
prettyPrint
(
"This checks `sload( 0x1)` followed by `sstore(loc: 0x01, val:0x11)`, then 'naked' sstore:"
+
"`sstore(loc: 0x02, val:0x11)` twice, and `sload(0x2)`, `sload(0x1)`. "
,
code
)
}
{
// Call variants
code
:=
[]
byte
{
// identity precompile
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0x04
,
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
CALL
),
byte
(
vm
.
POP
),
// random account - call 1
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
CALL
),
byte
(
vm
.
POP
),
// random account - call 2
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
STATICCALL
),
byte
(
vm
.
POP
),
}
prettyPrint
(
"This calls the `identity`-precompile (cheap), then calls an account (expensive) and `staticcall`s the same"
+
"account (cheap)"
,
code
)
}
}
// TestColdAccountAccessCost test that the cold account access cost is reported
// correctly
// see: https://github.com/ethereum/go-ethereum/issues/22649
func
TestColdAccountAccessCost
(
t
*
testing
.
T
)
{
for
i
,
tc
:=
range
[]
struct
{
code
[]
byte
step
int
want
uint64
}{
{
// EXTCODEHASH(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0xFF
,
byte
(
vm
.
EXTCODEHASH
),
byte
(
vm
.
POP
)},
step
:
1
,
want
:
2600
,
},
{
// BALANCE(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0xFF
,
byte
(
vm
.
BALANCE
),
byte
(
vm
.
POP
)},
step
:
1
,
want
:
2600
,
},
{
// CALL(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
CALL
),
byte
(
vm
.
POP
),
},
step
:
7
,
want
:
2855
,
},
{
// CALLCODE(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
CALLCODE
),
byte
(
vm
.
POP
),
},
step
:
7
,
want
:
2855
,
},
{
// DELEGATECALL(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DELEGATECALL
),
byte
(
vm
.
POP
),
},
step
:
6
,
want
:
2855
,
},
{
// STATICCALL(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
STATICCALL
),
byte
(
vm
.
POP
),
},
step
:
6
,
want
:
2855
,
},
{
// SELFDESTRUCT(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
SELFDESTRUCT
),
},
step
:
1
,
want
:
7600
,
},
}
{
var
step
=
0
var
have
=
uint64
(
0
)
Execute
(
tc
.
code
,
nil
,
&
Config
{
EVMConfig
:
vm
.
Config
{
Tracer
:
&
tracing
.
Hooks
{
OnOpcode
:
func
(
pc
uint64
,
op
byte
,
gas
,
cost
uint64
,
scope
tracing
.
OpContext
,
rData
[]
byte
,
depth
int
,
err
error
)
{
// Uncomment to investigate failures:
//t.Logf("%d: %v %d", step, vm.OpCode(op).String(), cost)
if
step
==
tc
.
step
{
have
=
cost
}
step
++
},
},
},
})
if
want
:=
tc
.
want
;
have
!=
want
{
t
.
Fatalf
(
"testcase %d, gas report wrong, step %d, have %d want %d"
,
i
,
tc
.
step
,
have
,
want
)
}
}
}
func
TestRuntimeJSTracer
(
t
*
testing
.
T
)
{
jsTracers
:=
[]
string
{
`{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, steps:0,
step: function() { this.steps++},
fault: function() {},
result: function() {
return [this.enters, this.exits,this.enterGas,this.gasUsed, this.steps].join(",")
},
enter: function(frame) {
this.enters++;
this.enterGas = frame.getGas();
},
exit: function(res) {
this.exits++;
this.gasUsed = res.getGasUsed();
}}`
,
`{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, steps:0,
fault: function() {},
result: function() {
return [this.enters, this.exits,this.enterGas,this.gasUsed, this.steps].join(",")
},
enter: function(frame) {
this.enters++;
this.enterGas = frame.getGas();
},
exit: function(res) {
this.exits++;
this.gasUsed = res.getGasUsed();
}}`
}
initcode
:=
program
.
New
()
.
Return
(
0
,
0
)
.
Bytes
()
tests
:=
[]
struct
{
code
[]
byte
// One result per tracer
results
[]
string
}{
{
// CREATE
code
:
program
.
New
()
.
MstoreSmall
(
initcode
,
0
)
.
Push
(
len
(
initcode
))
.
// length
Push
(
32
-
len
(
initcode
))
.
// offset
Push
(
0
)
.
// value
Op
(
vm
.
CREATE
)
.
Op
(
vm
.
POP
)
.
Bytes
(),
results
:
[]
string
{
`"1,1,952853,6,12"`
,
`"1,1,952853,6,0"`
},
},
{
// CREATE2
code
:
program
.
New
()
.
MstoreSmall
(
initcode
,
0
)
.
Push
(
1
)
.
// salt
Push
(
len
(
initcode
))
.
// length
Push
(
32
-
len
(
initcode
))
.
// offset
Push
(
0
)
.
// value
Op
(
vm
.
CREATE2
)
.
Op
(
vm
.
POP
)
.
Bytes
(),
results
:
[]
string
{
`"1,1,952844,6,13"`
,
`"1,1,952844,6,0"`
},
},
{
// CALL
code
:
program
.
New
()
.
Call
(
nil
,
0xbb
,
0
,
0
,
0
,
0
,
0
)
.
Op
(
vm
.
POP
)
.
Bytes
(),
results
:
[]
string
{
`"1,1,981796,6,13"`
,
`"1,1,981796,6,0"`
},
},
{
// CALLCODE
code
:
program
.
New
()
.
CallCode
(
nil
,
0xcc
,
0
,
0
,
0
,
0
,
0
)
.
Op
(
vm
.
POP
)
.
Bytes
(),
results
:
[]
string
{
`"1,1,981796,6,13"`
,
`"1,1,981796,6,0"`
},
},
{
// STATICCALL
code
:
program
.
New
()
.
StaticCall
(
nil
,
0xdd
,
0
,
0
,
0
,
0
)
.
Op
(
vm
.
POP
)
.
Bytes
(),
results
:
[]
string
{
`"1,1,981799,6,12"`
,
`"1,1,981799,6,0"`
},
},
{
// DELEGATECALL
code
:
program
.
New
()
.
DelegateCall
(
nil
,
0xee
,
0
,
0
,
0
,
0
)
.
Op
(
vm
.
POP
)
.
Bytes
(),
results
:
[]
string
{
`"1,1,981799,6,12"`
,
`"1,1,981799,6,0"`
},
},
{
// CALL self-destructing contract
code
:
program
.
New
()
.
Call
(
nil
,
0xff
,
0
,
0
,
0
,
0
,
0
)
.
Op
(
vm
.
POP
)
.
Bytes
(),
results
:
[]
string
{
`"2,2,0,5003,12"`
,
`"2,2,0,5003,0"`
},
},
}
calleeCode
:=
[]
byte
{
byte
(
vm
.
PUSH1
),
0
,
byte
(
vm
.
PUSH1
),
0
,
byte
(
vm
.
RETURN
),
}
suicideCode
:=
[]
byte
{
byte
(
vm
.
PUSH1
),
0xaa
,
byte
(
vm
.
SELFDESTRUCT
),
}
main
:=
common
.
HexToAddress
(
"0xaa"
)
for
i
,
jsTracer
:=
range
jsTracers
{
for
j
,
tc
:=
range
tests
{
statedb
,
_
:=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
statedb
.
SetCode
(
main
,
tc
.
code
)
statedb
.
SetCode
(
common
.
HexToAddress
(
"0xbb"
),
calleeCode
)
statedb
.
SetCode
(
common
.
HexToAddress
(
"0xcc"
),
calleeCode
)
statedb
.
SetCode
(
common
.
HexToAddress
(
"0xdd"
),
calleeCode
)
statedb
.
SetCode
(
common
.
HexToAddress
(
"0xee"
),
calleeCode
)
statedb
.
SetCode
(
common
.
HexToAddress
(
"0xff"
),
suicideCode
)
tracer
,
err
:=
tracers
.
DefaultDirectory
.
New
(
jsTracer
,
new
(
tracers
.
Context
),
nil
,
params
.
MergedTestChainConfig
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
_
,
_
,
err
=
Call
(
main
,
nil
,
&
Config
{
GasLimit
:
1000000
,
State
:
statedb
,
EVMConfig
:
vm
.
Config
{
Tracer
:
tracer
.
Hooks
,
}})
if
err
!=
nil
{
t
.
Fatal
(
"didn't expect error"
,
err
)
}
res
,
err
:=
tracer
.
GetResult
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
have
,
want
:=
string
(
res
),
tc
.
results
[
i
];
have
!=
want
{
t
.
Errorf
(
"wrong result for tracer %d testcase %d, have
\n
%v
\n
want
\n
%v
\n
"
,
i
,
j
,
have
,
want
)
}
}
}
}
func
TestJSTracerCreateTx
(
t
*
testing
.
T
)
{
jsTracer
:=
`
{enters: 0, exits: 0,
step: function() {},
fault: function() {},
result: function() { return [this.enters, this.exits].join(",") },
enter: function(frame) { this.enters++ },
exit: function(res) { this.exits++ }}`
code
:=
[]
byte
{
byte
(
vm
.
PUSH1
),
0
,
byte
(
vm
.
PUSH1
),
0
,
byte
(
vm
.
RETURN
)}
statedb
,
_
:=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
tracer
,
err
:=
tracers
.
DefaultDirectory
.
New
(
jsTracer
,
new
(
tracers
.
Context
),
nil
,
params
.
MergedTestChainConfig
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
_
,
_
,
_
,
err
=
Create
(
code
,
&
Config
{
State
:
statedb
,
EVMConfig
:
vm
.
Config
{
Tracer
:
tracer
.
Hooks
,
}})
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
res
,
err
:=
tracer
.
GetResult
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
have
,
want
:=
string
(
res
),
`"0,0"`
;
have
!=
want
{
t
.
Errorf
(
"wrong result for tracer, have
\n
%v
\n
want
\n
%v
\n
"
,
have
,
want
)
}
}
func
BenchmarkTracerStepVsCallFrame
(
b
*
testing
.
B
)
{
// Simply pushes and pops some values in a loop
p
,
lbl
:=
program
.
New
()
.
Jumpdest
()
code
:=
p
.
Push
(
0
)
.
Push
(
0
)
.
Op
(
vm
.
POP
,
vm
.
POP
)
.
Jump
(
lbl
)
.
Bytes
()
stepTracer
:=
`
{
step: function() {},
fault: function() {},
result: function() {},
}`
callFrameTracer
:=
`
{
enter: function() {},
exit: function() {},
fault: function() {},
result: function() {},
}`
benchmarkNonModifyingCode
(
10000000
,
code
,
"tracer-step-10M"
,
stepTracer
,
b
)
benchmarkNonModifyingCode
(
10000000
,
code
,
"tracer-call-frame-10M"
,
callFrameTracer
,
b
)
}
// TestDelegatedAccountAccessCost tests that calling an account with an EIP-7702
// delegation designator incurs the correct amount of gas based on the tracer.
func
TestDelegatedAccountAccessCost
(
t
*
testing
.
T
)
{
statedb
,
_
:=
state
.
New
(
types
.
EmptyRootHash
,
state
.
NewDatabaseForTesting
())
statedb
.
SetCode
(
common
.
HexToAddress
(
"0xff"
),
types
.
AddressToDelegation
(
common
.
HexToAddress
(
"0xaa"
)))
statedb
.
SetCode
(
common
.
HexToAddress
(
"0xaa"
),
program
.
New
()
.
Return
(
0
,
0
)
.
Bytes
())
for
i
,
tc
:=
range
[]
struct
{
code
[]
byte
step
int
want
uint64
}{
{
// CALL(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
CALL
),
byte
(
vm
.
POP
),
},
step
:
7
,
want
:
5455
,
},
{
// CALLCODE(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
CALLCODE
),
byte
(
vm
.
POP
),
},
step
:
7
,
want
:
5455
,
},
{
// DELEGATECALL(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DELEGATECALL
),
byte
(
vm
.
POP
),
},
step
:
6
,
want
:
5455
,
},
{
// STATICCALL(0xff)
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0x0
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
DUP1
),
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
DUP1
),
byte
(
vm
.
STATICCALL
),
byte
(
vm
.
POP
),
},
step
:
6
,
want
:
5455
,
},
{
// SELFDESTRUCT(0xff): should not be affected by resolution
code
:
[]
byte
{
byte
(
vm
.
PUSH1
),
0xff
,
byte
(
vm
.
SELFDESTRUCT
),
},
step
:
1
,
want
:
7600
,
},
}
{
var
step
=
0
var
have
=
uint64
(
0
)
Execute
(
tc
.
code
,
nil
,
&
Config
{
ChainConfig
:
params
.
MergedTestChainConfig
,
State
:
statedb
,
EVMConfig
:
vm
.
Config
{
Tracer
:
&
tracing
.
Hooks
{
OnOpcode
:
func
(
pc
uint64
,
op
byte
,
gas
,
cost
uint64
,
scope
tracing
.
OpContext
,
rData
[]
byte
,
depth
int
,
err
error
)
{
// Uncomment to investigate failures:
t
.
Logf
(
"%d: %v %d"
,
step
,
vm
.
OpCode
(
op
)
.
String
(),
cost
)
if
step
==
tc
.
step
{
have
=
cost
}
step
++
},
},
},
})
if
want
:=
tc
.
want
;
have
!=
want
{
t
.
Fatalf
(
"testcase %d, gas report wrong, step %d, have %d want %d"
,
i
,
tc
.
step
,
have
,
want
)
}
}
}
go.mod
View file @
1fff77e7
...
...
@@ -3,33 +3,27 @@ module code.wuban.net.cn/cmpchain/ethtracer
go 1.24.0
require (
github.com/CaduceusMetaverseProtocol/MetaProtocol v0.0.0-00010101000000-000000000000
code.wuban.net.cn/cmpchain/ethcrypto v0.0.0-20250707071006-5c3f8f42b6ad
github.com/CaduceusMetaverseProtocol/MetaTypes v1.0.0
github.com/consensys/gnark-crypto v0.18.0
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a
github.com/ethereum/go-verkle v0.2.2
github.com/holiman/uint256 v1.3.2
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.10.0
golang.org/x/crypto v0.36.0
)
require (
code.wuban.net.cn/cmpchain/ethcrypto v0.0.0-20250707071006-5c3f8f42b6ad // indirect
github.com/bits-and-blooms/bitset v1.20.0 // indirect
github.com/consensys/gnark-crypto v0.18.0 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect
github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 // indirect
github.com/ethereum/go-verkle v0.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/supranational/blst v0.3.14 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.33.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
...
...
go.sum
View file @
1fff77e7
code.wuban.net.cn/cmpchain/ethcrypto v0.0.0-20250707002024-1f73f3d61c24 h1:yfcvA4ma+sn2LaUSDKEqlLCqc8O38kRNzZX022FRFEA=
code.wuban.net.cn/cmpchain/ethcrypto v0.0.0-20250707002024-1f73f3d61c24/go.mod h1:yA5sSeNbmo4+xVQ5P0/5xAA/jh8eP3CYB9M+sGn3llM=
code.wuban.net.cn/cmpchain/ethcrypto v0.0.0-20250707071006-5c3f8f42b6ad h1:3oJWA4OyqocLv8uwSV47wba6+ZX+Pq7EBI4kolp+RbI=
code.wuban.net.cn/cmpchain/ethcrypto v0.0.0-20250707071006-5c3f8f42b6ad/go.mod h1:yA5sSeNbmo4+xVQ5P0/5xAA/jh8eP3CYB9M+sGn3llM=
github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU=
github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0=
github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c=
github.com/crate-crypto/go-ipa v0.0.0-20240
223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I
=
github.com/crate-crypto/go-ipa v0.0.0-20240
223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs
=
github.com/crate-crypto/go-ipa v0.0.0-20240
724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg
=
github.com/crate-crypto/go-ipa v0.0.0-20240
724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM
=
github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4=
github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 h1:B2mpK+MNqgPqk2/KNi1LbqwtZDy5F7iy0mynQiBr8VA=
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4/go.mod h1:y4GA2JbAUama1S4QwYjC2hefgGLU8Ul0GMtL/ADMF1c=
github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
...
...
@@ -47,46 +39,18 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo=
github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
stateless/encoding.go
View file @
1fff77e7
...
...
@@ -17,10 +17,10 @@
package
stateless
import
(
"code.wuban.net.cn/cmpchain/ethtracer/evm/evmtypes"
"io"
"code.wuban.net.cn/cmpchain/ethcrypto/rlp"
"code.wuban.net.cn/cmpchain/ethtracer/types"
)
// toExtWitness converts our internal witness representation to the consensus one.
...
...
@@ -70,7 +70,7 @@ func (w *Witness) DecodeRLP(s *rlp.Stream) error {
// extWitness is a witness RLP encoding for transferring across clients.
type
extWitness
struct
{
Headers
[]
*
types
.
Header
Headers
[]
*
evm
types
.
Header
Codes
[][]
byte
State
[][]
byte
}
stateless/witness.go
View file @
1fff77e7
...
...
@@ -17,28 +17,27 @@
package
stateless
import
(
"code.wuban.net.cn/cmpchain/ethtracer/evm/evmtypes"
"errors"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"maps"
"slices"
"sync"
"code.wuban.net.cn/cmpchain/ethtracer/types"
)
// HeaderReader is an interface to pull in headers in place of block hashes for
// the witness.
type
HeaderReader
interface
{
// GetHeader retrieves a block header from the database by hash and number,
GetHeader
(
hash
metatypes
.
Hash
,
number
uint64
)
*
types
.
Header
GetHeader
(
hash
metatypes
.
Hash
,
number
uint64
)
*
evm
types
.
Header
}
// Witness encompasses the state required to apply a set of transactions and
// derive a post state/receipt root.
type
Witness
struct
{
context
*
types
.
Header
// Header to which this witness belongs to, with rootHash and receiptHash zeroed out
context
*
evm
types
.
Header
// Header to which this witness belongs to, with rootHash and receiptHash zeroed out
Headers
[]
*
types
.
Header
// Past headers in reverse order (0=parent, 1=parent's-parent, etc). First *must* be set.
Headers
[]
*
evmtypes
.
Header
// Past headers in reverse order (0=parent, 1=parent's-parent, etc). First *must* be set.
Codes
map
[
string
]
struct
{}
// Set of bytecodes ran or accessed
State
map
[
string
]
struct
{}
// Set of MPT state trie nodes (account and storage together)
...
...
@@ -47,12 +46,12 @@ type Witness struct {
}
// NewWitness creates an empty witness ready for population.
func
NewWitness
(
context
*
types
.
Header
,
chain
HeaderReader
)
(
*
Witness
,
error
)
{
func
NewWitness
(
context
*
evm
types
.
Header
,
chain
HeaderReader
)
(
*
Witness
,
error
)
{
// When building witnesses, retrieve the parent header, which will *always*
// be included to act as a trustless pre-root hash container
var
headers
[]
*
types
.
Header
var
headers
[]
*
evm
types
.
Header
if
chain
!=
nil
{
parent
:=
chain
.
GetHeader
(
context
.
Parent
(),
context
.
Number
()
.
Uint64
()
-
1
)
parent
:=
chain
.
GetHeader
(
context
.
Parent
Hash
,
context
.
Number
.
Uint64
()
-
1
)
if
parent
==
nil
{
return
nil
,
errors
.
New
(
"failed to retrieve parent header"
)
}
...
...
@@ -73,9 +72,9 @@ func NewWitness(context *types.Header, chain HeaderReader) (*Witness, error) {
// the chain to cover the block being added.
func
(
w
*
Witness
)
AddBlockHash
(
number
uint64
)
{
// Keep pulling in headers until this hash is populated
for
int
(
w
.
context
.
Number
()
.
Uint64
()
-
number
)
>
len
(
w
.
Headers
)
{
for
int
(
w
.
context
.
Number
.
Uint64
()
-
number
)
>
len
(
w
.
Headers
)
{
tail
:=
w
.
Headers
[
len
(
w
.
Headers
)
-
1
]
w
.
Headers
=
append
(
w
.
Headers
,
w
.
chain
.
GetHeader
(
tail
.
Parent
(),
tail
.
Number
()
.
Uint64
()
-
1
))
w
.
Headers
=
append
(
w
.
Headers
,
w
.
chain
.
GetHeader
(
tail
.
Parent
Hash
,
tail
.
Number
.
Uint64
()
-
1
))
}
}
...
...
@@ -108,7 +107,7 @@ func (w *Witness) Copy() *Witness {
chain
:
w
.
chain
,
}
if
w
.
context
!=
nil
{
cpy
.
context
=
types
.
CopyHeader
(
w
.
context
)
cpy
.
context
=
evm
types
.
CopyHeader
(
w
.
context
)
}
return
cpy
}
...
...
@@ -118,5 +117,5 @@ func (w *Witness) Copy() *Witness {
// Note, this method will panic in case of a bad witness (but RLP decoding will
// sanitize it and fail before that).
func
(
w
*
Witness
)
Root
()
metatypes
.
Hash
{
return
w
.
Headers
[
0
]
.
Root
()
return
w
.
Headers
[
0
]
.
Root
}
tracing/hooks.go
View file @
1fff77e7
...
...
@@ -25,12 +25,12 @@
package
tracing
import
(
"code.wuban.net.cn/cmpchain/ethtracer/evm/evmtypes"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"github.com/CaduceusMetaverseProtocol/MetaTypes/types/coretype"
metacore
"github.com/CaduceusMetaverseProtocol/MetaTypes/types/coretype"
"math/big"
"code.wuban.net.cn/cmpchain/ethtracer/params"
"code.wuban.net.cn/cmpchain/ethtracer/types"
"github.com/holiman/uint256"
)
...
...
@@ -71,9 +71,9 @@ type VMContext struct {
// BlockEvent is emitted upon tracing an incoming block.
// It contains the block as well as consensus related information.
type
BlockEvent
struct
{
Block
*
types
.
Block
Finalized
*
types
.
Header
Safe
*
types
.
Header
Block
*
evm
types
.
Block
Finalized
*
evm
types
.
Header
Safe
*
evm
types
.
Header
}
type
(
...
...
@@ -84,10 +84,10 @@ type (
// TxStartHook is called before the execution of a transaction starts.
// Call simulations don't come with a valid signature. `from` field
// to be used for address of the caller.
TxStartHook
=
func
(
vm
*
VMContext
,
tx
*
types
.
Transaction
,
from
metatypes
.
Address
)
TxStartHook
=
func
(
vm
*
VMContext
,
tx
*
evm
types
.
Transaction
,
from
metatypes
.
Address
)
// TxEndHook is called after the execution of a transaction ends.
TxEndHook
=
func
(
receipt
*
types
.
Receipt
,
err
error
)
TxEndHook
=
func
(
receipt
*
evm
types
.
Receipt
,
err
error
)
// EnterHook is invoked when the processing of a message starts.
//
...
...
@@ -140,7 +140,7 @@ type (
SkippedBlockHook
=
func
(
event
BlockEvent
)
// GenesisBlockHook is called when the genesis block is being processed.
GenesisBlockHook
=
func
(
genesis
*
types
.
Block
,
alloc
coretyp
e
.
GenesisAccount
)
GenesisBlockHook
=
func
(
genesis
*
evmtypes
.
Block
,
alloc
metacor
e
.
GenesisAccount
)
// OnSystemCallStartHook is called when a system call is about to be executed. Today,
// this hook is invoked when the EIP-4788 system call is about to be executed to set the
...
...
@@ -182,7 +182,7 @@ type (
StorageChangeHook
=
func
(
addr
metatypes
.
Address
,
slot
metatypes
.
Hash
,
prev
,
new
metatypes
.
Hash
)
// LogHook is called when a log is emitted.
LogHook
=
func
(
log
*
types
.
Log
)
LogHook
=
func
(
log
*
evm
types
.
Log
)
// BlockHashReadHook is called when EVM reads the blockhash of a block.
BlockHashReadHook
=
func
(
blockNumber
uint64
,
hash
metatypes
.
Hash
)
...
...
tracing/journal.go
View file @
1fff77e7
...
...
@@ -17,10 +17,10 @@
package
tracing
import
(
"code.wuban.net.cn/cmpchain/ethtracer/evm/evmtypes"
"fmt"
"math/big"
"code.wuban.net.cn/cmpchain/ethtracer/types"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
)
...
...
@@ -112,7 +112,7 @@ func (j *journal) popRevision() {
}
// OnTxEnd resets the journal since each transaction has its own EVM call stack.
func
(
j
*
journal
)
OnTxEnd
(
receipt
*
types
.
Receipt
,
err
error
)
{
func
(
j
*
journal
)
OnTxEnd
(
receipt
*
evm
types
.
Receipt
,
err
error
)
{
j
.
reset
()
if
j
.
hooks
.
OnTxEnd
!=
nil
{
j
.
hooks
.
OnTxEnd
(
receipt
,
err
)
...
...
types/types.go
View file @
1fff77e7
package
types
import
(
basetype
"github.com/CaduceusMetaverseProtocol/MetaProtocol/gen/proto/go/base/v1"
metatypes
"github.com/CaduceusMetaverseProtocol/MetaTypes/types"
"math/big"
)
var
(
...
...
@@ -12,69 +10,70 @@ var (
EmptyCodeHash
=
metatypes
.
HexToHash
(
"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
)
)
type
Block
struct
{
*
basetype
.
MetaBlock
}
type
Header
struct
{
*
basetype
.
MetaBlockHeader
}
func
(
h
*
Header
)
Number
()
*
big
.
Int
{
return
h
.
BlockNumber
.
GetInt
()
}
func
(
h
*
Header
)
Parent
()
metatypes
.
Hash
{
return
*
h
.
ParentHash
}
func
(
h
*
Header
)
Root
()
metatypes
.
Hash
{
return
*
h
.
StateRoot
}
type
Transaction
struct
{
*
basetype
.
MetaProofTx
}
type
Receipt
struct
{
*
basetype
.
MetaReceipt
}
type
Log
struct
{
*
basetype
.
MetaTxLog
}
func
NewLog
(
addr
metatypes
.
Address
,
topics
[]
metatypes
.
Hash
,
data
[]
byte
,
number
uint64
)
*
Log
{
l
:=
&
Log
{
MetaTxLog
:
&
basetype
.
MetaTxLog
{
Address
:
new
(
metatypes
.
Address
),
Topics
:
make
([]
*
basetype
.
MetaTopic
,
len
(
topics
)),
Data
:
data
,
BlockNumber
:
number
,
},
}
l
.
Address
.
SetBytes
(
addr
.
Bytes
())
for
i
,
topic
:=
range
topics
{
l
.
Topics
[
i
]
=
&
basetype
.
MetaTopic
{
Topic
:
new
(
metatypes
.
Hash
),
}
l
.
Topics
[
i
]
.
Topic
.
SetBytes
(
topic
.
Bytes
())
}
return
l
}
//type GenesisAlloc struct {
// *basetype.MetaGenesisAlloc
//
//type Block struct {
// *basetype.MetaBlock
//}
//
//type Header struct {
// *basetype.MetaBlockHeader
//}
//
//func (h *Header) Number() *big.Int {
// return h.BlockNumber.GetInt()
//}
//
//func (h *Header) Parent() metatypes.Hash {
// return *h.ParentHash
//}
//func (h *Header) Root() metatypes.Hash {
// return *h.StateRoot
//}
//
//type Transaction struct {
// *basetype.MetaProofTx
//}
//
//type Receipt struct {
// *basetype.MetaReceipt
//}
//
//type Log struct {
// *basetype.MetaTxLog
//}
//
//func NewLog(addr metatypes.Address, topics []metatypes.Hash, data []byte, number uint64) *Log {
// l := &Log{
// MetaTxLog: &basetype.MetaTxLog{
// Address: new(metatypes.Address),
// Topics: make([]*basetype.MetaTopic, len(topics)),
// Data: data,
// BlockNumber: number,
// },
// }
// l.Address.SetBytes(addr.Bytes())
// for i, topic := range topics {
// l.Topics[i] = &basetype.MetaTopic{
// Topic: new(metatypes.Hash),
// }
// l.Topics[i].Topic.SetBytes(topic.Bytes())
// }
// return l
//}
//
////type GenesisAlloc struct {
//// *basetype.MetaGenesisAlloc
////}
//
//func CopyHeader(h *Header) *Header {
// return &Header{
// MetaBlockHeader: &basetype.MetaBlockHeader{
// BlockNumber: h.BlockNumber,
// ParentHash: h.ParentHash,
// Timestamp: h.Timestamp,
// Miner: h.Miner,
// GasLimit: h.GasLimit,
// GasUsed: h.GasUsed,
// },
// }
//}
func
CopyHeader
(
h
*
Header
)
*
Header
{
return
&
Header
{
MetaBlockHeader
:
&
basetype
.
MetaBlockHeader
{
BlockNumber
:
h
.
BlockNumber
,
ParentHash
:
h
.
ParentHash
,
Timestamp
:
h
.
Timestamp
,
Miner
:
h
.
Miner
,
GasLimit
:
h
.
GasLimit
,
GasUsed
:
h
.
GasUsed
,
},
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment