Skip to content

Commit 9925590

Browse files
committed
test: pseudo.Type.EncodeRLP()
1 parent 780a592 commit 9925590

File tree

3 files changed

+99
-3
lines changed

3 files changed

+99
-3
lines changed

libevm/ethtest/rand.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
// You should have received a copy of the GNU Lesser General Public License
1414
// along with the go-ethereum library. If not, see
1515
// <http://www.gnu.org/licenses/>.
16+
1617
package ethtest
1718

1819
import (
1920
"math/big"
2021

22+
"github.com/holiman/uint256"
2123
"golang.org/x/exp/rand"
2224

2325
"github.com/ethereum/go-ethereum/common"
@@ -33,9 +35,16 @@ func NewPseudoRand(seed uint64) *PseudoRand {
3335
return &PseudoRand{rand.New(rand.NewSource(seed))}
3436
}
3537

38+
// Read is equivalent to [rand.Rand.Read] except that it doesn't return an error
39+
// because it is guaranteed to be nil.
40+
func (r *PseudoRand) Read(p []byte) int {
41+
n, _ := r.Rand.Read(p) // Guaranteed nil error
42+
return n
43+
}
44+
3645
// Address returns a pseudorandom address.
3746
func (r *PseudoRand) Address() (a common.Address) {
38-
r.Read(a[:]) //nolint:gosec,errcheck // Guaranteed nil error
47+
r.Read(a[:])
3948
return a
4049
}
4150

@@ -47,18 +56,35 @@ func (r *PseudoRand) AddressPtr() *common.Address {
4756

4857
// Hash returns a pseudorandom hash.
4958
func (r *PseudoRand) Hash() (h common.Hash) {
50-
r.Read(h[:]) //nolint:gosec,errcheck // Guaranteed nil error
59+
r.Read(h[:])
5160
return h
5261
}
5362

63+
// HashPtr returns a pointer to a pseudorandom hash.
64+
func (r *PseudoRand) HashPtr() *common.Hash {
65+
h := r.Hash()
66+
return &h
67+
}
68+
5469
// Bytes returns `n` pseudorandom bytes.
5570
func (r *PseudoRand) Bytes(n uint) []byte {
5671
b := make([]byte, n)
57-
r.Read(b) //nolint:gosec,errcheck // Guaranteed nil error
72+
r.Read(b)
5873
return b
5974
}
6075

6176
// Big returns [rand.Rand.Uint64] as a [big.Int].
6277
func (r *PseudoRand) BigUint64() *big.Int {
6378
return new(big.Int).SetUint64(r.Uint64())
6479
}
80+
81+
// Uint64Ptr returns a pointer to a pseudorandom uint64.
82+
func (r *PseudoRand) Uint64Ptr() *uint64 {
83+
u := r.Uint64()
84+
return &u
85+
}
86+
87+
// Uint256 returns a random 256-bit unsigned int.
88+
func (r *PseudoRand) Uint256() *uint256.Int {
89+
return new(uint256.Int).SetBytes(r.Bytes(32))
90+
}

libevm/pseudo/rlp_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2024 the libevm authors.
2+
//
3+
// The libevm additions to go-ethereum are free software: you can redistribute
4+
// them and/or modify them under the terms of the GNU Lesser General Public License
5+
// as published by the Free Software Foundation, either version 3 of the License,
6+
// or (at your option) any later version.
7+
//
8+
// The libevm additions are distributed in the hope that they will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11+
// General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Lesser General Public License
14+
// along with the go-ethereum library. If not, see
15+
// <http://www.gnu.org/licenses/>.
16+
17+
package pseudo_test
18+
19+
import (
20+
"math/big"
21+
"testing"
22+
23+
"github.com/stretchr/testify/require"
24+
25+
"github.com/ethereum/go-ethereum/core/types"
26+
"github.com/ethereum/go-ethereum/libevm/ethtest"
27+
"github.com/ethereum/go-ethereum/libevm/pseudo"
28+
"github.com/ethereum/go-ethereum/rlp"
29+
)
30+
31+
func TestRLPEquivalence(t *testing.T) {
32+
t.Parallel()
33+
34+
for seed := uint64(0); seed < 20; seed++ {
35+
rng := ethtest.NewPseudoRand(seed)
36+
37+
t.Run("fuzz", func(t *testing.T) {
38+
t.Parallel()
39+
40+
hdr := &types.Header{
41+
ParentHash: rng.Hash(),
42+
UncleHash: rng.Hash(),
43+
Coinbase: rng.Address(),
44+
Root: rng.Hash(),
45+
TxHash: rng.Hash(),
46+
ReceiptHash: rng.Hash(),
47+
Difficulty: big.NewInt(rng.Int63()),
48+
Number: big.NewInt(rng.Int63()),
49+
GasLimit: rng.Uint64(),
50+
GasUsed: rng.Uint64(),
51+
Time: rng.Uint64(),
52+
Extra: rng.Bytes(uint(rng.Uint64n(128))),
53+
MixDigest: rng.Hash(),
54+
}
55+
rng.Read(hdr.Bloom[:])
56+
rng.Read(hdr.Nonce[:])
57+
58+
want, err := rlp.EncodeToBytes(hdr)
59+
require.NoErrorf(t, err, "rlp.EncodeToBytes(%T)", hdr)
60+
61+
typ := pseudo.From(hdr).Type
62+
got, err := rlp.EncodeToBytes(typ)
63+
require.NoErrorf(t, err, "rlp.EncodeToBytes(%T)", typ)
64+
65+
require.Equalf(t, want, got, "RLP encoding of %T (canonical) vs %T (under test)", hdr, typ)
66+
})
67+
}
68+
}

libevm/pseudo/type.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,10 @@ func (v *Value[T]) MarshalJSON() ([]byte, error) { return v.t.MarshalJSON() }
142142
// UnmarshalJSON implements the [json.Unmarshaler] interface.
143143
func (v *Value[T]) UnmarshalJSON(b []byte) error { return v.t.UnmarshalJSON(b) }
144144

145+
// EncodeRLP implements the [rlp.Encoder] interface.
145146
func (t *Type) EncodeRLP(w io.Writer) error { return t.val.EncodeRLP(w) }
146147

148+
// DecodeRLP implements the [rlp.Decoder] interface.
147149
func (t *Type) DecodeRLP(s *rlp.Stream) error { return t.val.DecodeRLP(s) }
148150

149151
var _ = []interface {

0 commit comments

Comments
 (0)