Skip to content

Commit

Permalink
feat: vm.SlimAccount.Extra from StateAccount equiv
Browse files Browse the repository at this point in the history
  • Loading branch information
ARR4N committed Oct 1, 2024
1 parent 0db9528 commit cda5afb
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 24 deletions.
8 changes: 4 additions & 4 deletions core/state/snapshot/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func TestDiskLayerExternalInvalidationFullFlatten(t *testing.T) {
}
// Since the base layer was modified, ensure that data retrievals on the external reference fail
if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale {
t.Errorf("stale reference returned account: %#x (err: %v)", acc, err)
t.Errorf("stale reference returned account: %+v (err: %v)", acc, err)
}
if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale {
t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err)
Expand Down Expand Up @@ -169,7 +169,7 @@ func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) {
}
// Since the base layer was modified, ensure that data retrievals on the external reference fail
if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale {
t.Errorf("stale reference returned account: %#x (err: %v)", acc, err)
t.Errorf("stale reference returned account: %+v (err: %v)", acc, err)
}
if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale {
t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err)
Expand Down Expand Up @@ -231,7 +231,7 @@ func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) {
}
// Since the accumulator diff layer was modified, ensure that data retrievals on the external reference fail
if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale {
t.Errorf("stale reference returned account: %#x (err: %v)", acc, err)
t.Errorf("stale reference returned account: %+v (err: %v)", acc, err)
}
if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale {
t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err)
Expand Down Expand Up @@ -280,7 +280,7 @@ func TestPostCapBasicDataAccess(t *testing.T) {
// shouldErr checks that an account access errors as expected
shouldErr := func(layer *diffLayer, key string) error {
if data, err := layer.Account(common.HexToHash(key)); err == nil {
return fmt.Errorf("expected error, got data %x", data)
return fmt.Errorf("expected error, got data %+v", data)
}
return nil
}
Expand Down
24 changes: 24 additions & 0 deletions core/types/gen_slim_account_rlp.libevm.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 27 additions & 9 deletions core/types/rlp_payload.libevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,39 +30,57 @@ func RegisterExtras[SA any](extras Extras[SA]) {
panic("re-registration of Extras")
}
registeredExtras = &extraConstructors{
newStateAccount: pseudo.NewConstructor[SA]().Zero,
newStateAccount: pseudo.NewConstructor[SA]().Zero,
cloneStateAccount: extras.cloneStateAccount,
}
}

func (e Extras[SA]) cloneStateAccount(s *StateAccountExtra) *StateAccountExtra {
v := pseudo.MustNewValue[SA](s.t)
return &StateAccountExtra{
t: pseudo.From(v.Get()).Type,
}
}

var registeredExtras *extraConstructors

type extraConstructors struct {
newStateAccount func() *pseudo.Type
newStateAccount func() *pseudo.Type
cloneStateAccount func(*StateAccountExtra) *StateAccountExtra
}

type StateAccountExtra struct {
t *pseudo.Type
}

func (e *StateAccountExtra) clone() *StateAccountExtra {
switch r := registeredExtras; {
case r == nil, e == nil:
return nil
default:
return r.cloneStateAccount(e)
}
}

var _ interface {
rlp.Encoder
rlp.Decoder
} = (*StateAccountExtra)(nil)

func (p *StateAccountExtra) EncodeRLP(w io.Writer) error {
func (e *StateAccountExtra) EncodeRLP(w io.Writer) error {
switch r := registeredExtras; {
case r == nil:
return nil
case p == nil:
p = &StateAccountExtra{}
case e == nil:
e = &StateAccountExtra{}
fallthrough
case p.t == nil:
p.t = r.newStateAccount()
case e.t == nil:
e.t = r.newStateAccount()
}
return p.t.EncodeRLP(w)
return e.t.EncodeRLP(w)
}

func (p *StateAccountExtra) DecodeRLP(s *rlp.Stream) error {
func (e *StateAccountExtra) DecodeRLP(s *rlp.Stream) error {
// DO NOT MERGE without implementation
return nil
}
8 changes: 7 additions & 1 deletion core/types/state_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
)

//go:generate go run ../../rlp/rlpgen -type StateAccount -out gen_account_rlp.go
//go:generate go run ../../rlp/rlpgen -type SlimAccount -out gen_slim_account_rlp.libevm.go

// StateAccount is the Ethereum consensus representation of accounts.
// These objects are stored in the main account trie.
Expand Down Expand Up @@ -57,6 +58,7 @@ func (acct *StateAccount) Copy() *StateAccount {
Balance: balance,
Root: acct.Root,
CodeHash: common.CopyBytes(acct.CodeHash),
Extra: acct.Extra.clone(),
}
}

