Skip to content

Commit dfb1158

Browse files
authored
bring in verkle iterator and verkle subcommand (#549)
1 parent 694b6a1 commit dfb1158

File tree

7 files changed

+357
-6
lines changed

7 files changed

+357
-6
lines changed

cmd/evm/internal/t8ntool/execution.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package t8ntool
1818

1919
import (
2020
"fmt"
21+
stdmath "math"
2122
"math/big"
2223

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

357358
if isEIP4762 {
358-
statedb.AccessEvents().AddAccount(w.Address, true)
359+
statedb.AccessEvents().AddAccount(w.Address, true, stdmath.MaxUint64)
359360
}
360361
}
361362

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

434-
statedb, _ := state.New(types.EmptyRootHash, sdb)
435+
root := types.EmptyRootHash
436+
if verkle {
437+
root = types.EmptyVerkleHash
438+
}
439+
statedb, _ := state.New(root, sdb)
435440
for addr, a := range pre.Pre {
436441
statedb.SetCode(addr, a.Code)
437442
statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeGenesis)

cmd/evm/internal/t8ntool/transition.go

Lines changed: 178 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,22 @@ import (
2828
"github.com/ethereum/go-ethereum/common"
2929
"github.com/ethereum/go-ethereum/common/hexutil"
3030
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
31+
"github.com/ethereum/go-ethereum/core"
32+
"github.com/ethereum/go-ethereum/core/rawdb"
3133
"github.com/ethereum/go-ethereum/core/state"
3234
"github.com/ethereum/go-ethereum/core/tracing"
3335
"github.com/ethereum/go-ethereum/core/types"
3436
"github.com/ethereum/go-ethereum/core/vm"
37+
"github.com/ethereum/go-ethereum/crypto"
3538
"github.com/ethereum/go-ethereum/eth/tracers"
3639
"github.com/ethereum/go-ethereum/eth/tracers/logger"
3740
"github.com/ethereum/go-ethereum/log"
3841
"github.com/ethereum/go-ethereum/params"
3942
"github.com/ethereum/go-ethereum/tests"
43+
"github.com/ethereum/go-ethereum/trie"
44+
"github.com/ethereum/go-ethereum/trie/utils"
45+
"github.com/ethereum/go-ethereum/triedb"
46+
"github.com/holiman/uint256"
4047
"github.com/urfave/cli/v2"
4148
)
4249

@@ -194,7 +201,9 @@ func Transition(ctx *cli.Context) error {
194201
s.DumpToCollector(collector, nil)
195202
} else {
196203
vktleaves = make(map[common.Hash]hexutil.Bytes)
197-
s.DumpVKTLeaves(vktleaves)
204+
if err := s.DumpVKTLeaves(vktleaves); err != nil {
205+
return err
206+
}
198207
}
199208
return dispatchOutput(ctx, baseDir, result, collector, body, vktleaves)
200209
}
@@ -368,3 +377,171 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a
368377
}
369378
return nil
370379
}
380+
381+
// VerkleKey computes the tree key given an address and an optional
382+
// slot number.
383+
func VerkleKey(ctx *cli.Context) error {
384+
if ctx.Args().Len() == 0 || ctx.Args().Len() > 2 {
385+
return errors.New("invalid number of arguments: expecting an address and an optional slot number")
386+
}
387+
388+
addr, err := hexutil.Decode(ctx.Args().Get(0))
389+
if err != nil {
390+
return fmt.Errorf("error decoding address: %w", err)
391+
}
392+
393+
ap := utils.EvaluateAddressPoint(addr)
394+
if ctx.Args().Len() == 2 {
395+
slot, err := hexutil.Decode(ctx.Args().Get(1))
396+
if err != nil {
397+
return fmt.Errorf("error decoding slot: %w", err)
398+
}
399+
fmt.Printf("%#x\n", utils.GetTreeKeyStorageSlotWithEvaluatedAddress(ap, slot))
400+
} else {
401+
fmt.Printf("%#x\n", utils.GetTreeKeyBasicDataEvaluatedAddress(ap))
402+
}
403+
return nil
404+
}
405+
406+
// VerkleKeys computes a set of tree keys given a genesis alloc.
407+
func VerkleKeys(ctx *cli.Context) error {
408+
var allocStr = ctx.String(InputAllocFlag.Name)
409+
var alloc core.GenesisAlloc
410+
// Figure out the prestate alloc
411+
if allocStr == stdinSelector {
412+
decoder := json.NewDecoder(os.Stdin)
413+
if err := decoder.Decode(&alloc); err != nil {
414+
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err))
415+
}
416+
}
417+
if allocStr != stdinSelector {
418+
if err := readFile(allocStr, "alloc", &alloc); err != nil {
419+
return err
420+
}
421+
}
422+
423+
vkt, err := genVktFromAlloc(alloc)
424+
if err != nil {
425+
return fmt.Errorf("error generating vkt: %w", err)
426+
}
427+
428+
collector := make(map[common.Hash]hexutil.Bytes)
429+
it, err := vkt.NodeIterator(nil)
430+
if err != nil {
431+
panic(err)
432+
}
433+
for it.Next(true) {
434+
if it.Leaf() {
435+
collector[common.BytesToHash(it.LeafKey())] = it.LeafBlob()
436+
}
437+
}
438+
439+
output, err := json.MarshalIndent(collector, "", "")
440+
if err != nil {
441+
return fmt.Errorf("error outputting tree: %w", err)
442+
}
443+
444+
fmt.Println(string(output))
445+
446+
return nil
447+
}
448+
449+
// VerkleRoot computes the root of a VKT from a genesis alloc.
450+
func VerkleRoot(ctx *cli.Context) error {
451+
var allocStr = ctx.String(InputAllocFlag.Name)
452+
var alloc core.GenesisAlloc
453+
if allocStr == stdinSelector {
454+
decoder := json.NewDecoder(os.Stdin)
455+
if err := decoder.Decode(&alloc); err != nil {
456+
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err))
457+
}
458+
}
459+
if allocStr != stdinSelector {
460+
if err := readFile(allocStr, "alloc", &alloc); err != nil {
461+
return err
462+
}
463+
}
464+
465+
vkt, err := genVktFromAlloc(alloc)
466+
if err != nil {
467+
return fmt.Errorf("error generating vkt: %w", err)
468+
}
469+
fmt.Println(vkt.Hash().Hex())
470+
471+
return nil
472+
}
473+
474+
func genVktFromAlloc(alloc core.GenesisAlloc) (*trie.VerkleTrie, error) {
475+
vkt, err := trie.NewVerkleTrie(types.EmptyVerkleHash, triedb.NewDatabase(rawdb.NewMemoryDatabase(),
476+
&triedb.Config{
477+
IsVerkle: true,
478+
}), utils.NewPointCache(1024))
479+
if err != nil {
480+
return nil, err
481+
}
482+
483+
for addr, acc := range alloc {
484+
for slot, value := range acc.Storage {
485+
err := vkt.UpdateStorage(addr, slot.Bytes(), value.Big().Bytes())
486+
if err != nil {
487+
return nil, fmt.Errorf("error inserting storage: %w", err)
488+
}
489+
}
490+
491+
account := &types.StateAccount{
492+
Balance: uint256.MustFromBig(acc.Balance),
493+
Nonce: acc.Nonce,
494+
CodeHash: crypto.Keccak256Hash(acc.Code).Bytes(),
495+
Root: common.Hash{},
496+
}
497+
err := vkt.UpdateAccount(addr, account, len(acc.Code))
498+
if err != nil {
499+
return nil, fmt.Errorf("error inserting account: %w", err)
500+
}
501+
502+
err = vkt.UpdateContractCode(addr, common.BytesToHash(account.CodeHash), acc.Code)
503+
if err != nil {
504+
return nil, fmt.Errorf("error inserting code: %w", err)
505+
}
506+
}
507+
return vkt, nil
508+
}
509+
510+
// VerkleCodeChunkKey computes the tree key of a code-chunk for a given address.
511+
func VerkleCodeChunkKey(ctx *cli.Context) error {
512+
if ctx.Args().Len() == 0 || ctx.Args().Len() > 2 {
513+
return errors.New("invalid number of arguments: expecting an address and an code-chunk number")
514+
}
515+
516+
addr, err := hexutil.Decode(ctx.Args().Get(0))
517+
if err != nil {
518+
return fmt.Errorf("error decoding address: %w", err)
519+
}
520+
chunkNumberBytes, err := hexutil.Decode(ctx.Args().Get(1))
521+
if err != nil {
522+
return fmt.Errorf("error decoding chunk number: %w", err)
523+
}
524+
var chunkNumber uint256.Int
525+
chunkNumber.SetBytes(chunkNumberBytes)
526+
527+
fmt.Printf("%#x\n", utils.GetTreeKeyCodeChunk(addr, &chunkNumber))
528+
529+
return nil
530+
}
531+
532+
// VerkleChunkifyCode returns the code chunkification for a given code.
533+
func VerkleChunkifyCode(ctx *cli.Context) error {
534+
if ctx.Args().Len() == 0 || ctx.Args().Len() > 1 {
535+
return errors.New("invalid number of arguments: expecting a bytecode")
536+
}
537+
538+
bytecode, err := hexutil.Decode(ctx.Args().Get(0))
539+
if err != nil {
540+
return fmt.Errorf("error decoding address: %w", err)
541+
}
542+
543+
chunkedCode := trie.ChunkifyCode(bytecode)
544+
fmt.Printf("%#x\n", chunkedCode)
545+
546+
return nil
547+
}

