Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 7 additions & 2 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package t8ntool

import (
"fmt"
stdmath "math"
"math/big"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -355,7 +356,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)

if isEIP4762 {
statedb.AccessEvents().AddAccount(w.Address, true)
statedb.AccessEvents().AddAccount(w.Address, true, stdmath.MaxUint64)
}
}

Expand Down Expand Up @@ -431,7 +432,11 @@ func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prest
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true, IsVerkle: verkle})
sdb := state.NewDatabase(tdb, nil)

statedb, _ := state.New(types.EmptyRootHash, sdb)
root := types.EmptyRootHash
if verkle {
root = types.EmptyVerkleHash
}
statedb, _ := state.New(root, sdb)
for addr, a := range pre.Pre {
statedb.SetCode(addr, a.Code)
statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeGenesis)
Expand Down
179 changes: 178 additions & 1 deletion cmd/evm/internal/t8ntool/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,22 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/tests"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/utils"
"github.com/ethereum/go-ethereum/triedb"
"github.com/holiman/uint256"
"github.com/urfave/cli/v2"
)

Expand Down Expand Up @@ -194,7 +201,9 @@ func Transition(ctx *cli.Context) error {
s.DumpToCollector(collector, nil)
} else {
vktleaves = make(map[common.Hash]hexutil.Bytes)
s.DumpVKTLeaves(vktleaves)
if err := s.DumpVKTLeaves(vktleaves); err != nil {
return err
}
}
return dispatchOutput(ctx, baseDir, result, collector, body, vktleaves)
}
Expand Down Expand Up @@ -368,3 +377,171 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a
}
return nil
}

// VerkleKey computes the tree key given an address and an optional
// slot number.
func VerkleKey(ctx *cli.Context) error {
if ctx.Args().Len() == 0 || ctx.Args().Len() > 2 {
return errors.New("invalid number of arguments: expecting an address and an optional slot number")
}

addr, err := hexutil.Decode(ctx.Args().Get(0))
if err != nil {
return fmt.Errorf("error decoding address: %w", err)
}

ap := utils.EvaluateAddressPoint(addr)
if ctx.Args().Len() == 2 {
slot, err := hexutil.Decode(ctx.Args().Get(1))
if err != nil {
return fmt.Errorf("error decoding slot: %w", err)
}
fmt.Printf("%#x\n", utils.GetTreeKeyStorageSlotWithEvaluatedAddress(ap, slot))
} else {
fmt.Printf("%#x\n", utils.GetTreeKeyBasicDataEvaluatedAddress(ap))
}
return nil
}

// VerkleKeys computes a set of tree keys given a genesis alloc.
func VerkleKeys(ctx *cli.Context) error {
var allocStr = ctx.String(InputAllocFlag.Name)
var alloc core.GenesisAlloc
// Figure out the prestate alloc
if allocStr == stdinSelector {
decoder := json.NewDecoder(os.Stdin)
if err := decoder.Decode(&alloc); err != nil {
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err))
}
}
if allocStr != stdinSelector {
if err := readFile(allocStr, "alloc", &alloc); err != nil {
return err
}
}

vkt, err := genVktFromAlloc(alloc)
if err != nil {
return fmt.Errorf("error generating vkt: %w", err)
}

collector := make(map[common.Hash]hexutil.Bytes)
it, err := vkt.NodeIterator(nil)
if err != nil {
panic(err)
}
for it.Next(true) {
if it.Leaf() {
collector[common.BytesToHash(it.LeafKey())] = it.LeafBlob()
}
}

output, err := json.MarshalIndent(collector, "", "")
if err != nil {
return fmt.Errorf("error outputting tree: %w", err)
}

fmt.Println(string(output))

return nil
}

// VerkleRoot computes the root of a VKT from a genesis alloc.
func VerkleRoot(ctx *cli.Context) error {
var allocStr = ctx.String(InputAllocFlag.Name)
var alloc core.GenesisAlloc
if allocStr == stdinSelector {
decoder := json.NewDecoder(os.Stdin)
if err := decoder.Decode(&alloc); err != nil {
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err))
}
}
if allocStr != stdinSelector {
if err := readFile(allocStr, "alloc", &alloc); err != nil {
return err
}
}

vkt, err := genVktFromAlloc(alloc)
if err != nil {
return fmt.Errorf("error generating vkt: %w", err)
}
fmt.Println(vkt.Hash().Hex())

return nil
}

