[beta] Stricter uint256 RLP decoding. Update consensus tests to 10.1 (#3089)

* Clean up test runners. Don't run legacy tests

* Cherry pick https://github.com/ethereum/go-ethereum/pull/22927

* Tests update 10.1: Transaction Tests

* Port decodeBigInt changes to decodeUint256

* Introduce (*Stream) Uint256Bytes

* Temporarily disable stTransactionTest/HighGasPrice

* linter

* ttWrongRLP transaction tests pass now

* Fix stTransactionTest/HighGasPrice

Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
Andrew Ashikhmin 2021-12-06 08:00:54 +00:00 committed by GitHub
parent 3f34dee475
commit 759fb00593
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 191 additions and 286 deletions

View File

@ -203,12 +203,21 @@ func (st *StateTransition) to() common.Address {
func (st *StateTransition) buyGas(gasBailout bool) error {
mgval := st.sharedBuyGas
mgval.SetUint64(st.msg.Gas())
mgval = mgval.Mul(mgval, st.gasPrice)
mgval, overflow := mgval.MulOverflow(mgval, st.gasPrice)
if overflow {
return fmt.Errorf("%w: address %v", ErrInsufficientFunds, st.msg.From().Hex())
}
balanceCheck := mgval
if st.gasFeeCap != nil {
balanceCheck = st.sharedBuyGasBalance.SetUint64(st.msg.Gas())
balanceCheck = balanceCheck.Mul(balanceCheck, st.gasFeeCap)
balanceCheck.Add(balanceCheck, st.value)
balanceCheck, overflow = balanceCheck.MulOverflow(balanceCheck, st.gasFeeCap)
if overflow {
return fmt.Errorf("%w: address %v", ErrInsufficientFunds, st.msg.From().Hex())
}
balanceCheck, overflow = balanceCheck.AddOverflow(balanceCheck, st.value)
if overflow {
return fmt.Errorf("%w: address %v", ErrInsufficientFunds, st.msg.From().Hex())
}
}
if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 {
if !gasBailout {

View File

@ -465,22 +465,16 @@ func (tx *AccessListTx) DecodeRLP(s *rlp.Stream) error {
return err
}
var b []byte
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read ChainID: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for ChainID: %d", len(b))
}
tx.ChainID = new(uint256.Int).SetBytes(b)
if tx.Nonce, err = s.Uint(); err != nil {
return fmt.Errorf("read Nonce: %w", err)
}
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read GasPrice: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for GasPrice: %d", len(b))
}
tx.GasPrice = new(uint256.Int).SetBytes(b)
if tx.Gas, err = s.Uint(); err != nil {
return fmt.Errorf("read Gas: %w", err)
@ -495,12 +489,9 @@ func (tx *AccessListTx) DecodeRLP(s *rlp.Stream) error {
tx.To = &common.Address{}
copy((*tx.To)[:], b)
}
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read Value: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for Value: %d", len(b))
}
tx.Value = new(uint256.Int).SetBytes(b)
if tx.Data, err = s.Bytes(); err != nil {
return fmt.Errorf("read Data: %w", err)
@ -511,26 +502,17 @@ func (tx *AccessListTx) DecodeRLP(s *rlp.Stream) error {
return fmt.Errorf("read AccessList: %w", err)
}
// decode V
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read V: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for V: %d", len(b))
}
tx.V.SetBytes(b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read R: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for R: %d", len(b))
}
tx.R.SetBytes(b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read S: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for S: %d", len(b))
}
tx.S.SetBytes(b)
if err := s.ListEnd(); err != nil {
return fmt.Errorf("close AccessListTx: %w", err)

View File

@ -486,19 +486,13 @@ func (h *Header) DecodeRLP(s *rlp.Stream) error {
return fmt.Errorf("wrong size for Bloom: %d", len(b))
}
copy(h.Bloom[:], b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read Difficulty: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for Difficulty: %d", len(b))
}
h.Difficulty = new(big.Int).SetBytes(b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read Number: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for Number: %d", len(b))
}
h.Number = new(big.Int).SetBytes(b)
if h.GasLimit, err = s.Uint(); err != nil {
return fmt.Errorf("read GasLimit: %w", err)
@ -536,7 +530,7 @@ func (h *Header) DecodeRLP(s *rlp.Stream) error {
return fmt.Errorf("wrong size for Nonce: %d", len(b))
}
copy(h.Nonce[:], b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
if errors.Is(err, rlp.EOL) {
h.BaseFee = nil
h.Eip1559 = false
@ -547,9 +541,6 @@ func (h *Header) DecodeRLP(s *rlp.Stream) error {
}
return fmt.Errorf("read BaseFee: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for BaseFee: %d", len(b))
}
h.Eip1559 = true
h.BaseFee = new(big.Int).SetBytes(b)
}

View File

@ -378,29 +378,20 @@ func (tx *DynamicFeeTransaction) DecodeRLP(s *rlp.Stream) error {
return err
}
var b []byte
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return err
}
if len(b) > 32 {
return fmt.Errorf("wrong size for ChainID: %d", len(b))
}
tx.ChainID = new(uint256.Int).SetBytes(b)
if tx.Nonce, err = s.Uint(); err != nil {
return err
}
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return err
}
if len(b) > 32 {
return fmt.Errorf("wrong size for MaxPriorityFeePerGas: %d", len(b))
}
tx.Tip = new(uint256.Int).SetBytes(b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return err
}
if len(b) > 32 {
return fmt.Errorf("wrong size for MaxFeePerGas: %d", len(b))
}
tx.FeeCap = new(uint256.Int).SetBytes(b)
if tx.Gas, err = s.Uint(); err != nil {
return err
@ -415,12 +406,9 @@ func (tx *DynamicFeeTransaction) DecodeRLP(s *rlp.Stream) error {
tx.To = &common.Address{}
copy((*tx.To)[:], b)
}
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return err
}
if len(b) > 32 {
return fmt.Errorf("wrong size for Value: %d", len(b))
}
tx.Value = new(uint256.Int).SetBytes(b)
if tx.Data, err = s.Bytes(); err != nil {
return err
@ -431,26 +419,17 @@ func (tx *DynamicFeeTransaction) DecodeRLP(s *rlp.Stream) error {
return err
}
// decode V
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return err
}
if len(b) > 32 {
return fmt.Errorf("wrong size for V: %d", len(b))
}
tx.V.SetBytes(b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return err
}
if len(b) > 32 {
return fmt.Errorf("wrong size for R: %d", len(b))
}
tx.R.SetBytes(b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return err
}
if len(b) > 32 {
return fmt.Errorf("wrong size for S: %d", len(b))
}
tx.S.SetBytes(b)
return s.ListEnd()

View File

@ -369,12 +369,9 @@ func (tx *LegacyTx) DecodeRLP(s *rlp.Stream, encodingSize uint64) error {
return fmt.Errorf("read Nonce: %w", err)
}
var b []byte
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read GasPrice: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for GasPrice: %d", len(b))
}
tx.GasPrice = new(uint256.Int).SetBytes(b)
if tx.Gas, err = s.Uint(); err != nil {
return fmt.Errorf("read Gas: %w", err)
@ -389,36 +386,24 @@ func (tx *LegacyTx) DecodeRLP(s *rlp.Stream, encodingSize uint64) error {
tx.To = &common.Address{}
copy((*tx.To)[:], b)
}
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read Value: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for Value: %d", len(b))
}
tx.Value = new(uint256.Int).SetBytes(b)
if tx.Data, err = s.Bytes(); err != nil {
return fmt.Errorf("read Data: %w", err)
}
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read V: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for V: %d", len(b))
}
tx.V.SetBytes(b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read R: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for R: %d", len(b))
}
tx.R.SetBytes(b)
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read S: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for S: %d", len(b))
}
tx.S.SetBytes(b)
if err = s.ListEnd(); err != nil {
return fmt.Errorf("close tx struct: %w", err)

View File

@ -373,12 +373,9 @@ func (nbp *NewBlockPacket) DecodeRLP(s *rlp.Stream) error {
}
// decode TD
var b []byte
if b, err = s.Bytes(); err != nil {
if b, err = s.Uint256Bytes(); err != nil {
return fmt.Errorf("read TD: %w", err)
}
if len(b) > 32 {
return fmt.Errorf("wrong size for TD: %d", len(b))
}
nbp.TD = new(big.Int).SetBytes(b)
if err = s.ListEnd(); err != nil {
return err

View File

@ -242,19 +242,17 @@ func decodeBigIntNoPtr(s *Stream, val reflect.Value) error {
}
func decodeBigInt(s *Stream, val reflect.Value) error {
b, err := s.Bytes()
b, err := s.bigIntBytes()
if err != nil {
return wrapStreamError(err, val.Type())
}
// Set the integer bytes.
i := val.Interface().(*big.Int)
if i == nil {
i = new(big.Int)
val.Set(reflect.ValueOf(i))
}
// Reject leading zero bytes
if len(b) > 0 && b[0] == 0 {
return wrapStreamError(ErrCanonInt, val.Type())
}
i.SetBytes(b)
return nil
}
@ -264,22 +262,17 @@ func decodeUint256NoPtr(s *Stream, val reflect.Value) error {
}
func decodeUint256(s *Stream, val reflect.Value) error {
b, err := s.Bytes()
b, err := s.Uint256Bytes()
if err != nil {
return wrapStreamError(err, val.Type())
}
if len(b) > 32 {
return wrapStreamError(errUintOverflow, val.Type())
}
// Set the integer bytes.
i := val.Interface().(*uint256.Int)
if i == nil {
i = new(uint256.Int)
val.Set(reflect.ValueOf(i))
}
// Reject leading zero bytes
if len(b) > 0 && b[0] == 0 {
return wrapStreamError(ErrCanonInt, val.Type())
}
i.SetBytes(b)
return nil
}
@ -599,7 +592,7 @@ type Stream struct {
limited bool
// auxiliary buffer for integer decoding
uintbuf []byte
uintbuf [32]byte
kind Kind // kind of value ahead
size uint64 // size of value ahead
@ -734,6 +727,59 @@ func (s *Stream) uint(maxbits int) (uint64, error) {
}
}
func (s *Stream) Uint256Bytes() ([]byte, error) {
b, err := s.bigIntBytes()
if err != nil {
return nil, err
}
if len(b) > 32 {
return nil, errUintOverflow
}
return b, nil
}
func (s *Stream) bigIntBytes() ([]byte, error) {
var buffer []byte
kind, size, err := s.Kind()
switch {
case err != nil:
return nil, err
case kind == List:
return nil, ErrExpectedString
case kind == Byte:
buffer = s.uintbuf[:1]
buffer[0] = s.byteval
s.kind = -1 // re-arm Kind
case size == 0:
// Avoid zero-length read.
s.kind = -1
case size <= uint64(len(s.uintbuf)):
// For integers smaller than s.uintbuf, allocating a buffer
// can be avoided.
buffer = s.uintbuf[:size]
if err := s.readFull(buffer); err != nil {
return nil, err
}
// Reject inputs where single byte encoding should have been used.
if size == 1 && buffer[0] < 128 {
return nil, ErrCanonSize
}
default:
// For large integers, a temporary buffer is needed.
buffer = make([]byte, size)
if err := s.readFull(buffer); err != nil {
return nil, err
}
}
// Reject leading zero bytes.
if len(buffer) > 0 && buffer[0] == 0 {
return nil, ErrCanonInt
}
return buffer, nil
}
// Bool reads an RLP string of up to 1 byte and returns its contents
// as a boolean. If the input does not contain an RLP string, the
// returned error will be ErrExpectedString.
@ -856,9 +902,7 @@ func (s *Stream) Reset(r io.Reader, inputLimit uint64) {
s.size = 0
s.kind = -1
s.kinderr = nil
if s.uintbuf == nil {
s.uintbuf = make([]byte, 8)
}
s.uintbuf = [32]byte{}
s.byteval = 0
}
@ -977,20 +1021,20 @@ func (s *Stream) readUint(size byte) (uint64, error) {
b, err := s.readByte()
return uint64(b), err
default:
start := int(8 - size)
for i := 0; i < start; i++ {
s.uintbuf[i] = 0
buffer := s.uintbuf[:8]
for i := range buffer {
buffer[i] = 0
}
if err := s.readFull(s.uintbuf[start:]); err != nil {
start := int(8 - size)
if err := s.readFull(buffer[start:]); err != nil {
return 0, err
}
if s.uintbuf[start] == 0 {
// Note: readUint is also used to decode integer
// values. The error needs to be adjusted to become
// ErrCanonInt in this case.
if buffer[start] == 0 {
// Note: readUint is also used to decode integer values.
// The error needs to be adjusted to become ErrCanonInt in this case.
return 0, ErrCanonSize
}
return binary.BigEndian.Uint64(s.uintbuf), nil
return binary.BigEndian.Uint64(buffer), nil
}
}

View File

@ -327,6 +327,11 @@ type recstruct struct {
Child *recstruct `rlp:"nil"`
}
type bigIntStruct struct {
I *big.Int
B string
}
type invalidNilTag struct {
X []byte `rlp:"nil"`
}
@ -375,6 +380,7 @@ var (
uint256.NewInt(0xFFFF),
)
realBigInt = big.NewInt(0).SetBytes(unhex("010000000000000000000000000000000000000000000000000000000000000000"))
veryVeryBigInt = new(big.Int).Exp(veryBigInt.ToBig(), big.NewInt(8), nil)
)
type hasIgnoredField struct {
@ -451,13 +457,16 @@ var decodeTests = []decodeTest{
{input: "C0", ptr: new(string), error: "rlp: expected input string or byte for string"},
// big ints
{input: "80", ptr: new(*big.Int), value: big.NewInt(0)},
{input: "01", ptr: new(*big.Int), value: big.NewInt(1)},
{input: "89FFFFFFFFFFFFFFFFFF", ptr: new(*big.Int), value: veryBigInt.ToBig()},
{input: "A1010000000000000000000000000000000000000000000000000000000000000000", ptr: new(*big.Int), value: realBigInt},
{input: "B848FFFFFFFFFFFFFFFFF800000000000000001BFFFFFFFFFFFFFFFFC8000000000000000045FFFFFFFFFFFFFFFFC800000000000000001BFFFFFFFFFFFFFFFFF8000000000000000001", ptr: new(*big.Int), value: veryVeryBigInt},
{input: "10", ptr: new(big.Int), value: *big.NewInt(16)}, // non-pointer also works
{input: "C0", ptr: new(*big.Int), error: "rlp: expected input string or byte for *big.Int"},
{input: "820001", ptr: new(big.Int), error: "rlp: non-canonical integer (leading zero bytes) for *big.Int"},
{input: "8105", ptr: new(big.Int), error: "rlp: non-canonical size information for *big.Int"},
{input: "00", ptr: new(*big.Int), error: "rlp: non-canonical integer (leading zero bytes) for *big.Int"},
{input: "820001", ptr: new(*big.Int), error: "rlp: non-canonical integer (leading zero bytes) for *big.Int"},
{input: "8105", ptr: new(*big.Int), error: "rlp: non-canonical size information for *big.Int"},
// uint256
{input: "01", ptr: new(*uint256.Int), value: uint256.NewInt(1)},
@ -479,6 +488,13 @@ var decodeTests = []decodeTest{
ptr: new(recstruct),
value: recstruct{1, &recstruct{2, &recstruct{3, nil}}},
},
{
// This checks that empty big.Int works correctly in struct context. It's easy to
// miss the update of s.kind for this case, so it needs its own test.
input: "C58083343434",
ptr: new(bigIntStruct),
value: bigIntStruct{new(big.Int), "444"},
},
// struct errors
{

View File

@ -134,6 +134,14 @@ var encTests = []encTest{
val: big.NewInt(0).SetBytes(unhex("010000000000000000000000000000000000000000000000000000000000000000")),
output: "A1010000000000000000000000000000000000000000000000000000000000000000",
},
{
val: veryBigInt,
output: "89FFFFFFFFFFFFFFFFFF",
},
{
val: veryVeryBigInt,
output: "B848FFFFFFFFFFFFFFFFF800000000000000001BFFFFFFFFFFFFFFFFC8000000000000000045FFFFFFFFFFFFFFFFC800000000000000001BFFFFFFFFFFFFFFFFF8000000000000000001",
},
// non-pointer big.Int
{val: *big.NewInt(0), output: "80"},

View File

@ -32,33 +32,8 @@ func TestBlockchain(t *testing.T) {
bt := new(testMatcher)
// General state tests are 'exported' as blockchain tests, but we can run them natively.
// For speedier CI-runs, the line below can be uncommented, so those are skipped.
// For now, in hardfork-times (Berlin), we run the tests both as StateTests and
// as blockchain tests, since the latter also covers things like receipt root
//bt.skipLoad(`^GeneralStateTests/`)
// Skip random failures due to selfish mining test
bt.skipLoad(`.*bcForgedTest/bcForkUncle\.json`)
// Slow tests
bt.slow(`.*bcExploitTest/DelegateCallSpam.json`)
bt.slow(`.*bcExploitTest/ShanghaiLove.json`)
bt.slow(`.*bcExploitTest/SuicideIssue.json`)
bt.slow(`.*/bcForkStressTest/`)
bt.slow(`.*/bcGasPricerTest/RPC_API_Test.json`)
bt.slow(`.*/bcWalletTest/`)
// Very slow test
bt.skipLoad(`.*/stTimeConsuming/.*`)
// test takes a lot for time and goes easily OOM because of sha3 calculation on a huge range,
// using 4.6 TGas
bt.skipLoad(`.*randomStatetest94.json.*`)
bt.fails(`(?m)^TestBlockchain/InvalidBlocks/bcInvalidHeaderTest/wrongReceiptTrie.json/wrongReceiptTrie_EIP150`, "No receipt validation before Byzantium")
bt.fails(`(?m)^TestBlockchain/InvalidBlocks/bcInvalidHeaderTest/wrongReceiptTrie.json/wrongReceiptTrie_EIP158`, "No receipt validation before Byzantium")
bt.fails(`(?m)^TestBlockchain/InvalidBlocks/bcInvalidHeaderTest/wrongReceiptTrie.json/wrongReceiptTrie_Frontier`, "No receipt validation before Byzantium")
bt.fails(`(?m)^TestBlockchain/InvalidBlocks/bcInvalidHeaderTest/wrongReceiptTrie.json/wrongReceiptTrie_Homestead`, "No receipt validation before Byzantium")
// For speedier CI-runs those are skipped.
bt.skipLoad(`^GeneralStateTests/`)
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
// import pre accounts & construct test genesis block & state root
@ -66,8 +41,4 @@ func TestBlockchain(t *testing.T) {
t.Error(err)
}
})
// There is also a LegacyTests folder, containing blockchain tests generated
// prior to Istanbul. However, they are all derived from GeneralStateTests,
// which run natively, so there's no reason to run them here.
}

View File

@ -37,8 +37,6 @@ var (
baseDir = filepath.Join(".", "testdata")
blockTestDir = filepath.Join(baseDir, "BlockchainTests")
stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
vmTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "VMTests")
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
rlpTestDir = filepath.Join(baseDir, "RLPTests")
difficultyTestDir = filepath.Join(baseDir, "BasicTests")

View File

@ -39,21 +39,10 @@ func TestState(t *testing.T) {
t.Parallel()
st := new(testMatcher)
// Long tests:
st.slow(`^stAttackTest/ContractCreationSpam`)
st.slow(`^stBadOpcode/badOpcodes`)
st.slow(`^stPreCompiledContracts/modexp`)
st.slow(`^stQuadraticComplexityTest/`)
st.slow(`^stStaticCall/static_Call50000`)
st.slow(`^stStaticCall/static_Return50000`)
st.slow(`^stSystemOperationsTest/CallRecursiveBomb`)
st.slow(`^stTransactionTest/Opcodes_TransactionInit`)
// Very time consuming
st.skipLoad(`^stTimeConsuming/`)
// Uses 1GB RAM per tested fork
st.skipLoad(`^stStaticCall/static_Call1MB`)
st.skipLoad(`.*vmPerformance/loop.*`)
// Broken tests:
st.skipLoad(`^stCreate2/create2collisionStorage.json`)
@ -61,20 +50,10 @@ func TestState(t *testing.T) {
st.skipLoad(`^stSStoreTest/InitCollision.json`)
st.skipLoad(`^stEIP1559/typeTwoBerlin.json`)
// Expected failures:
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/0`, "bug in test")
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/3`, "bug in test")
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Constantinople/0`, "bug in test")
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Constantinople/3`, "bug in test")
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/ConstantinopleFix/0`, "bug in test")
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/ConstantinopleFix/3`, "bug in test")
// https://github.com/ethereum/tests/issues/1001
st.skipLoad(`^stTransactionTest/ValueOverflow.json`)
// For Istanbul, older tests were moved into LegacyTests
for _, dir := range []string{
stateTestDir,
legacyStateTestDir,
} {
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
st.walk(t, stateTestDir, func(t *testing.T, name string, test *StateTest) {
db := memdb.NewTestDB(t)
for _, subtest := range test.Subtests() {
subtest := subtest
@ -99,7 +78,6 @@ func TestState(t *testing.T) {
}
})
}
}
// Transactions with gasLimit above this value will not get a VM trace on failure.
const traceErrorLimit = 400000

View File

@ -230,13 +230,6 @@ func (t *StateTest) RunNoVerify(rules params.Rules, tx kv.RwTx, subtest StateSub
statedb.RevertToSnapshot(snapshot)
}
// And _now_ get the state root
// Add 0-value mining reward. This only makes a difference in the cases
// where
// - the coinbase suicided, or
// - there are only 'bad' transactions, which aren't executed. In those cases,
// the coinbase gets no txfee, so isn't created, and thus needs to be touched
statedb.AddBalance(block.Coinbase(), new(uint256.Int))
if err = statedb.FinalizeTx(evm.ChainRules, w); err != nil {
return nil, common.Hash{}, err
}

@ -1 +1 @@
Subproject commit 52cb3b3e724d13943bd8a457ed70929f98b9b8bf
Subproject commit fbff6fee061ade2358280a8d6f98f67b4ae2b60e

View File

@ -26,25 +26,16 @@ func TestTransaction(t *testing.T) {
t.Parallel()
txt := new(testMatcher)
// These can't be parsed, invalid hex in RLP
txt.skipLoad("^ttWrongRLP/.*")
// We don't allow more than uint64 in gas amount
// This is a pseudo-consensus vulnerability, but not in practice
// because of the gas limit
txt.skipLoad("^ttGasLimit/TransactionWithGasLimitxPriceOverflow.json")
// We _do_ allow more than uint64 in gas price, as opposed to the tests
// This is also not a concern, as long as tx.Cost() uses big.Int for
// calculating the final cozt
txt.skipLoad(".*TransactionWithGasPriceOverflow.*")
// The nonce is too large for uint64. Not a concern, it means geth won't
// accept transactions at a certain point in the distant future
txt.skipLoad("^ttNonce/TransactionWithHighNonce256.json")
// The value is larger than uint64, which according to the test is invalid.
// Geth accepts it, which is not a consensus issue since we use big.Int's
// internally to calculate the cost
txt.skipLoad("^ttValue/TransactionWithHighValueOverflow.json")
txt.walk(t, transactionTestDir, func(t *testing.T, name string, test *TransactionTest) {
cfg := params.MainnetChainConfig
if err := txt.checkFailure(t, test.Run(cfg)); err != nil {

View File

@ -30,19 +30,27 @@ import (
// TransactionTest checks RLP decoding and sender derivation of transactions.
type TransactionTest struct {
RLP hexutil.Bytes `json:"rlp"`
RLP hexutil.Bytes `json:"txbytes"`
Forks ttForks `json:"result"`
}
type ttForks struct {
Berlin ttFork
Byzantium ttFork
Constantinople ttFork
Istanbul ttFork
ConstantinopleFix ttFork
EIP150 ttFork
EIP158 ttFork
Frontier ttFork
Homestead ttFork
Istanbul ttFork
London ttFork
}
type ttFork struct {
Sender common.UnprefixedAddress `json:"sender"`
Hash common.UnprefixedHash `json:"hash"`
Exception string `json:"exception"`
Sender common.Address `json:"sender"`
Hash common.Hash `json:"hash"`
}
func (tt *TransactionTest) Run(config *params.ChainConfig) error {
@ -74,19 +82,22 @@ func (tt *TransactionTest) Run(config *params.ChainConfig) error {
isHomestead bool
isIstanbul bool
}{
{"Frontier", types.MakeFrontierSigner(), tt.Frontier, false, false},
{"Homestead", types.LatestSignerForChainID(nil), tt.Homestead, true, false},
{"EIP150", types.LatestSignerForChainID(nil), tt.EIP150, true, false},
{"EIP158", types.LatestSignerForChainID(config.ChainID), tt.EIP158, true, false},
{"Byzantium", types.LatestSignerForChainID(config.ChainID), tt.Byzantium, true, false},
{"Constantinople", types.LatestSignerForChainID(config.ChainID), tt.Constantinople, true, false},
{"Istanbul", types.LatestSignerForChainID(config.ChainID), tt.Istanbul, true, true},
{"Frontier", types.MakeFrontierSigner(), tt.Forks.Frontier, false, false},
{"Homestead", types.LatestSignerForChainID(nil), tt.Forks.Homestead, true, false},
{"EIP150", types.LatestSignerForChainID(nil), tt.Forks.EIP150, true, false},
{"EIP158", types.LatestSignerForChainID(config.ChainID), tt.Forks.EIP158, true, false},
{"Byzantium", types.LatestSignerForChainID(config.ChainID), tt.Forks.Byzantium, true, false},
{"Constantinople", types.LatestSignerForChainID(config.ChainID), tt.Forks.Constantinople, true, false},
{"ConstantinopleFix", types.LatestSignerForChainID(config.ChainID), tt.Forks.ConstantinopleFix, true, false},
{"Istanbul", types.LatestSignerForChainID(config.ChainID), tt.Forks.Istanbul, true, true},
{"Berlin", types.LatestSignerForChainID(config.ChainID), tt.Forks.Berlin, true, true},
{"London", types.LatestSignerForChainID(config.ChainID), tt.Forks.London, true, true},
} {
sender, txhash, err := validateTx(tt.RLP, *testcase.signer, testcase.isHomestead, testcase.isIstanbul)
if testcase.fork.Sender == (common.UnprefixedAddress{}) {
if testcase.fork.Exception != "" {
if err == nil {
return fmt.Errorf("expected error, got none (address %v)[%v]", sender.String(), testcase.name)
return fmt.Errorf("expected error %v, got none [%v]", testcase.fork.Exception, testcase.name)
}
continue
}

View File

@ -1,48 +0,0 @@
// Copyright 2014 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 tests
import (
"context"
"testing"
"github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/ledgerwatch/erigon/core/vm"
"github.com/ledgerwatch/log/v3"
)
func TestVM(t *testing.T) {
defer log.Root().SetHandler(log.Root().GetHandler())
log.Root().SetHandler(log.LvlFilterHandler(log.LvlError, log.StderrHandler))
t.Parallel()
vmt := new(testMatcher)
vmt.slow("^vmPerformance")
vmt.fails("^vmSystemOperationsTest.json/createNameRegistrator$", "fails without parallel execution")
db := memdb.NewTestDB(t)
vmt.walk(t, vmTestDir, func(t *testing.T, name string, test *VMTest) {
withTrace(t, test.json.Exec.GasLimit, func(vmconfig vm.Config) error {
tx, err := db.BeginRw(context.Background())
if err != nil {
t.Fatal(err)
}
defer tx.Rollback()
return vmt.checkFailure(t, test.Run(tx, vmconfig, 0))
})
})
}