cmd/evm/main.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,51 @@ var (
159159
t8ntool.RewardFlag,
160160
},
161161
}
162+
163+
verkleCommand = &cli.Command{
164+
Name: "verkle",
165+
Aliases: []string{"vkt"},
166+
Usage: "Verkle helpers",
167+
Subcommands: []*cli.Command{
168+
{
169+
Name: "tree-keys",
170+
Aliases: []string{"v"},
171+
Usage: "compute a set of verkle tree keys, given their source addresses and optional slot numbers",
172+
Action: t8ntool.VerkleKeys,
173+
Flags: []cli.Flag{
174+
t8ntool.InputAllocFlag,
175+
},
176+
},
177+
{
178+
Name: "single-key",
179+
Aliases: []string{"vk"},
180+
Usage: "compute the verkle tree key given an address and optional slot number",
181+
Action: t8ntool.VerkleKey,
182+
},
183+
{
184+
Name: "code-chunk-key",
185+
Aliases: []string{"vck"},
186+
Usage: "compute the verkle tree key given an address and chunk number",
187+
Action: t8ntool.VerkleCodeChunkKey,
188+
},
189+
{
190+
Name: "chunkify-code",
191+
Aliases: []string{"vcc"},
192+
Usage: "chunkify a given bytecode",
193+
Action: t8ntool.VerkleChunkifyCode,
194+
},
195+
{
196+
Name: "state-root",
197+
Aliases: []string{"vsr"},
198+
Usage: "compute the state-root of a verkle tree for the given alloc",
199+
Action: t8ntool.VerkleRoot,
200+
Flags: []cli.Flag{
201+
t8ntool.InputAllocFlag,
202+
},
203+
},
204+
},
205+
}
206+
162207
transactionCommand = &cli.Command{
163208
Name: "transaction",
164209
Aliases: []string{"t9n"},
@@ -213,6 +258,7 @@ func init() {
213258
stateTransitionCommand,
214259
transactionCommand,
215260
blockBuilderCommand,
261+
verkleCommand,
216262
}
217263
app.Before = func(ctx *cli.Context) error {
218264
flags.MigrateGlobalFlags(ctx)

core/state/dump.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,15 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
221221
return nextKey
222222
}
223223

224-
func (s *StateDB) DumpVKTLeaves(collector map[common.Hash]hexutil.Bytes) {
224+
func (s *StateDB) DumpVKTLeaves(collector map[common.Hash]hexutil.Bytes) error {
225+
if s.trie == nil {
226+
trie, err := s.db.OpenTrie(s.originalRoot)
227+
if err != nil {
228+
return err
229+
}
230+
s.trie = trie
231+
}
232+
225233
it, err := s.trie.(*trie.VerkleTrie).NodeIterator(nil)
226234
if err != nil {
227235
panic(err)
@@ -231,6 +239,7 @@ func (s *StateDB) DumpVKTLeaves(collector map[common.Hash]hexutil.Bytes) {
231239
collector[common.BytesToHash(it.LeafKey())] = it.LeafBlob()
232240
}
233241
}
242+
return nil
234243
}
235244

236245
// RawDump returns the state. If the processing is aborted e.g. due to options

0 commit comments

Comments
 (0)