Expand All @@ -68,21 +70,24 @@ type SlimAccount struct {
Balance *uint256.Int
Root []byte // Nil if root equals to types.EmptyRootHash
CodeHash []byte // Nil if hash equals to types.EmptyCodeHash

Extra *StateAccountExtra
}

// SlimAccountRLP encodes the state account in 'slim RLP' format.
func SlimAccountRLP(account StateAccount) []byte {
slim := SlimAccount{
Nonce: account.Nonce,
Balance: account.Balance,
Extra: account.Extra.clone(),
}
if account.Root != EmptyRootHash {
slim.Root = account.Root[:]
}
if !bytes.Equal(account.CodeHash, EmptyCodeHash[:]) {
slim.CodeHash = account.CodeHash
}
data, err := rlp.EncodeToBytes(slim)
data, err := rlp.EncodeToBytes(&slim)
if err != nil {
panic(err)
}
Expand All @@ -98,6 +103,7 @@ func FullAccount(data []byte) (*StateAccount, error) {
}
var account StateAccount
account.Nonce, account.Balance = slim.Nonce, slim.Balance
account.Extra = slim.Extra.clone()

// Interpret the storage root and code hash in slim format.
if len(slim.Root) == 0 {
Expand Down
32 changes: 22 additions & 10 deletions core/types/state_account.libevm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,34 +142,34 @@ func TestSlimAccountRLP(t *testing.T) {
// modifications, to lock in default behaviour.
tests := []struct {
name string
acc SlimAccount
acc *SlimAccount
wantHex string
}{
{
acc: SlimAccount{
acc: &SlimAccount{
Nonce: 0x444444,
Balance: uint256.NewInt(0x777777),
},
wantHex: `0xca83444444837777778080`,
},
{
acc: SlimAccount{
acc: &SlimAccount{
Nonce: 0x444444,
Balance: uint256.NewInt(0x777777),
Root: common.MaxHash[:],
},
wantHex: `0xea8344444483777777a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80`,
},
{
acc: SlimAccount{
acc: &SlimAccount{
Nonce: 0x444444,
Balance: uint256.NewInt(0x777777),
CodeHash: common.MaxHash[:],
},
wantHex: `0xea834444448377777780a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`,
},
{
acc: SlimAccount{
acc: &SlimAccount{
Nonce: 0x444444,
Balance: uint256.NewInt(0x777777),
Root: common.MaxHash[:],
Expand All @@ -183,12 +183,24 @@ func TestSlimAccountRLP(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
buf := assertRLPEncodingAndReturn(t, tt.acc, tt.wantHex)

var got SlimAccount
require.NoError(t, rlp.DecodeBytes(buf, &got), "rlp.DecodeBytes()")
got := new(SlimAccount)
require.NoError(t, rlp.DecodeBytes(buf, got), "rlp.DecodeBytes()")

opts := []cmp.Option{
// The require package differentiates between empty and nil
// slices and doesn't have a configuration mechanism.
cmpopts.EquateEmpty(),
cmp.Comparer(func(a, b *StateAccountExtra) bool {
aNil := a == nil || a.t == nil
bNil := b == nil || b.t == nil
if aNil && bNil {
return true
}
return false // DO NOT MERGE
}),
}

// The require package differentiates between empty and nil slices
// and doesn't have a configuration mechanism.
if diff := cmp.Diff(tt.acc, got, cmpopts.EquateEmpty()); diff != "" {
if diff := cmp.Diff(tt.acc, got, opts...); diff != "" {
t.Errorf("rlp.DecodeBytes(rlp.EncodeToBytes(%T), ...) round trip; diff (-want +got):\n%s", tt.acc, diff)
}
})
Expand Down

0 comments on commit cda5afb

Please sign in to comment.