Skip to content

Commit

Permalink
test: pseudo.Type.EncodeRLP()
Browse files Browse the repository at this point in the history
  • Loading branch information
ARR4N committed Oct 1, 2024
1 parent 780a592 commit 9925590
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 3 deletions.
32 changes: 29 additions & 3 deletions libevm/ethtest/rand.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
// 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 ethtest

import (
"math/big"

"github.com/holiman/uint256"
"golang.org/x/exp/rand"

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

// Read is equivalent to [rand.Rand.Read] except that it doesn't return an error
// because it is guaranteed to be nil.
func (r *PseudoRand) Read(p []byte) int {
n, _ := r.Rand.Read(p) // Guaranteed nil error
return n
}

// Address returns a pseudorandom address.
func (r *PseudoRand) Address() (a common.Address) {
r.Read(a[:]) //nolint:gosec,errcheck // Guaranteed nil error
r.Read(a[:])
return a
}

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

// Hash returns a pseudorandom hash.
func (r *PseudoRand) Hash() (h common.Hash) {
r.Read(h[:]) //nolint:gosec,errcheck // Guaranteed nil error
r.Read(h[:])
return h
}

// HashPtr returns a pointer to a pseudorandom hash.
func (r *PseudoRand) HashPtr() *common.Hash {
h := r.Hash()
return &h
}

// Bytes returns `n` pseudorandom bytes.
func (r *PseudoRand) Bytes(n uint) []byte {
b := make([]byte, n)
r.Read(b) //nolint:gosec,errcheck // Guaranteed nil error
r.Read(b)
return b
}

// Big returns [rand.Rand.Uint64] as a [big.Int].
func (r *PseudoRand) BigUint64() *big.Int {
return new(big.Int).SetUint64(r.Uint64())
}

// Uint64Ptr returns a pointer to a pseudorandom uint64.
func (r *PseudoRand) Uint64Ptr() *uint64 {
u := r.Uint64()
return &u
}

// Uint256 returns a random 256-bit unsigned int.
func (r *PseudoRand) Uint256() *uint256.Int {
return new(uint256.Int).SetBytes(r.Bytes(32))
}
68 changes: 68 additions & 0 deletions libevm/pseudo/rlp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2024 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 pseudo_test

import (
"math/big"
"testing"

"github.com/stretchr/testify/require"

"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/libevm/ethtest"
"github.com/ethereum/go-ethereum/libevm/pseudo"
"github.com/ethereum/go-ethereum/rlp"
)

func TestRLPEquivalence(t *testing.T) {
t.Parallel()

for seed := uint64(0); seed < 20; seed++ {
rng := ethtest.NewPseudoRand(seed)

t.Run("fuzz", func(t *testing.T) {
t.Parallel()

hdr := &types.Header{
ParentHash: rng.Hash(),
UncleHash: rng.Hash(),
Coinbase: rng.Address(),
Root: rng.Hash(),
TxHash: rng.Hash(),
ReceiptHash: rng.Hash(),
Difficulty: big.NewInt(rng.Int63()),
Number: big.NewInt(rng.Int63()),
GasLimit: rng.Uint64(),
GasUsed: rng.Uint64(),
Time: rng.Uint64(),
Extra: rng.Bytes(uint(rng.Uint64n(128))),
MixDigest: rng.Hash(),
}
rng.Read(hdr.Bloom[:])
rng.Read(hdr.Nonce[:])

want, err := rlp.EncodeToBytes(hdr)
require.NoErrorf(t, err, "rlp.EncodeToBytes(%T)", hdr)

typ := pseudo.From(hdr).Type
got, err := rlp.EncodeToBytes(typ)
require.NoErrorf(t, err, "rlp.EncodeToBytes(%T)", typ)

require.Equalf(t, want, got, "RLP encoding of %T (canonical) vs %T (under test)", hdr, typ)
})
}
}
2 changes: 2 additions & 0 deletions libevm/pseudo/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ func (v *Value[T]) MarshalJSON() ([]byte, error) { return v.t.MarshalJSON() }
// UnmarshalJSON implements the [json.Unmarshaler] interface.
func (v *Value[T]) UnmarshalJSON(b []byte) error { return v.t.UnmarshalJSON(b) }

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

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

var _ = []interface {
Expand Down

0 comments on commit 9925590

Please sign in to comment.