Skip to content

Commit 10eb6f8

Browse files
committed
feat: registration of StateAccount payload type
1 parent 08e0f2a commit 10eb6f8

File tree

4 files changed

+89
-49
lines changed

4 files changed

+89
-49
lines changed

core/types/gen_account_rlp.go

Lines changed: 2 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/types/rlp_payload.libevm.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,46 @@ import (
77
"github.com/ethereum/go-ethereum/rlp"
88
)
99

10-
type RLPPayload struct {
11-
t *pseudo.Type
10+
type Extras[SA any] struct{}
11+
12+
func RegisterExtras[SA any](extras Extras[SA]) {
13+
if registeredExtras != nil {
14+
panic("re-registration of Extras")
15+
}
16+
registeredExtras = &extraConstructors{
17+
newStateAccount: pseudo.NewConstructor[SA]().Zero,
18+
}
1219
}
1320

14-
func NewRLPPayload[T any]() (*RLPPayload, *pseudo.Value[T]) {
15-
var x T
16-
return RLPPayloadOf(x)
21+
var registeredExtras *extraConstructors
22+
23+
type extraConstructors struct {
24+
newStateAccount func() *pseudo.Type
1725
}
1826

19-
func RLPPayloadOf[T any](x T) (*RLPPayload, *pseudo.Value[T]) {
20-
p := pseudo.From(x)
21-
return &RLPPayload{p.Type}, p.Value
27+
type StateAccountExtra struct {
28+
t *pseudo.Type
2229
}
2330

2431
var _ interface {
2532
rlp.Encoder
2633
rlp.Decoder
27-
} = (*RLPPayload)(nil)
34+
} = (*StateAccountExtra)(nil)
2835

29-
func (p *RLPPayload) EncodeRLP(w io.Writer) error {
30-
if p == nil || p.t == nil {
36+
func (p *StateAccountExtra) EncodeRLP(w io.Writer) error {
37+
switch r := registeredExtras; {
38+
case r == nil:
3139
return nil
40+
case p == nil:
41+
p = &StateAccountExtra{}
42+
fallthrough
43+
case p.t == nil:
44+
p.t = r.newStateAccount()
3245
}
3346
return p.t.EncodeRLP(w)
3447
}
3548

36-
func (p *RLPPayload) DecodeRLP(s *rlp.Stream) error {
49+
func (p *StateAccountExtra) DecodeRLP(s *rlp.Stream) error {
3750
// DO NOT MERGE without implementation
3851
return nil
3952
}

core/types/state_account.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ type StateAccount struct {
3434
Root common.Hash // merkle root of the storage trie
3535
CodeHash []byte
3636

37-
Extra *RLPPayload `rlp:"optional"`
37+
Extra *StateAccountExtra
3838
}
3939

4040
// NewEmptyStateAccount constructs an empty state account.

core/types/state_account.libevm_test.go

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/ethereum/go-ethereum/common"
8+
"github.com/ethereum/go-ethereum/libevm/pseudo"
89
"github.com/ethereum/go-ethereum/rlp"
910
"github.com/holiman/uint256"
1011
"github.com/stretchr/testify/require"
@@ -15,63 +16,92 @@ func TestStateAccountRLP(t *testing.T) {
1516
// geth StateAccounts *before* any libevm modifications, thus locking in
1617
// default behaviour. Encodings that involve a boolean payload were
1718
// generated on ava-labs/coreth StateAccounts to guarantee equivalence.
18-
tests := []struct {
19-
name string
20-
acc *StateAccount
21-
wantHex string
22-
}{
23-
{
24-
name: "vanilla geth account",
25-
acc: &StateAccount{
26-
Nonce: 0xcccccc,
27-
Balance: uint256.NewInt(0x555555),
28-
Root: common.MaxHash,
29-
CodeHash: []byte{0x77, 0x77, 0x77},
19+
20+
type test struct {
21+
name string
22+
register func()
23+
acc *StateAccount
24+
wantHex string
25+
}
26+
27+
explicitFalseBoolean := test{
28+
name: "explicit false-boolean extra",
29+
register: func() {
30+
RegisterExtras(Extras[bool]{})
31+
},
32+
acc: &StateAccount{
33+
Nonce: 0x444444,
34+
Balance: uint256.NewInt(0x666666),
35+
Root: common.Hash{},
36+
CodeHash: []byte{0xbb, 0xbb, 0xbb},
37+
Extra: &StateAccountExtra{
38+
t: pseudo.From(false).Type,
3039
},
31-
wantHex: `0xed83cccccc83555555a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83777777`,
3240
},
41+
wantHex: `0xee8344444483666666a0000000000000000000000000000000000000000000000000000000000000000083bbbbbb80`,
42+
}
43+
44+
// The vanilla geth code won't set payloads so we need to ensure that the
45+
// zero-value encoding is used instead of the null-value default as when
46+
// no type is registered.
47+
implicitFalseBoolean := explicitFalseBoolean
48+
implicitFalseBoolean.name = "implicit false-boolean extra as zero-value of registered type"
49+
// Clearing the Extra makes the `false` value implicit and due only to the
50+
// fact that we register `bool`. Most importantly, note that `wantHex`
51+
// remains identical.
52+
implicitFalseBoolean.acc.Extra = nil
53+
54+
tests := []test{
55+
explicitFalseBoolean,
56+
implicitFalseBoolean,
3357
{
34-
name: "vanilla geth account",
58+
name: "true-boolean extra",
59+
register: func() {
60+
RegisterExtras(Extras[bool]{})
61+
},
3562
acc: &StateAccount{
3663
Nonce: 0x444444,
3764
Balance: uint256.NewInt(0x666666),
3865
Root: common.Hash{},
3966
CodeHash: []byte{0xbb, 0xbb, 0xbb},
67+
Extra: &StateAccountExtra{
68+
t: pseudo.From(true).Type,
69+
},
4070
},
41-
wantHex: `0xed8344444483666666a0000000000000000000000000000000000000000000000000000000000000000083bbbbbb`,
71+
wantHex: `0xee8344444483666666a0000000000000000000000000000000000000000000000000000000000000000083bbbbbb01`,
4272
},
4373
{
44-
name: "true boolean extra",
74+
name: "vanilla geth account",
4575
acc: &StateAccount{
46-
Nonce: 0x444444,
47-
Balance: uint256.NewInt(0x666666),
48-
Root: common.Hash{},
49-
CodeHash: []byte{0xbb, 0xbb, 0xbb},
50-
Extra: func() *RLPPayload {
51-
p, _ := RLPPayloadOf(true) // not an error being dropped
52-
return p
53-
}(),
76+
Nonce: 0xcccccc,
77+
Balance: uint256.NewInt(0x555555),
78+
Root: common.MaxHash,
79+
CodeHash: []byte{0x77, 0x77, 0x77},
5480
},
55-
wantHex: `0xee8344444483666666a0000000000000000000000000000000000000000000000000000000000000000083bbbbbb01`,
81+
wantHex: `0xed83cccccc83555555a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83777777`,
5682
},
5783
{
58-
name: "false boolean extra",
84+
name: "vanilla geth account",
5985
acc: &StateAccount{
6086
Nonce: 0x444444,
6187
Balance: uint256.NewInt(0x666666),
6288
Root: common.Hash{},
6389
CodeHash: []byte{0xbb, 0xbb, 0xbb},
64-
Extra: func() *RLPPayload {
65-
p, _ := RLPPayloadOf(false)
66-
return p
67-
}(),
6890
},
69-
wantHex: `0xee8344444483666666a0000000000000000000000000000000000000000000000000000000000000000083bbbbbb80`,
91+
wantHex: `0xed8344444483666666a0000000000000000000000000000000000000000000000000000000000000000083bbbbbb`,
7092
},
7193
}
7294

7395
for _, tt := range tests {
7496
t.Run(tt.name, func(t *testing.T) {
97+
if tt.register != nil {
98+
registeredExtras = nil
99+
tt.register()
100+
t.Cleanup(func() {
101+
registeredExtras = nil
102+
})
103+
}
104+
75105
got, err := rlp.EncodeToBytes(tt.acc)
76106
require.NoError(t, err)
77107
t.Logf("got: %#x", got)

0 commit comments

Comments
 (0)