func genVktFromAlloc(alloc core.GenesisAlloc) (*trie.VerkleTrie, error) {
vkt, err := trie.NewVerkleTrie(types.EmptyVerkleHash, triedb.NewDatabase(rawdb.NewMemoryDatabase(),
&triedb.Config{
IsVerkle: true,
}), utils.NewPointCache(1024))
if err != nil {
return nil, err
}

for addr, acc := range alloc {
for slot, value := range acc.Storage {
err := vkt.UpdateStorage(addr, slot.Bytes(), value.Big().Bytes())
if err != nil {
return nil, fmt.Errorf("error inserting storage: %w", err)
}
}

account := &types.StateAccount{
Balance: uint256.MustFromBig(acc.Balance),
Nonce: acc.Nonce,
CodeHash: crypto.Keccak256Hash(acc.Code).Bytes(),
Root: common.Hash{},
}
err := vkt.UpdateAccount(addr, account, len(acc.Code))
if err != nil {
return nil, fmt.Errorf("error inserting account: %w", err)
}

err = vkt.UpdateContractCode(addr, common.BytesToHash(account.CodeHash), acc.Code)
if err != nil {
return nil, fmt.Errorf("error inserting code: %w", err)
}
}
return vkt, nil
}

// VerkleCodeChunkKey computes the tree key of a code-chunk for a given address.
func VerkleCodeChunkKey(ctx *cli.Context) error {
if ctx.Args().Len() == 0 || ctx.Args().Len() > 2 {
return errors.New("invalid number of arguments: expecting an address and an code-chunk number")
}

addr, err := hexutil.Decode(ctx.Args().Get(0))
if err != nil {
return fmt.Errorf("error decoding address: %w", err)
}
chunkNumberBytes, err := hexutil.Decode(ctx.Args().Get(1))
if err != nil {
return fmt.Errorf("error decoding chunk number: %w", err)
}
var chunkNumber uint256.Int
chunkNumber.SetBytes(chunkNumberBytes)

fmt.Printf("%#x\n", utils.GetTreeKeyCodeChunk(addr, &chunkNumber))

return nil
}

// VerkleChunkifyCode returns the code chunkification for a given code.
func VerkleChunkifyCode(ctx *cli.Context) error {
if ctx.Args().Len() == 0 || ctx.Args().Len() > 1 {
return errors.New("invalid number of arguments: expecting a bytecode")
}

bytecode, err := hexutil.Decode(ctx.Args().Get(0))
if err != nil {
return fmt.Errorf("error decoding address: %w", err)
}

chunkedCode := trie.ChunkifyCode(bytecode)
fmt.Printf("%#x\n", chunkedCode)

return nil
}
46 changes: 46 additions & 0 deletions cmd/evm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,51 @@ var (
t8ntool.RewardFlag,
},
}

verkleCommand = &cli.Command{
Name: "verkle",
Aliases: []string{"vkt"},
Usage: "Verkle helpers",
Subcommands: []*cli.Command{
{
Name: "tree-keys",
Aliases: []string{"v"},
Usage: "compute a set of verkle tree keys, given their source addresses and optional slot numbers",
Action: t8ntool.VerkleKeys,
Flags: []cli.Flag{
t8ntool.InputAllocFlag,
},
},
{
Name: "single-key",
Aliases: []string{"vk"},
Usage: "compute the verkle tree key given an address and optional slot number",
Action: t8ntool.VerkleKey,
},
{
Name: "code-chunk-key",
Aliases: []string{"vck"},
Usage: "compute the verkle tree key given an address and chunk number",
Action: t8ntool.VerkleCodeChunkKey,
},
{
Name: "chunkify-code",
Aliases: []string{"vcc"},
Usage: "chunkify a given bytecode",
Action: t8ntool.VerkleChunkifyCode,
},
{
Name: "state-root",
Aliases: []string{"vsr"},
Usage: "compute the state-root of a verkle tree for the given alloc",
Action: t8ntool.VerkleRoot,
Flags: []cli.Flag{
t8ntool.InputAllocFlag,
},
},
},
}

transactionCommand = &cli.Command{
Name: "transaction",
Aliases: []string{"t9n"},
Expand Down Expand Up @@ -213,6 +258,7 @@ func init() {
stateTransitionCommand,
transactionCommand,
blockBuilderCommand,
verkleCommand,
}
app.Before = func(ctx *cli.Context) error {
flags.MigrateGlobalFlags(ctx)
Expand Down
11 changes: 10 additions & 1 deletion core/state/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,15 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
return nextKey
}

func (s *StateDB) DumpVKTLeaves(collector map[common.Hash]hexutil.Bytes) {
func (s *StateDB) DumpVKTLeaves(collector map[common.Hash]hexutil.Bytes) error {
if s.trie == nil {
trie, err := s.db.OpenTrie(s.originalRoot)
if err != nil {
return err
}
s.trie = trie
}

it, err := s.trie.(*trie.VerkleTrie).NodeIterator(nil)
if err != nil {
panic(err)
Expand All @@ -231,6 +239,7 @@ func (s *StateDB) DumpVKTLeaves(collector map[common.Hash]hexutil.Bytes) {
collector[common.BytesToHash(it.LeafKey())] = it.LeafBlob()
}
}
return nil
}

// RawDump returns the state. If the processing is aborted e.g. due to options
Expand Down
Loading