mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-03 01:27:38 +00:00
[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:
parent
3f34dee475
commit
759fb00593
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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"},
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))
|
||||
})
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user