diff --git a/core/state_transition.go b/core/state_transition.go index 148a319d504..58bf689ebdd 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -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 { diff --git a/core/types/access_list_tx.go b/core/types/access_list_tx.go index 0dd41185445..d46031efdb0 100644 --- a/core/types/access_list_tx.go +++ b/core/types/access_list_tx.go @@ -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) diff --git a/core/types/block.go b/core/types/block.go index 2e99de7d501..969b9cdbb89 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -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) } diff --git a/core/types/dynamic_fee_tx.go b/core/types/dynamic_fee_tx.go index fce6d6197d1..ed8b99d446f 100644 --- a/core/types/dynamic_fee_tx.go +++ b/core/types/dynamic_fee_tx.go @@ -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() diff --git a/core/types/legacy_tx.go b/core/types/legacy_tx.go index 36f8566d815..24a4db88b6b 100644 --- a/core/types/legacy_tx.go +++ b/core/types/legacy_tx.go @@ -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) diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go index 3efba04159b..a8338662bcb 100644 --- a/eth/protocols/eth/protocol.go +++ b/eth/protocols/eth/protocol.go @@ -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 diff --git a/rlp/decode.go b/rlp/decode.go index fefca41ff3c..1568bb60e1d 100644 --- a/rlp/decode.go +++ b/rlp/decode.go @@ -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 } } diff --git a/rlp/decode_test.go b/rlp/decode_test.go index 4e308324426..c91e4865d5d 100644 --- a/rlp/decode_test.go +++ b/rlp/decode_test.go @@ -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"` } @@ -374,7 +379,8 @@ var ( uint256.NewInt(0).Lsh(uint256.NewInt(0xFFFFFFFFFFFFFF), 16), uint256.NewInt(0xFFFF), ) - realBigInt = big.NewInt(0).SetBytes(unhex("010000000000000000000000000000000000000000000000000000000000000000")) + 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 { diff --git a/rlp/encode_test.go b/rlp/encode_test.go index f3bd5e02887..722d8b6d827 100644 --- a/rlp/encode_test.go +++ b/rlp/encode_test.go @@ -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"}, diff --git a/tests/block_test.go b/tests/block_test.go index c04a4088a10..ecc5c653c31 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -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. } diff --git a/tests/init_test.go b/tests/init_test.go index 547720a06fc..fdc478add74 100644 --- a/tests/init_test.go +++ b/tests/init_test.go @@ -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") diff --git a/tests/state_test.go b/tests/state_test.go index 59ebaa88fb7..72d3c317d50 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -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,44 +50,33 @@ 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) { - db := memdb.NewTestDB(t) - for _, subtest := range test.Subtests() { - subtest := subtest - key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index) - t.Run(key, func(t *testing.T) { - withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { - config, ok := Forks[subtest.Fork] - if !ok { - return UnsupportedForkError{subtest.Fork} - } - rules := config.Rules(1) - tx, err := db.BeginRw(context.Background()) - if err != nil { - t.Fatal(err) - } - defer tx.Rollback() - _, err = test.Run(rules, tx, subtest, vmconfig) - tx.Rollback() - return st.checkFailure(t, err) - }) + st.walk(t, stateTestDir, func(t *testing.T, name string, test *StateTest) { + db := memdb.NewTestDB(t) + for _, subtest := range test.Subtests() { + subtest := subtest + key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index) + t.Run(key, func(t *testing.T) { + withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { + config, ok := Forks[subtest.Fork] + if !ok { + return UnsupportedForkError{subtest.Fork} + } + rules := config.Rules(1) + tx, err := db.BeginRw(context.Background()) + if err != nil { + t.Fatal(err) + } + defer tx.Rollback() + _, err = test.Run(rules, tx, subtest, vmconfig) + tx.Rollback() + return st.checkFailure(t, err) }) - } - }) - } + }) + } + }) } // Transactions with gasLimit above this value will not get a VM trace on failure. diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 4529bbfdfdd..ccfc363b806 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -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 } diff --git a/tests/testdata b/tests/testdata index 52cb3b3e724..fbff6fee061 160000 --- a/tests/testdata +++ b/tests/testdata @@ -1 +1 @@ -Subproject commit 52cb3b3e724d13943bd8a457ed70929f98b9b8bf +Subproject commit fbff6fee061ade2358280a8d6f98f67b4ae2b60e diff --git a/tests/transaction_test.go b/tests/transaction_test.go index f4a2d295008..2d528b720e4 100644 --- a/tests/transaction_test.go +++ b/tests/transaction_test.go @@ -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 { diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index 9c70b008cd6..60e79cc5a0c 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -30,19 +30,27 @@ import ( // TransactionTest checks RLP decoding and sender derivation of transactions. type TransactionTest struct { - RLP hexutil.Bytes `json:"rlp"` - Byzantium ttFork - Constantinople ttFork - Istanbul ttFork - EIP150 ttFork - EIP158 ttFork - Frontier ttFork - Homestead ttFork + RLP hexutil.Bytes `json:"txbytes"` + Forks ttForks `json:"result"` +} + +type ttForks struct { + Berlin ttFork + Byzantium ttFork + Constantinople 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 } diff --git a/tests/vm_test.go b/tests/vm_test.go deleted file mode 100644 index 55768bcf71c..00000000000 --- a/tests/vm_test.go +++ /dev/null @@ -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 . - -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)) - }) - }) -}