mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 18:30:45 +00:00
refactor(core/types): Body backwards-compatibility out of package types_test (#131)
## Why this should be merged Simplify testing in #130. ## How this works Backwards-compatibility tests were originally created in `package types_test` because the first one uses `ethtest` and would have caused a circular dependency. None of the later tests have this issue so they were moved into `package types`. The `cmpeth` test utility isn't currently needed anywhere else so its functionality is collapsed inside this new file. ## How this was tested N/A as simply moving existing tests to different files.
This commit is contained in:
parent
67f879ac18
commit
80fbed641e
3 changed files with 134 additions and 153 deletions
|
|
@ -14,7 +14,7 @@
|
||||||
// along with the go-ethereum library. If not, see
|
// along with the go-ethereum library. If not, see
|
||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package types_test
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
@ -26,91 +26,9 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/ava-labs/libevm/common"
|
"github.com/ava-labs/libevm/common"
|
||||||
. "github.com/ava-labs/libevm/core/types"
|
|
||||||
"github.com/ava-labs/libevm/libevm/cmpeth"
|
|
||||||
"github.com/ava-labs/libevm/libevm/ethtest"
|
|
||||||
"github.com/ava-labs/libevm/rlp"
|
"github.com/ava-labs/libevm/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHeaderRLPBackwardsCompatibility(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
register func()
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "no registered extras",
|
|
||||||
register: func() {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no-op header hooks",
|
|
||||||
register: func() {
|
|
||||||
RegisterExtras[NOOPHeaderHooks, *NOOPHeaderHooks, struct{}]()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
TestOnlyClearRegisteredExtras()
|
|
||||||
defer TestOnlyClearRegisteredExtras()
|
|
||||||
tt.register()
|
|
||||||
testHeaderRLPBackwardsCompatibility(t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//nolint:thelper
|
|
||||||
func testHeaderRLPBackwardsCompatibility(t *testing.T) {
|
|
||||||
// This is a deliberate change-detector test that locks in backwards
|
|
||||||
// compatibility of RLP encoding.
|
|
||||||
rng := ethtest.NewPseudoRand(42)
|
|
||||||
|
|
||||||
const numExtraBytes = 16
|
|
||||||
hdr := &Header{
|
|
||||||
ParentHash: rng.Hash(),
|
|
||||||
UncleHash: rng.Hash(),
|
|
||||||
Coinbase: rng.Address(),
|
|
||||||
Root: rng.Hash(),
|
|
||||||
TxHash: rng.Hash(),
|
|
||||||
ReceiptHash: rng.Hash(),
|
|
||||||
Bloom: rng.Bloom(),
|
|
||||||
Difficulty: rng.Uint256().ToBig(),
|
|
||||||
Number: rng.BigUint64(),
|
|
||||||
GasLimit: rng.Uint64(),
|
|
||||||
GasUsed: rng.Uint64(),
|
|
||||||
Time: rng.Uint64(),
|
|
||||||
Extra: rng.Bytes(numExtraBytes),
|
|
||||||
MixDigest: rng.Hash(),
|
|
||||||
Nonce: rng.BlockNonce(),
|
|
||||||
|
|
||||||
BaseFee: rng.BigUint64(),
|
|
||||||
WithdrawalsHash: rng.HashPtr(),
|
|
||||||
BlobGasUsed: rng.Uint64Ptr(),
|
|
||||||
ExcessBlobGas: rng.Uint64Ptr(),
|
|
||||||
ParentBeaconRoot: rng.HashPtr(),
|
|
||||||
}
|
|
||||||
t.Logf("%T:\n%+v", hdr, hdr)
|
|
||||||
|
|
||||||
// WARNING: changing this hex might break backwards compatibility of RLP
|
|
||||||
// encoding (i.e. block hashes might change)!
|
|
||||||
const wantHex = `f9029aa01a571e7e4d774caf46053201cfe0001b3c355ffcc93f510e671e8809741f0eeda0756095410506ec72a2c287fe83ebf68efb0be177e61acec1c985277e90e52087941bfc3bc193012ba58912c01fb35a3454831a8971a00bc9f064144eb5965c5e5d1020f9f90392e7e06ded9225966abc7c754b410e61a0d942eab201424f4320ec1e1ffa9390baf941629b9349977b5d48e0502dbb9386a035d9d550a9c113f78689b4c161c4605609bb57b83061914c42ad244daa7fc38eb901004b31d39ae246d689f23176d679a62ff328f530407cbafd0146f45b2ed635282e2812f2705bfffe52576a6fb31df817f29efac71fa56b8e133334079f8e2a8fd2055451571021506f27190adb52a1313f6d28c77d66ae1aa3d3d6757a762476f4c8a2b7b2a37079a4b6a15d1bc44161190c82d5e1c8b55e05c7354f1e5f6512924c941fb3d93667dc3a8c304a3c164e6525dfc99b5f474110c5059485732153e20300c3482832d07b65f97958360da414cb438ce252aec6c2718d155798390a6c6782181d1bac1dd64cd956332b008412ddc735f2994e297c8a088c6bb4c637542295ba3cbc3cd399c8127076f4d834d74d5b11a36b6d02e2fe3a583216aa4ccea0f052df9a96e7a454256bebabdfc38c429079f25913e0f1d7416b2f056c4a115f88b85f0e9fd6d25717881f03d9985060087c88a2c54269dfd07ca388eb8f974b42a412da90c757012bf5479896165caf573cf82fb3a0aa10f6ebf6b62bef8ed36b8ea3d4b1ddb80c99afafa37cb8f3393eb6d802f5bc886c8cd6bcd168a7e0886d5b1345d948b818a0061a7182ff228a4e66bade4717e6f4d318ac98fca12a053af6f98805a764fb5d8890ed9cab2c5229908891c7e2f71857c77ca0523cb6f654ef3fc7294c7768cddd9ccf4bcda3066d382675f37dd1a18507b5fb`
|
|
||||||
wantRLP, err := hex.DecodeString(wantHex)
|
|
||||||
require.NoError(t, err, "hex.DecodeString()")
|
|
||||||
|
|
||||||
t.Run("Encode", func(t *testing.T) {
|
|
||||||
got, err := rlp.EncodeToBytes(hdr)
|
|
||||||
require.NoErrorf(t, err, "rlp.EncodeToBytes(%T)", hdr)
|
|
||||||
assert.Equalf(t, wantRLP, got, "rlp.EncodeToBytes(%T)", hdr)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Decode", func(t *testing.T) {
|
|
||||||
got := new(Header)
|
|
||||||
err := rlp.DecodeBytes(wantRLP, got)
|
|
||||||
require.NoErrorf(t, err, "rlp.DecodeBytes(..., %T)", hdr)
|
|
||||||
assert.Equal(t, hdr, got)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBodyRLPBackwardsCompatibility(t *testing.T) {
|
func TestBodyRLPBackwardsCompatibility(t *testing.T) {
|
||||||
newTx := func(nonce uint64) *Transaction { return NewTx(&LegacyTx{Nonce: nonce}) }
|
newTx := func(nonce uint64) *Transaction { return NewTx(&LegacyTx{Nonce: nonce}) }
|
||||||
newHdr := func(hashLow byte) *Header { return &Header{ParentHash: common.Hash{hashLow}} }
|
newHdr := func(hashLow byte) *Header { return &Header{ParentHash: common.Hash{hashLow}} }
|
||||||
|
|
@ -176,8 +94,8 @@ func TestBodyRLPBackwardsCompatibility(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := cmp.Options{
|
opts := cmp.Options{
|
||||||
cmpeth.CompareHeadersByHash(),
|
cmp.Comparer((*Header).equalHash),
|
||||||
cmpeth.CompareTransactionsByBinary(t),
|
cmp.Comparer((*Transaction).equalHash),
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(body, got, opts); diff != "" {
|
if diff := cmp.Diff(body, got, opts); diff != "" {
|
||||||
t.Errorf("rlp.DecodeBytes(rlp.EncodeToBytes(%#v)) diff (-want +got):\n%s", body, diff)
|
t.Errorf("rlp.DecodeBytes(rlp.EncodeToBytes(%#v)) diff (-want +got):\n%s", body, diff)
|
||||||
|
|
@ -292,8 +210,8 @@ func TestBodyRLPCChainCompat(t *testing.T) {
|
||||||
assert.Equal(t, tt.extra, &extra, "rlp.DecodeBytes(%#x, [%T as registered extra in %T carrier])", wantRLP, &extra, got)
|
assert.Equal(t, tt.extra, &extra, "rlp.DecodeBytes(%#x, [%T as registered extra in %T carrier])", wantRLP, &extra, got)
|
||||||
|
|
||||||
opts := cmp.Options{
|
opts := cmp.Options{
|
||||||
cmpeth.CompareHeadersByHash(),
|
cmp.Comparer((*Header).equalHash),
|
||||||
cmpeth.CompareTransactionsByBinary(t),
|
cmp.Comparer((*Transaction).equalHash),
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(body, got, opts); diff != "" {
|
if diff := cmp.Diff(body, got, opts); diff != "" {
|
||||||
t.Errorf("rlp.DecodeBytes(%#x, [%T while carrying registered %T extra payload]) diff (-want +got):\n%s", wantRLP, got, &extra, diff)
|
t.Errorf("rlp.DecodeBytes(%#x, [%T while carrying registered %T extra payload]) diff (-want +got):\n%s", wantRLP, got, &extra, diff)
|
||||||
|
|
@ -302,3 +220,24 @@ func TestBodyRLPCChainCompat(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// equalHash reports whether `a` and `b` have equal hashes. It allows for nil
|
||||||
|
// arguments, returning `true` if both are nil, `false` if only one is nil,
|
||||||
|
// otherwise `a.Hash() == b.Hash()`.
|
||||||
|
func equalHash[
|
||||||
|
T any, P interface {
|
||||||
|
Hash() common.Hash
|
||||||
|
*T
|
||||||
|
},
|
||||||
|
](a, b P) bool {
|
||||||
|
if a == nil && b == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if a == nil || b == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return a.Hash() == b.Hash()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Header) equalHash(hh *Header) bool { return equalHash(h, hh) }
|
||||||
|
func (tx *Transaction) equalHash(u *Transaction) bool { return equalHash(tx, u) }
|
||||||
108
core/types/backwards_compat_diffpkg.libevm_test.go
Normal file
108
core/types/backwards_compat_diffpkg.libevm_test.go
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
// Copyright 2024-2025 the libevm authors.
|
||||||
|
//
|
||||||
|
// The libevm additions to go-ethereum are free software: you can redistribute
|
||||||
|
// them and/or modify them 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 libevm additions are distributed in the hope that they 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 types_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
. "github.com/ava-labs/libevm/core/types"
|
||||||
|
"github.com/ava-labs/libevm/libevm/ethtest"
|
||||||
|
"github.com/ava-labs/libevm/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHeaderRLPBackwardsCompatibility(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
register func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no registered extras",
|
||||||
|
register: func() {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no-op header hooks",
|
||||||
|
register: func() {
|
||||||
|
RegisterExtras[NOOPHeaderHooks, *NOOPHeaderHooks, struct{}]()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
TestOnlyClearRegisteredExtras()
|
||||||
|
defer TestOnlyClearRegisteredExtras()
|
||||||
|
tt.register()
|
||||||
|
testHeaderRLPBackwardsCompatibility(t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:thelper
|
||||||
|
func testHeaderRLPBackwardsCompatibility(t *testing.T) {
|
||||||
|
// This is a deliberate change-detector test that locks in backwards
|
||||||
|
// compatibility of RLP encoding.
|
||||||
|
rng := ethtest.NewPseudoRand(42)
|
||||||
|
|
||||||
|
const numExtraBytes = 16
|
||||||
|
hdr := &Header{
|
||||||
|
ParentHash: rng.Hash(),
|
||||||
|
UncleHash: rng.Hash(),
|
||||||
|
Coinbase: rng.Address(),
|
||||||
|
Root: rng.Hash(),
|
||||||
|
TxHash: rng.Hash(),
|
||||||
|
ReceiptHash: rng.Hash(),
|
||||||
|
Bloom: rng.Bloom(),
|
||||||
|
Difficulty: rng.Uint256().ToBig(),
|
||||||
|
Number: rng.BigUint64(),
|
||||||
|
GasLimit: rng.Uint64(),
|
||||||
|
GasUsed: rng.Uint64(),
|
||||||
|
Time: rng.Uint64(),
|
||||||
|
Extra: rng.Bytes(numExtraBytes),
|
||||||
|
MixDigest: rng.Hash(),
|
||||||
|
Nonce: rng.BlockNonce(),
|
||||||
|
|
||||||
|
BaseFee: rng.BigUint64(),
|
||||||
|
WithdrawalsHash: rng.HashPtr(),
|
||||||
|
BlobGasUsed: rng.Uint64Ptr(),
|
||||||
|
ExcessBlobGas: rng.Uint64Ptr(),
|
||||||
|
ParentBeaconRoot: rng.HashPtr(),
|
||||||
|
}
|
||||||
|
t.Logf("%T:\n%+v", hdr, hdr)
|
||||||
|
|
||||||
|
// WARNING: changing this hex might break backwards compatibility of RLP
|
||||||
|
// encoding (i.e. block hashes might change)!
|
||||||
|
const wantHex = `f9029aa01a571e7e4d774caf46053201cfe0001b3c355ffcc93f510e671e8809741f0eeda0756095410506ec72a2c287fe83ebf68efb0be177e61acec1c985277e90e52087941bfc3bc193012ba58912c01fb35a3454831a8971a00bc9f064144eb5965c5e5d1020f9f90392e7e06ded9225966abc7c754b410e61a0d942eab201424f4320ec1e1ffa9390baf941629b9349977b5d48e0502dbb9386a035d9d550a9c113f78689b4c161c4605609bb57b83061914c42ad244daa7fc38eb901004b31d39ae246d689f23176d679a62ff328f530407cbafd0146f45b2ed635282e2812f2705bfffe52576a6fb31df817f29efac71fa56b8e133334079f8e2a8fd2055451571021506f27190adb52a1313f6d28c77d66ae1aa3d3d6757a762476f4c8a2b7b2a37079a4b6a15d1bc44161190c82d5e1c8b55e05c7354f1e5f6512924c941fb3d93667dc3a8c304a3c164e6525dfc99b5f474110c5059485732153e20300c3482832d07b65f97958360da414cb438ce252aec6c2718d155798390a6c6782181d1bac1dd64cd956332b008412ddc735f2994e297c8a088c6bb4c637542295ba3cbc3cd399c8127076f4d834d74d5b11a36b6d02e2fe3a583216aa4ccea0f052df9a96e7a454256bebabdfc38c429079f25913e0f1d7416b2f056c4a115f88b85f0e9fd6d25717881f03d9985060087c88a2c54269dfd07ca388eb8f974b42a412da90c757012bf5479896165caf573cf82fb3a0aa10f6ebf6b62bef8ed36b8ea3d4b1ddb80c99afafa37cb8f3393eb6d802f5bc886c8cd6bcd168a7e0886d5b1345d948b818a0061a7182ff228a4e66bade4717e6f4d318ac98fca12a053af6f98805a764fb5d8890ed9cab2c5229908891c7e2f71857c77ca0523cb6f654ef3fc7294c7768cddd9ccf4bcda3066d382675f37dd1a18507b5fb`
|
||||||
|
wantRLP, err := hex.DecodeString(wantHex)
|
||||||
|
require.NoError(t, err, "hex.DecodeString()")
|
||||||
|
|
||||||
|
t.Run("Encode", func(t *testing.T) {
|
||||||
|
got, err := rlp.EncodeToBytes(hdr)
|
||||||
|
require.NoErrorf(t, err, "rlp.EncodeToBytes(%T)", hdr)
|
||||||
|
assert.Equalf(t, wantRLP, got, "rlp.EncodeToBytes(%T)", hdr)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Decode", func(t *testing.T) {
|
||||||
|
got := new(Header)
|
||||||
|
err := rlp.DecodeBytes(wantRLP, got)
|
||||||
|
require.NoErrorf(t, err, "rlp.DecodeBytes(..., %T)", hdr)
|
||||||
|
assert.Equal(t, hdr, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
// Copyright 2025 the libevm authors.
|
|
||||||
//
|
|
||||||
// The libevm additions to go-ethereum are free software: you can redistribute
|
|
||||||
// them and/or modify them 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 libevm additions are distributed in the hope that they 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 cmpeth provides ETH-specific options for the cmp package.
|
|
||||||
package cmpeth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
|
|
||||||
"github.com/ava-labs/libevm/core/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CompareHeadersByHash returns an option to compare Headers based on
|
|
||||||
// [types.Header.Hash] equality.
|
|
||||||
func CompareHeadersByHash() cmp.Option {
|
|
||||||
return cmp.Comparer(func(a, b *types.Header) bool {
|
|
||||||
return a.Hash() == b.Hash()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompareTransactionsByBinary returns an option to compare Transactions based
|
|
||||||
// on [types.Transaction.MarshalBinary] equality. Two nil pointers are
|
|
||||||
// considered equal.
|
|
||||||
//
|
|
||||||
// If MarshalBinary() returns an error, it will be reported with
|
|
||||||
// [testing.TB.Fatal].
|
|
||||||
func CompareTransactionsByBinary(tb testing.TB) cmp.Option {
|
|
||||||
tb.Helper()
|
|
||||||
return cmp.Comparer(func(a, b *types.Transaction) bool {
|
|
||||||
tb.Helper()
|
|
||||||
|
|
||||||
if a == nil && b == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if a == nil || b == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes.Equal(marshalTxBinary(tb, a), marshalTxBinary(tb, b))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalTxBinary(tb testing.TB, tx *types.Transaction) []byte {
|
|
||||||
tb.Helper()
|
|
||||||
buf, err := tx.MarshalBinary()
|
|
||||||
if err != nil {
|
|
||||||
tb.Fatalf("%T.MarshalBinary() error %v", tx, err)
|
|
||||||
}
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue