diff --git a/CHANGELOG.md b/CHANGELOG.md index 42328573492..9029d5ee576 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ This is a release candidate of a patch release that extends EC finality tooling - fix(net): update FIL DevTTY WebTransport certhashes in the mainnet bootstrap list ([filecoin-project/lotus#13530](https://github.com/filecoin-project/lotus/pull/13530)) - fix(gas): stricter bounds for `GasEstimateGasPremium` lookback ([filecoin-project/lotus#13556](https://github.com/filecoin-project/lotus/pull/13556)) - fix: remove duplicate SQL statement entries from `preparedStatementMapping` ([filecoin-project/lotus#13545](https://github.com/filecoin-project/lotus/pull/13545)) +- fix(api): `StateSearchMsg` should respect `lookbackLimit` [filecoin-project/lotus#13562](https://github.com/filecoin-project/lotus/pull/13562) ## 👌 Improvements diff --git a/chain/stmgr/searchwait.go b/chain/stmgr/searchwait.go index 3d7a52ecb4d..2e75c2e44e6 100644 --- a/chain/stmgr/searchwait.go +++ b/chain/stmgr/searchwait.go @@ -158,6 +158,9 @@ func (sm *StateManager) SearchForMessage(ctx context.Context, head *types.TipSet switch { case err == nil: if r != nil && foundMsg.Defined() { + if lookbackLimit != LookbackNoLimit && fts.Height()+lookbackLimit < head.Height() { + return nil, nil, cid.Undef, nil + } return fts, r, foundMsg, nil } diff --git a/chain/types/ethtypes/rlp.go b/chain/types/ethtypes/rlp.go index 65801ac45c8..301165a548d 100644 --- a/chain/types/ethtypes/rlp.go +++ b/chain/types/ethtypes/rlp.go @@ -1,23 +1,50 @@ package ethtypes import ( - "bytes" "encoding/binary" + "errors" "fmt" "golang.org/x/xerrors" ) -// maxListElements restricts the amount of RLP list elements we'll read. -// The ETH API only ever reads EIP-1559 transactions, which are bounded by -// 12 elements exactly, so we play it safe and set exactly that limit here. -const maxListElements = 12 +const ( + // maxListElements limits the number of elements decoded per RLP list. + // Of the transaction formats we decode, EIP-1559 has the most fields + // at 12 (legacy has 9). This is set to match that upper bound. + maxListElements = 12 + + // maxListDepth limits how deeply RLP lists may be nested. Input length + // alone does not bound recursion depth, a sequence of 0xc1 bytes + // creates one stack frame per byte, so an explicit limit is required. + // Ethereum transactions nest at most 3 levels deep; 32 is generous. + maxListDepth = 32 + + // maxInputLen is the largest RLP blob we will attempt to decode. + // Contract-deploy transactions on Filecoin can carry up to 1 MiB of + // init-code; 2 MiB gives comfortable headroom after RLP framing. + maxInputLen = 2 << 20 // 2 MiB +) + +var ( + errRLPEmptyInput = errors.New("invalid rlp data: data is empty") + errRLPNonCanonicalList = errors.New("invalid rlp data: non-canonical list length encoding") + errRLPNonCanonicalString = errors.New("invalid rlp data: non-canonical string length encoding") + errRLPNonCanonicalByte = errors.New("invalid rlp data: non-canonical single byte encoding") + errRLPNonCanonicalLeading = errors.New("invalid rlp data: non-canonical length encoding with leading zeros") + errRLPListBounds = errors.New("invalid rlp data: out of bound while parsing list") + errRLPStringBounds = errors.New("invalid rlp data: out of bound while parsing string") + errRLPLengthBounds = errors.New("invalid rlp data: out of bound while parsing length") + errRLPIncorrectListLen = errors.New("invalid rlp data: incorrect list length") + errRLPEncodeZeroLength = errors.New("cannot encode length: length should be larger than 0") + errRLPEncodeInvalidType = errors.New("input data should either be a list or a byte array") +) -func EncodeRLP(val interface{}) ([]byte, error) { +func EncodeRLP(val any) ([]byte, error) { return encodeRLP(val) } -func encodeRLPListItems(list []interface{}) (result []byte, err error) { +func encodeRLPListItems(list []any) (result []byte, err error) { res := []byte{} for _, elem := range list { encoded, err := encodeRLP(elem) @@ -29,30 +56,22 @@ func encodeRLPListItems(list []interface{}) (result []byte, err error) { return res, nil } -func encodeLength(length int) (lenInBytes []byte, err error) { +// encodeLength returns the minimal big-endian representation of length. +func encodeLength(length int) ([]byte, error) { if length == 0 { - return nil, fmt.Errorf("cannot encode length: length should be larger than 0") - } - - buf := new(bytes.Buffer) - err = binary.Write(buf, binary.BigEndian, int64(length)) - if err != nil { - return nil, err + return nil, errRLPEncodeZeroLength } - - firstNonZeroIndex := len(buf.Bytes()) - 1 - for i, b := range buf.Bytes() { + var buf [8]byte + binary.BigEndian.PutUint64(buf[:], uint64(length)) + for i, b := range buf { if b != 0 { - firstNonZeroIndex = i - break + return append([]byte{}, buf[i:]...), nil } } - - res := buf.Bytes()[firstNonZeroIndex:] - return res, nil + return nil, errRLPEncodeZeroLength } -func encodeRLP(val interface{}) ([]byte, error) { +func encodeRLP(val any) ([]byte, error) { switch data := val.(type) { case []byte: if len(data) == 1 && data[0] <= 0x7f { @@ -70,7 +89,7 @@ func encodeRLP(val interface{}) ([]byte, error) { []byte{prefix}, append(lenInBytes, data...)..., ), nil - case []interface{}: + case []any: encodedList, err := encodeRLPListItems(data) if err != nil { return nil, err @@ -92,87 +111,114 @@ func encodeRLP(val interface{}) ([]byte, error) { append(lenInBytes, encodedList...)..., ), nil default: - return nil, fmt.Errorf("input data should either be a list or a byte array") + return nil, errRLPEncodeInvalidType } } -func DecodeRLP(data []byte) (interface{}, error) { - res, consumed, err := decodeRLP(data) +func DecodeRLP(data []byte) (any, error) { + if len(data) == 0 { + return nil, errRLPEmptyInput + } + if len(data) > maxInputLen { + return nil, fmt.Errorf("invalid rlp data: input length %d exceeds limit of %d", len(data), maxInputLen) + } + res, consumed, err := decodeRLP(data, 0) if err != nil { return nil, err } if consumed != len(data) { - return nil, xerrors.Errorf("invalid rlp data: length %d, consumed %d", len(data), consumed) + return nil, fmt.Errorf("invalid rlp data: length %d, consumed %d", len(data), consumed) } return res, nil } -func decodeRLP(data []byte) (res interface{}, consumed int, err error) { +func decodeRLP(data []byte, depth int) (res any, consumed int, err error) { if len(data) == 0 { - return data, 0, xerrors.Errorf("invalid rlp data: data cannot be empty") + return nil, 0, errRLPEmptyInput + } + if depth > maxListDepth { + return nil, 0, fmt.Errorf("invalid rlp data: list nesting depth exceeds limit of %d", maxListDepth) } - if data[0] >= 0xf8 { - listLenInBytes := int(data[0]) - 0xf7 + + b := data[0] + + switch { + case b >= 0xf8: // long list (> 55 bytes content) + listLenInBytes := int(b) - 0xf7 listLen, err := decodeLength(data[1:], listLenInBytes) if err != nil { return nil, 0, err } + if listLen < 56 { + return nil, 0, errRLPNonCanonicalList + } if 1+listLenInBytes+listLen > len(data) { - return nil, 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list") + return nil, 0, errRLPListBounds } - result, err := decodeListElems(data[1+listLenInBytes:], listLen) + result, err := decodeListElems(data[1+listLenInBytes:], listLen, depth+1) return result, 1 + listLenInBytes + listLen, err - } else if data[0] >= 0xc0 { - length := int(data[0]) - 0xc0 - result, err := decodeListElems(data[1:], length) + + case b >= 0xc0: // short list (0-55 bytes content) + length := int(b) - 0xc0 + if 1+length > len(data) { + return nil, 0, errRLPListBounds + } + result, err := decodeListElems(data[1:], length, depth+1) return result, 1 + length, err - } else if data[0] >= 0xb8 { - strLenInBytes := int(data[0]) - 0xb7 + + case b >= 0xb8: // long string (> 55 bytes) + strLenInBytes := int(b) - 0xb7 strLen, err := decodeLength(data[1:], strLenInBytes) if err != nil { return nil, 0, err } + if strLen < 56 { + return nil, 0, errRLPNonCanonicalString + } totalLen := 1 + strLenInBytes + strLen if totalLen > len(data) || totalLen < 0 { - return nil, 0, xerrors.Errorf("invalid rlp data: out of bound while parsing string") + return nil, 0, errRLPStringBounds } return data[1+strLenInBytes : totalLen], totalLen, nil - } else if data[0] >= 0x80 { - length := int(data[0]) - 0x80 + + case b >= 0x80: // short string (0-55 bytes) + length := int(b) - 0x80 if 1+length > len(data) { - return nil, 0, xerrors.Errorf("invalid rlp data: out of bound while parsing string") + return nil, 0, errRLPStringBounds + } + if length == 1 && data[1] < 0x80 { + return nil, 0, errRLPNonCanonicalByte } return data[1 : 1+length], 1 + length, nil + + default: // single byte [0x00, 0x7f] + return []byte{b}, 1, nil } - return []byte{data[0]}, 1, nil } -func decodeLength(data []byte, lenInBytes int) (length int, err error) { +// decodeLength reads a big-endian length from the first lenInBytes of data. +func decodeLength(data []byte, lenInBytes int) (int, error) { if lenInBytes > len(data) || lenInBytes > 8 { - return 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list length") - } - var decodedLength int64 - r := bytes.NewReader(append(make([]byte, 8-lenInBytes), data[:lenInBytes]...)) - if err := binary.Read(r, binary.BigEndian, &decodedLength); err != nil { - return 0, xerrors.Errorf("invalid rlp data: cannot parse string length: %w", err) + return 0, errRLPLengthBounds } - if decodedLength < 0 { - return 0, xerrors.Errorf("invalid rlp data: negative string length") + if lenInBytes > 0 && data[0] == 0 { + return 0, errRLPNonCanonicalLeading } - - totalLength := lenInBytes + int(decodedLength) - if totalLength < 0 || totalLength > len(data) { - return 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list") + var buf [8]byte + copy(buf[8-lenInBytes:], data[:lenInBytes]) + length := binary.BigEndian.Uint64(buf[:]) + if length > uint64(len(data)-lenInBytes) { + return 0, errRLPLengthBounds } - return int(decodedLength), nil + return int(length), nil } -func decodeListElems(data []byte, length int) (res []interface{}, err error) { +func decodeListElems(data []byte, length int, depth int) (res []any, err error) { totalConsumed := 0 - result := []interface{}{} + result := []any{} for i := 0; totalConsumed < length && i < maxListElements; i++ { - elem, consumed, err := decodeRLP(data[totalConsumed:]) + elem, consumed, err := decodeRLP(data[totalConsumed:], depth) if err != nil { return nil, xerrors.Errorf("invalid rlp data: cannot decode list element: %w", err) } @@ -180,7 +226,7 @@ func decodeListElems(data []byte, length int) (res []interface{}, err error) { result = append(result, elem) } if totalConsumed != length { - return nil, xerrors.Errorf("invalid rlp data: incorrect list length") + return nil, errRLPIncorrectListLen } return result, nil } diff --git a/chain/types/ethtypes/rlp_test.go b/chain/types/ethtypes/rlp_test.go index 0c74cf58c0a..7bb9d9b185c 100644 --- a/chain/types/ethtypes/rlp_test.go +++ b/chain/types/ethtypes/rlp_test.go @@ -1,6 +1,7 @@ package ethtypes import ( + "bytes" "encoding/hex" "fmt" "strings" @@ -11,6 +12,14 @@ import ( "github.com/filecoin-project/go-address" ) +func mustDecodeHex(s string) []byte { + d, err := hex.DecodeString(strings.Replace(s, "0x", "", -1)) + if err != nil { + panic(fmt.Errorf("err must be nil: %w", err)) + } + return d +} + func TestEncode(t *testing.T) { testcases := []TestCase{ {[]byte(""), mustDecodeHex("0x80")}, @@ -57,7 +66,7 @@ func TestEncode(t *testing.T) { for _, tc := range testcases { result, err := EncodeRLP(tc.Input) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, tc.Output.([]byte), result) } @@ -76,25 +85,17 @@ func TestDecodeString(t *testing.T) { for _, tc := range testcases { input, err := hex.DecodeString(strings.Replace(tc.Input.(string), "0x", "", -1)) - require.Nil(t, err) + require.NoError(t, err) output, err := hex.DecodeString(strings.Replace(tc.Output.(string), "0x", "", -1)) - require.Nil(t, err) + require.NoError(t, err) result, err := DecodeRLP(input) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, output, result.([]byte)) } } -func mustDecodeHex(s string) []byte { - d, err := hex.DecodeString(strings.Replace(s, "0x", "", -1)) - if err != nil { - panic(fmt.Errorf("err must be nil: %w", err)) - } - return d -} - func TestDecodeList(t *testing.T) { testcases := []TestCase{ {"0xc0", []interface{}{}}, @@ -128,12 +129,11 @@ func TestDecodeList(t *testing.T) { for _, tc := range testcases { input, err := hex.DecodeString(strings.Replace(tc.Input.(string), "0x", "", -1)) - require.Nil(t, err) + require.NoError(t, err) result, err := DecodeRLP(input) - require.Nil(t, err) + require.NoError(t, err) - fmt.Println(result) r := result.([]interface{}) require.Equal(t, len(tc.Output.([]interface{})), len(r)) @@ -167,10 +167,10 @@ func TestDecodeEncodeTx(t *testing.T) { for _, tc := range testcases { decoded, err := DecodeRLP(tc) - require.Nil(t, err) + require.NoError(t, err) encoded, err := EncodeRLP(decoded) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, tc, encoded) } } @@ -190,6 +190,198 @@ func TestDecodeError(t *testing.T) { } } +// TestDecodeLimits verifies the decoder's input validation bounds: empty input, +// max input size, list nesting depth, and per-list element count. +func TestDecodeLimits(t *testing.T) { + t.Run("empty input", func(t *testing.T) { + _, err := DecodeRLP([]byte{}) + require.ErrorContains(t, err, "data is empty") + }) + + t.Run("input too large", func(t *testing.T) { + // Just over the limit; content doesn't matter, the check is pre-parse. + data := make([]byte, maxInputLen+1) + data[0] = 0x80 + _, err := DecodeRLP(data) + require.ErrorContains(t, err, "exceeds limit") + }) + + t.Run("nesting exceeds limit", func(t *testing.T) { + payload := bytes.Repeat([]byte{0xc1}, maxListDepth+2) + _, err := DecodeRLP(payload) + require.ErrorContains(t, err, "nesting depth exceeds limit") + }) + + t.Run("nesting at limit with leaf value", func(t *testing.T) { + // Build a validly-encoded nested structure: maxListDepth layers of + // short lists wrapping a leaf byte. Each prefix encodes the correct + // content length: + // innermost: 0xc1 0x42 (list with 1-byte content) + // next out: 0xc2 0xc1 0x42 (list with 2-byte content) + // next out: 0xc3 0xc2 0xc1 0x42 (list with 3-byte content) + depth := maxListDepth + data := make([]byte, depth+1) + for i := 0; i < depth; i++ { + data[i] = byte(0xc0 + depth - i) + } + data[depth] = 0x42 + result, err := DecodeRLP(data) + require.NoError(t, err) + + // Unwrap the nested lists down to the leaf. + var cur interface{} = result + for i := 0; i < depth; i++ { + lst, ok := cur.([]interface{}) + require.True(t, ok, "expected list at depth %d", i) + require.Len(t, lst, 1) + cur = lst[0] + } + require.Equal(t, []byte{0x42}, cur) + }) + + t.Run("list element count exceeds limit", func(t *testing.T) { + // Encode a list with maxListElements+1 single-byte elements. + elems := make([]byte, maxListElements+1) + for i := range elems { + elems[i] = byte(i) + } + // Short list prefix: 0xc0 + content length. + data := append([]byte{byte(0xc0 + len(elems))}, elems...) + _, err := DecodeRLP(data) + require.ErrorContains(t, err, "incorrect list length") + }) +} + +// TestDecodeCanonical verifies that the decoder rejects non-canonical RLP +// encodings. Test vectors are derived from go-ethereum's rlp test suite +// (ErrCanonSize cases in decode_test.go and raw_test.go). +func TestDecodeCanonical(t *testing.T) { + // Single byte values [0x00..0x7f] must not use a string prefix. + t.Run("single byte with unnecessary prefix", func(t *testing.T) { + for _, tc := range []string{ + "8100", // 0x00 should be encoded as 0x00 + "8101", // 0x01 should be encoded as 0x01 + "8105", // 0x05 should be encoded as 0x05 + "817f", // 0x7f should be encoded as 0x7f + } { + _, err := DecodeRLP(mustDecodeHex("0x" + tc)) + require.ErrorContains(t, err, "non-canonical single byte", "input: %s", tc) + } + // 0x80 is the first value that legitimately needs the prefix. + _, err := DecodeRLP(mustDecodeHex("0x8180")) + require.NoError(t, err) + }) + + // Long string prefix (0xb8+) must not be used for lengths <= 55. + t.Run("long string prefix for short content", func(t *testing.T) { + for _, tc := range []string{ + "b800", // 0-byte string: should use 0x80 + "b80100", // 1-byte string: should use 0x81 + "b83700" + strings.Repeat("aa", 54), // 55-byte string: should use 0xb7 + } { + _, err := DecodeRLP(mustDecodeHex("0x" + tc)) + require.ErrorContains(t, err, "non-canonical", "input prefix: %s", tc[:4]) + } + }) + + // Long list prefix (0xf8+) must not be used for lengths <= 55. + t.Run("long list prefix for short content", func(t *testing.T) { + for _, tc := range []string{ + "f800", // 0-byte list: should use 0xc0 + "f80100", // 1-byte list: should use 0xc1 + } { + _, err := DecodeRLP(mustDecodeHex("0x" + tc)) + require.ErrorContains(t, err, "non-canonical", "input prefix: %s", tc[:4]) + } + }) + + // Length encoding must not have leading zero bytes. + t.Run("leading zeros in length", func(t *testing.T) { + for _, tc := range []string{ + "b90055" + strings.Repeat("aa", 0x55), // 2-byte len but 0x0055 has leading zero + "ba0002ffff", // 3-byte len but 0x0002ff has leading zero + } { + _, err := DecodeRLP(mustDecodeHex("0x" + tc)) + require.ErrorContains(t, err, "non-canonical", "input: %s...", tc[:6]) + } + }) +} + +// TestDecodeLengthMismatch checks that the decoder rejects payloads where the +// declared length does not match the available data (truncated payloads or +// extra trailing bytes). +func TestDecodeLengthMismatch(t *testing.T) { + testcases := []struct { + name string + input string + }{ + {"short string truncated", "8201"}, // claims 2 bytes, only 1 + {"long string truncated", "b838" + strings.Repeat("ff", 10)}, // claims 56, only 10 + {"short list trailing data", "c3000102ff"}, // list claims 3 bytes content, but 4 follow (extra byte) + {"long list truncated", "f838" + strings.Repeat("00", 10)}, // claims 56 bytes content, only 10 + {"string with trailing data", "850505050505ff"}, // claims 5 bytes, has 5 + trailing + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + _, err := DecodeRLP(mustDecodeHex("0x" + tc.input)) + require.Error(t, err, "input: %s", tc.input) + }) + } +} + +// TestDecodeEncodeRoundtrip verifies encode/decode symmetry across a range +// of value types including edge cases at encoding boundaries. +func TestDecodeEncodeRoundtrip(t *testing.T) { + testcases := []struct { + name string + val interface{} + }{ + {"empty string", []byte{}}, + {"single byte 0x00", []byte{0x00}}, + {"single byte 0x7f", []byte{0x7f}}, + {"single byte 0x80", []byte{0x80}}, + {"55 byte string", bytes.Repeat([]byte{0xab}, 55)}, + {"56 byte string", bytes.Repeat([]byte{0xab}, 56)}, + {"256 byte string", bytes.Repeat([]byte{0xab}, 256)}, + {"empty list", []interface{}{}}, + {"list with empty string", []interface{}{[]byte{}}}, + {"nested empty lists", []interface{}{[]interface{}{}}}, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + encoded, err := EncodeRLP(tc.val) + require.NoError(t, err) + + decoded, err := DecodeRLP(encoded) + require.NoError(t, err) + + reencoded, err := EncodeRLP(decoded) + require.NoError(t, err) + require.Equal(t, encoded, reencoded) + }) + } +} + +// TestDecodeEncodeTxRoundtrip is the original transaction roundtrip test, +// exercising real transaction payloads including contract-deploy sizes. +func TestDecodeEncodeTxRoundtrip(t *testing.T) { + testcases := [][]byte{ + mustDecodeHex("0xdc82013a0185012a05f2008504a817c8008080872386f26fc1000000c0"), + mustDecodeHex("0xf85f82013a0185012a05f2008504a817c8008080872386f26fc1000000c001a027fa36fb9623e4d71fcdd7f7dce71eb814c9560dcf3908c1719386e2efd122fba05fb4e4227174eeb0ba84747a4fb883c8d4e0fdb129c4b1f42e90282c41480234"), + mustDecodeHex("0xf9061c82013a0185012a05f2008504a817c8008080872386f26fc10000b905bb608060405234801561001057600080fd5b506127106000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610556806100656000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a1114610076578063f8b2cb4f146100a6575b600080fd5b610060600480360381019061005b919061030a565b6100d6565b60405161006d9190610350565b60405180910390f35b610090600480360381019061008b9190610397565b6100f4565b60405161009d91906103f2565b60405180910390f35b6100c060048036038101906100bb919061030a565b61025f565b6040516100cd9190610350565b60405180910390f35b600060026100e38361025f565b6100ed919061043c565b9050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101455760009050610259565b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101939190610496565b92505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101e891906104ca565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161024c9190610350565b60405180910390a3600190505b92915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d7826102ac565b9050919050565b6102e7816102cc565b81146102f257600080fd5b50565b600081359050610304816102de565b92915050565b6000602082840312156103205761031f6102a7565b5b600061032e848285016102f5565b91505092915050565b6000819050919050565b61034a81610337565b82525050565b60006020820190506103656000830184610341565b92915050565b61037481610337565b811461037f57600080fd5b50565b6000813590506103918161036b565b92915050565b600080604083850312156103ae576103ad6102a7565b5b60006103bc858286016102f5565b92505060206103cd85828601610382565b9150509250929050565b60008115159050919050565b6103ec816103d7565b82525050565b600060208201905061040760008301846103e3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061044782610337565b915061045283610337565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561048b5761048a61040d565b5b828202905092915050565b60006104a182610337565b91506104ac83610337565b9250828210156104bf576104be61040d565b5b828203905092915050565b60006104d582610337565b91506104e083610337565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156105155761051461040d565b5b82820190509291505056fea26469706673582212208e5b4b874c839967f88008ed2fa42d6c2d9c9b0ae05d1d2c61faa7d229c134e664736f6c634300080d0033c080a0c4e9477f57c6848b2f1ea73a14809c1f44529d20763c947f3ac8ffd3d1629d93a011485a215457579bb13ac7b53bb9d6804763ae6fe5ce8ddd41642cea55c9a09a"), + mustDecodeHex("0xf9063082013a0185012a05f2008504a817c8008094025b594a4f1c4888cafcfaf2bb24ed95507749e0872386f26fc10000b905bb608060405234801561001057600080fd5b506127106000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610556806100656000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a1114610076578063f8b2cb4f146100a6575b600080fd5b610060600480360381019061005b919061030a565b6100d6565b60405161006d9190610350565b60405180910390f35b610090600480360381019061008b9190610397565b6100f4565b60405161009d91906103f2565b60405180910390f35b6100c060048036038101906100bb919061030a565b61025f565b6040516100cd9190610350565b60405180910390f35b600060026100e38361025f565b6100ed919061043c565b9050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101455760009050610259565b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101939190610496565b92505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101e891906104ca565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161024c9190610350565b60405180910390a3600190505b92915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d7826102ac565b9050919050565b6102e7816102cc565b81146102f257600080fd5b50565b600081359050610304816102de565b92915050565b6000602082840312156103205761031f6102a7565b5b600061032e848285016102f5565b91505092915050565b6000819050919050565b61034a81610337565b82525050565b60006020820190506103656000830184610341565b92915050565b61037481610337565b811461037f57600080fd5b50565b6000813590506103918161036b565b92915050565b600080604083850312156103ae576103ad6102a7565b5b60006103bc858286016102f5565b92505060206103cd85828601610382565b9150509250929050565b60008115159050919050565b6103ec816103d7565b82525050565b600060208201905061040760008301846103e3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061044782610337565b915061045283610337565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561048b5761048a61040d565b5b828202905092915050565b60006104a182610337565b91506104ac83610337565b9250828210156104bf576104be61040d565b5b828203905092915050565b60006104d582610337565b91506104e083610337565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156105155761051461040d565b5b82820190509291505056fea26469706673582212208e5b4b874c839967f88008ed2fa42d6c2d9c9b0ae05d1d2c61faa7d229c134e664736f6c634300080d0033c080a0fe38720928596f9e9dfbf891d00311638efce3713f03cdd67b212ecbbcf18f29a05993e656c0b35b8a580da6aff7c89b3d3e8b1c6f83a7ce09473c0699a8500b9c"), + } + + for _, tc := range testcases { + decoded, err := DecodeRLP(tc) + require.NoError(t, err) + + encoded, err := EncodeRLP(decoded) + require.NoError(t, err) + require.Equal(t, tc, encoded) + } +} + func TestDecode1(t *testing.T) { b := mustDecodeHex("0x02f8758401df5e7680832c8411832c8411830767f89452963ef50e27e06d72d59fcb4f3c2a687be3cfef880de0b6b3a764000080c080a094b11866f453ad85a980e0e8a2fc98cbaeb4409618c7734a7e12ae2f66fd405da042dbfb1b37af102023830ceeee0e703ffba0b8b3afeb8fe59f405eca9ed61072") decoded, err := parseEip1559Tx(b) diff --git a/go.mod b/go.mod index e1fea56762c..89e18d6c777 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/filecoin-project/go-jsonrpc v0.10.1 github.com/filecoin-project/go-keccak v0.1.0 github.com/filecoin-project/go-padreader v0.0.1 - github.com/filecoin-project/go-paramfetch v0.0.4 + github.com/filecoin-project/go-paramfetch v0.0.5 github.com/filecoin-project/go-state-types v0.18.0-dev // dependency-check-ignore: unknown github.com/filecoin-project/go-statemachine v1.0.3 github.com/filecoin-project/go-statestore v0.2.0 @@ -318,7 +318,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect google.golang.org/grpc v1.78.0 // indirect google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect; dependency-check-ignore: required by github.com/elastic/go-sysinfo diff --git a/go.sum b/go.sum index 32f72f26eb1..e77bbe432c0 100644 --- a/go.sum +++ b/go.sum @@ -241,7 +241,6 @@ github.com/etclabscore/go-jsonschema-walk v0.0.6/go.mod h1:VdfDY72AFAiUhy0ZXEaWS github.com/etclabscore/go-openrpc-reflect v0.0.37 h1:IH0e7JqIvR9OhbbFWi/BHIkXrqbR3Zyia3RJ733eT6c= github.com/etclabscore/go-openrpc-reflect v0.0.37/go.mod h1:0404Ky3igAasAOpyj1eESjstTyneBAIk5PgJFbK4s5E= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -293,8 +292,8 @@ github.com/filecoin-project/go-keccak v0.1.0 h1:SWoaAVbqKgB9iXBceIjmgMskr8DlJTAJ github.com/filecoin-project/go-keccak v0.1.0/go.mod h1:X3vAWrEOJSO5GnJfzRFZzv8QC/2IacwECuIj11cnE4Y= github.com/filecoin-project/go-padreader v0.0.1 h1:8h2tVy5HpoNbr2gBRr+WD6zV6VD6XHig+ynSGJg8ZOs= github.com/filecoin-project/go-padreader v0.0.1/go.mod h1:VYVPJqwpsfmtoHnAmPx6MUwmrK6HIcDqZJiuZhtmfLQ= -github.com/filecoin-project/go-paramfetch v0.0.4 h1:H+Me8EL8T5+79z/KHYQQcT8NVOzYVqXIi7nhb48tdm8= -github.com/filecoin-project/go-paramfetch v0.0.4/go.mod h1:1FH85P8U+DUEmWk1Jkw3Bw7FrwTVUNHk/95PSPG+dts= +github.com/filecoin-project/go-paramfetch v0.0.5 h1:swArYYMekRBkye7GEqL1nWvJm6yY51hyQyFdB7IKCKg= +github.com/filecoin-project/go-paramfetch v0.0.5/go.mod h1:Dllgpm22B33tzgvrtwPhmz5HE89sXDDnpTwTmpZ8u+I= github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= @@ -651,7 +650,6 @@ github.com/ipfs/go-ds-measure v0.2.2 h1:4kwvBGbbSXNYe4ANlg7qTIYoZU6mNlqzQHdVqICk github.com/ipfs/go-ds-measure v0.2.2/go.mod h1:b/87ak0jMgH9Ylt7oH0+XGy4P8jHx9KG09Qz+pOeTIs= github.com/ipfs/go-dsqueue v0.2.0 h1:MBi9w3oSiX98Xc+Y7NuJ9G8MI6mAT4IGdO9dHEMCZzU= github.com/ipfs/go-dsqueue v0.2.0/go.mod h1:8FfNQC4DMF/KkzBXRNB9Rb3MKDW0Sh98HMtXYl1mLQE= -github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28L7zESmM= github.com/ipfs/go-fs-lock v0.1.1 h1:TecsP/Uc7WqYYatasreZQiP9EGRy4ZnKoG4yXxR33nw= github.com/ipfs/go-fs-lock v0.1.1/go.mod h1:2goSXMCw7QfscHmSe09oXiR34DQeUdm+ei+dhonqly0= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= @@ -916,7 +914,6 @@ github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -924,7 +921,6 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= @@ -1435,7 +1431,6 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1601,7 +1596,6 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20180202135801-37707fdb30a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1925,8 +1919,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= -gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=