Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: types.StateAccount pseudo-generic payload #44

Merged
merged 17 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
ARR4N marked this conversation as resolved.
Show resolved Hide resolved
}
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
1 change: 1 addition & 0 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
Balance: acc.Balance,
CodeHash: acc.CodeHash,
Root: common.BytesToHash(acc.Root),
Extra: acc.Extra, // no need to deep-copy as `acc` is short-lived
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code is also removed upstream in upcoming revisions, fyi

}
if len(data.CodeHash) == 0 {
data.CodeHash = types.EmptyCodeHash.Bytes()
Expand Down
3 changes: 3 additions & 0 deletions core/types/gen_account_rlp.go

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

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.

93 changes: 93 additions & 0 deletions core/types/rlp_payload.libevm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// 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 types

import (
"io"

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

type Extras[SA any] struct{}

func RegisterExtras[SA any](extras Extras[SA]) {
if registeredExtras != nil {
panic("re-registration of Extras")
}
registeredExtras = &extraConstructors{
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
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 (e *StateAccountExtra) EncodeRLP(w io.Writer) error {
switch r := registeredExtras; {
case r == nil:
return nil
case e == nil:
e = &StateAccountExtra{}
fallthrough
case e.t == nil:
e.t = r.newStateAccount()
}
return e.t.EncodeRLP(w)
}

func (e *StateAccountExtra) DecodeRLP(s *rlp.Stream) error {
switch r := registeredExtras; {
case r == nil:
return nil
case e.t == nil:
e.t = r.newStateAccount()
fallthrough
default:
return s.Decode(e.t)
}
}
10 changes: 9 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 All @@ -33,6 +34,8 @@ type StateAccount struct {
Balance *uint256.Int
Root common.Hash // merkle root of the storage trie
CodeHash []byte

Extra *StateAccountExtra
}

// NewEmptyStateAccount constructs an empty state account.
Expand All @@ -55,6 +58,7 @@ func (acct *StateAccount) Copy() *StateAccount {
Balance: balance,
Root: acct.Root,
CodeHash: common.CopyBytes(acct.CodeHash),
Extra: acct.Extra.clone(),
}
}

Expand All @@ -66,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 @@ -96,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
Loading