From 777d14f730ed989f353b505ee9e5044029c08d19 Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:48:54 +0200 Subject: [PATCH] save current state --- cmd/geth/chaincmd.go | 2 +- cmd/utils/cmd.go | 4 + consensus/beacon/consensus.go | 135 +++++++++++------------- core/block_validator.go | 1 + core/blockchain.go | 4 +- core/overlay/conversion.go | 60 ++++++++--- core/state/access_witness.go | 76 ++++++++------ core/state/database.go | 11 +- core/state/statedb.go | 4 +- core/state_processor.go | 125 +++++++++++++++++++++- core/vm/interpreter.go | 1 + core/vm/operations_verkle.go | 25 ++--- eth/tracers/tracers_test.go | 7 +- go.mod | 14 +-- go.sum | 32 +++--- light/trie.go | 2 +- params/config.go | 4 +- trie/secure_trie.go | 2 +- trie/transition.go | 4 +- trie/utils/verkle.go | 30 ++---- trie/verkle.go | 188 ++++++++++++++++++++++------------ trie/verkle_iterator_test.go | 4 +- 22 files changed, 465 insertions(+), 270 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 2179b61032b..6cdddccd576 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -425,7 +425,7 @@ func exportOverlayPreimages(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - chain, _ := utils.MakeChain(ctx, stack, true) + chain, _ := utils.MakeChain(ctx, stack, false) var root common.Hash if ctx.String(utils.TreeRootFlag.Name) != "" { diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index de25fd1a146..092401ef86c 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -170,6 +170,10 @@ func ImportChain(chain *core.BlockChain, fn string) error { } defer fh.Close() + // if _, err := fh.Seek(18224628422, 0); err != nil { + // panic(err) + // } + var reader io.Reader = fh if strings.HasSuffix(fn, ".gz") { if reader, err = gzip.NewReader(reader); err != nil { diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index e40c180aa42..fbf0290749c 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -32,8 +32,9 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/utils" - "github.com/ethereum/go-verkle" + // "github.com/ethereum/go-ethereum/trie/utils" + // "github.com/ethereum/go-verkle" + // "github.com/pk910/dynamic-ssz" ) // Proof-of-stake protocol constants. @@ -373,9 +374,9 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. // FinalizeAndAssemble implements consensus.Engine, setting the final state and // assembling the block. -func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { +func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { if !beacon.IsPoSHeader(header) { - return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil) + return beacon.ethone.FinalizeAndAssemble(chain, header, statedb, txs, uncles, receipts, nil) } shanghai := chain.Config().IsShanghai(header.Number, header.Time) if shanghai { @@ -389,86 +390,66 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea } } // Finalize and assemble the block. - beacon.Finalize(chain, header, state, txs, uncles, withdrawals) + beacon.Finalize(chain, header, statedb, txs, uncles, withdrawals) // Assign the final state root to header. - header.Root = state.IntermediateRoot(true) + header.Root = statedb.IntermediateRoot(true) // Associate current conversion state to computed state // root and store it in the database for later recovery. - state.Database().SaveTransitionState(header.Root) - - var ( - p *verkle.VerkleProof - k verkle.StateDiff - keys = state.Witness().Keys() - ) - if chain.Config().IsPrague(header.Number, header.Time) { - // Open the pre-tree to prove the pre-state against - parent := chain.GetHeaderByNumber(header.Number.Uint64() - 1) - if parent == nil { - return nil, fmt.Errorf("nil parent header for block %d", header.Number) - } - - // Load transition state at beginning of block, because - // OpenTrie needs to know what the conversion status is. - state.Database().LoadTransitionState(parent.Root) - - if chain.Config().ProofInBlocks { - preTrie, err := state.Database().OpenTrie(parent.Root) - if err != nil { - return nil, fmt.Errorf("error opening pre-state tree root: %w", err) - } - - var okpre, okpost bool - var vtrpre, vtrpost *trie.VerkleTrie - switch pre := preTrie.(type) { - case *trie.VerkleTrie: - vtrpre, okpre = preTrie.(*trie.VerkleTrie) - switch tr := state.GetTrie().(type) { - case *trie.VerkleTrie: - vtrpost = tr - okpost = true - // This is to handle a situation right at the start of the conversion: - // the post trie is a transition tree when the pre tree is an empty - // verkle tree. - case *trie.TransitionTrie: - vtrpost = tr.Overlay() - okpost = true - default: - okpost = false - } - case *trie.TransitionTrie: - vtrpre = pre.Overlay() - okpre = true - post, _ := state.GetTrie().(*trie.TransitionTrie) - vtrpost = post.Overlay() - okpost = true - default: - // This should only happen for the first block of the - // conversion, when the previous tree is a merkle tree. - // Logically, the "previous" verkle tree is an empty tree. - okpre = true - vtrpre = trie.NewVerkleTrie(verkle.New(), state.Database().TrieDB(), utils.NewPointCache(), false) - post := state.GetTrie().(*trie.TransitionTrie) - vtrpost = post.Overlay() - okpost = true - } - if okpre && okpost { - if len(keys) > 0 { - p, k, err = trie.ProveAndSerialize(vtrpre, vtrpost, keys, vtrpre.FlatdbNodeResolver) - if err != nil { - return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err) - } - } - } - } - } + statedb.Database().SaveTransitionState(header.Root) + + // var ( + // p *verkle.VerkleProof + // k verkle.StateDiff + // keys = statedb.Witness().Keys() + // ) + // if chain.Config().IsPrague(header.Number, header.Time) { + // // Open the pre-tree to prove the pre-state against + // parent := chain.GetHeaderByNumber(header.Number.Uint64() - 1) + // if parent == nil { + // return nil, fmt.Errorf("nil parent header for block %d", header.Number) + // } + + // // Load transition state at beginning of block, because + // // OpenTrie needs to know what the conversion status is. + // statedb.Database().LoadTransitionState(parent.Root) + + // preTrie, err := statedb.Database().OpenTrie(parent.Root) + // if err != nil { + // return nil, fmt.Errorf("error opening pre-state tree root: %w", err) + // } + + // var vtrpre *trie.VerkleTrie + // switch pre := preTrie.(type) { + // case *trie.VerkleTrie: + // vtrpre = preTrie.(*trie.VerkleTrie) + // case *trie.TransitionTrie: + // vtrpre = pre.Overlay() + // default: + // panic("should not happen") + // } + // if len(keys) > 0 { + // p, k, err = trie.ProveAndSerialize(vtrpre, nil, keys, vtrpre.FlatdbNodeResolver) + // if err != nil { + // return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err) + // } + // } + + // ew := types.ExecutionWitness{StateDiff: k, VerkleProof: p} + // encoder := dynssz.NewDynSsz(map[string]any{}) + // encoded, err := encoder.MarshalSSZ(&ew) + // if err != nil { + // spew.Dump(ew) + // panic(err) + // } + // state.AppendBytesToFile("witness_size.csv", []byte(fmt.Sprintf("%d,%d", header.Number, len(encoded)))) + // } // Assemble and return the final block. block := types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil)) - if chain.Config().IsPrague(header.Number, header.Time) && chain.Config().ProofInBlocks { - block.SetVerkleProof(p, k) - } + // if chain.Config().IsPrague(header.Number, header.Time) && chain.Config().ProofInBlocks { + // block.SetVerkleProof(p, k) + // } return block, nil } diff --git a/core/block_validator.go b/core/block_validator.go index d3058b156c4..a80d42c9341 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -126,6 +126,7 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD // if receiptSha != header.ReceiptHash { // return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha) // } + // // Validate the state root against the received state root and throw // // an error if they don't match. // if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root { diff --git a/core/blockchain.go b/core/blockchain.go index f92d174ccf1..f843d49f7b4 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -249,7 +249,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis } if overrides != nil { if overrides.OverrideProofInBlock != nil { - chainConfig.ProofInBlocks = *overrides.OverrideProofInBlock + chainConfig.ProofInBlocks = true // *overrides.OverrideProofInBlock } if overrides.OverrideOverlayStride != nil { chainConfig.OverlayStride = *overrides.OverrideOverlayStride @@ -322,7 +322,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis // for it to be able to recover if interrupted during the transition // but that's left out to a later PR since there's not really a need // right now. - bc.stateCache.InitTransitionStatus(true, true) + bc.stateCache.InitTransitionStatus(false, false) bc.stateCache.EndVerkleTransition() } diff --git a/core/overlay/conversion.go b/core/overlay/conversion.go index 0e83e206635..ebd50f75fbb 100644 --- a/core/overlay/conversion.go +++ b/core/overlay/conversion.go @@ -95,19 +95,15 @@ func (kvm *keyValueMigrator) addStorageSlot(addr []byte, slotNumber []byte, slot func (kvm *keyValueMigrator) addAccount(addr []byte, acc *types.StateAccount) { leafNodeData := kvm.getOrInitLeafNodeData(newBranchKey(addr, &zeroTreeIndex)) - var version [verkle.LeafValueSize]byte - leafNodeData.Values[utils.VersionLeafKey] = version[:] + var basicData [verkle.LeafValueSize]byte + basicData[utils.BasicDataVersionOffset] = 0 + binary.BigEndian.PutUint64(basicData[utils.BasicDataNonceOffset:], acc.Nonce) - var balance [verkle.LeafValueSize]byte - for i, b := range acc.Balance.Bytes() { - balance[len(acc.Balance.Bytes())-1-i] = b - } - leafNodeData.Values[utils.BalanceLeafKey] = balance[:] - - var nonce [verkle.LeafValueSize]byte - binary.LittleEndian.PutUint64(nonce[:8], acc.Nonce) - leafNodeData.Values[utils.NonceLeafKey] = nonce[:] + // get the lower 16 bytes of water and change its endianness + balanceBytes := acc.Balance.Bytes() + copy(basicData[32-len(balanceBytes):], balanceBytes[:]) + leafNodeData.Values[utils.BasicDataLeafKey] = basicData[:] leafNodeData.Values[utils.CodeHashLeafKey] = acc.CodeHash[:] } @@ -115,9 +111,9 @@ func (kvm *keyValueMigrator) addAccountCode(addr []byte, codeSize uint64, chunks leafNodeData := kvm.getOrInitLeafNodeData(newBranchKey(addr, &zeroTreeIndex)) // Save the code size. - var codeSizeBytes [verkle.LeafValueSize]byte - binary.LittleEndian.PutUint64(codeSizeBytes[:8], codeSize) - leafNodeData.Values[utils.CodeSizeLeafKey] = codeSizeBytes[:] + var cs [4]byte + binary.BigEndian.PutUint32(cs[:], uint32(codeSize)) + copy(leafNodeData.Values[utils.BasicDataLeafKey][utils.BasicDataCodeSizeOffset:utils.BasicDataNonceOffset], cs[:]) // The first 128 chunks are stored in the account header leaf. for i := 0; i < 128 && i < len(chunks)/32; i++ { @@ -218,12 +214,27 @@ func (kvm *keyValueMigrator) migrateCollectedKeyValues(tree *trie.VerkleTrie) er return nil } +var dump bool = false + // OverlayVerkleTransition contains the overlay conversion logic func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedCount uint64) error { migrdb := statedb.Database() migrdb.LockCurrentTransitionState() defer migrdb.UnLockCurrentTransitionState() + // Open or create file for writing; append data if file exists + var ( + file *os.File + err error + ) + if dump { + file, err = os.OpenFile("prout.bin", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer file.Close() + } + // verkle transition: if the conversion process is in progress, move // N values from the MPT into the verkle tree. if migrdb.InTransition() { @@ -271,6 +282,13 @@ func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedC if len(addr) != 20 { return fmt.Errorf("addr len is zero is not 32: %d", len(addr)) } + if dump { + n, err := file.Write(addr.Bytes()) + if err != nil { + fmt.Println(n, addr, err, file) + panic(err) + } + } } migrdb.SetCurrentAccountAddress(addr) if migrdb.GetCurrentAccountHash() != accIt.Hash() { @@ -344,7 +362,13 @@ func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedC } else { slotnr = rawdb.ReadPreimage(migrdb.DiskDB(), stIt.Hash()) if len(slotnr) != 32 { - return fmt.Errorf("slotnr len is zero is not 32: %d", len(slotnr)) + panic(fmt.Errorf("slotnr len is zero is not 32: %d", len(slotnr))) + } + if dump { + _, err = file.Write(slotnr) + if err != nil { + panic(err) + } } } log.Trace("found slot number", "number", slotnr) @@ -400,6 +424,12 @@ func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedC if len(addr) != 20 { return fmt.Errorf("account address len is zero is not 20: %d", len(addr)) } + if dump { + _, err = file.Write(addr.Bytes()) + if err != nil { + panic(err) + } + } } if crypto.Keccak256Hash(addr[:]) != accIt.Hash() { return fmt.Errorf("preimage file does not match account hash: %s != %s", crypto.Keccak256Hash(addr[:]), accIt.Hash()) diff --git a/core/state/access_witness.go b/core/state/access_witness.go index 4c9d3218ad9..d1f057834ce 100644 --- a/core/state/access_witness.go +++ b/core/state/access_witness.go @@ -17,6 +17,8 @@ package state import ( + "os" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/params" @@ -91,7 +93,7 @@ func (aw *AccessWitness) Copy() *AccessWitness { func (aw *AccessWitness) TouchFullAccount(addr []byte, isWrite bool) uint64 { var gas uint64 - for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ { + for i := utils.BasicDataLeafKey; i <= utils.CodeHashLeafKey; i++ { gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, byte(i), isWrite) } return gas @@ -99,15 +101,14 @@ func (aw *AccessWitness) TouchFullAccount(addr []byte, isWrite bool) uint64 { func (aw *AccessWitness) TouchAndChargeMessageCall(addr []byte) uint64 { var gas uint64 - gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, false) - gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeSizeLeafKey, false) + gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, false) return gas } func (aw *AccessWitness) TouchAndChargeValueTransfer(callerAddr, targetAddr []byte) uint64 { var gas uint64 - gas += aw.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BalanceLeafKey, true) - gas += aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, true) + gas += aw.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BasicDataLeafKey, true) + gas += aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true) return gas } @@ -115,17 +116,13 @@ func (aw *AccessWitness) TouchAndChargeValueTransfer(callerAddr, targetAddr []by // a contract creation func (aw *AccessWitness) TouchAndChargeContractCreateInit(addr []byte, createSendsValue bool) uint64 { var gas uint64 - gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, true) - gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, true) - if createSendsValue { - gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, true) - } + gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, true) return gas } func (aw *AccessWitness) TouchTxOriginAndComputeGas(originAddr []byte) uint64 { - for i := utils.VersionLeafKey; i <= utils.CodeSizeLeafKey; i++ { - aw.touchAddressAndChargeGas(originAddr, zeroTreeIndex, byte(i), i == utils.BalanceLeafKey || i == utils.NonceLeafKey) + for i := utils.BasicDataLeafKey; i <= utils.CodeHashLeafKey; i++ { + aw.touchAddressAndChargeGas(originAddr, zeroTreeIndex, byte(i), i == utils.BasicDataLeafKey) } // Kaustinen note: we're currently experimenting with stop chargin gas for the origin address @@ -136,14 +133,10 @@ func (aw *AccessWitness) TouchTxOriginAndComputeGas(originAddr []byte) uint64 { } func (aw *AccessWitness) TouchTxExistingAndComputeGas(targetAddr []byte, sendsValue bool) uint64 { - aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.VersionLeafKey, false) - aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.CodeSizeLeafKey, false) + aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, false) aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.CodeHashLeafKey, false) - aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.NonceLeafKey, false) if sendsValue { - aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, true) - } else { - aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, false) + aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true) } // Kaustinen note: we're currently experimenting with stop chargin gas for the origin address @@ -158,6 +151,23 @@ func (aw *AccessWitness) TouchSlotAndChargeGas(addr []byte, slot common.Hash, is return aw.touchAddressAndChargeGas(addr, *treeIndex, subIndex, isWrite) } +func AppendBytesToFile(filename string, bytes []byte) error { + // Open or create file for writing; append data if file exists + file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer file.Close() + + // Write bytes to file + _, err = file.Write(bytes) + if err != nil { + return err + } + + return nil +} + func (aw *AccessWitness) touchAddressAndChargeGas(addr []byte, treeIndex uint256.Int, subIndex byte, isWrite bool) uint64 { stemRead, selectorRead, stemWrite, selectorWrite, selectorFill := aw.touchAddress(addr, treeIndex, subIndex, isWrite) @@ -178,7 +188,19 @@ func (aw *AccessWitness) touchAddressAndChargeGas(addr []byte, treeIndex uint256 gas += params.WitnessChunkFillCost } - return gas + var record [1 + 20 + 32 + 1 + 1]byte + record[0] = 0 + copy(record[1:21], addr) + copy(record[21:53], treeIndex.Bytes()) + record[53] = subIndex + if isWrite { + record[54] = 1 + } + if err := AppendBytesToFile("gas.log", record[:]); err != nil { + panic(err) + } + + return 0 } // touchAddress adds any missing access event to the witness. @@ -276,20 +298,8 @@ func (aw *AccessWitness) TouchCodeChunksRangeAndChargeGas(contractAddr []byte, s return statelessGasCharged } -func (aw *AccessWitness) TouchVersion(addr []byte, isWrite bool) uint64 { - return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.VersionLeafKey, isWrite) -} - -func (aw *AccessWitness) TouchBalance(addr []byte, isWrite bool) uint64 { - return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, isWrite) -} - -func (aw *AccessWitness) TouchNonce(addr []byte, isWrite bool) uint64 { - return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.NonceLeafKey, isWrite) -} - -func (aw *AccessWitness) TouchCodeSize(addr []byte, isWrite bool) uint64 { - return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.CodeSizeLeafKey, isWrite) +func (aw *AccessWitness) TouchBasicData(addr []byte, isWrite bool) uint64 { + return aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, isWrite) } func (aw *AccessWitness) TouchCodeHash(addr []byte, isWrite bool) uint64 { diff --git a/core/state/database.go b/core/state/database.go index 826c03cd9f0..ce3fa5a55e4 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -141,7 +141,7 @@ type Trie interface { // UpdateAccount abstracts an account write to the trie. It encodes the // provided account object with associated algorithm and then updates it // in the trie with provided address. - UpdateAccount(address common.Address, account *types.StateAccount) error + UpdateAccount(address common.Address, account *types.StateAccount, codelen int) error // UpdateContractCode abstracts code write to the trie. It is expected // to be moved to the stateWriter interface when the latter is ready. @@ -312,7 +312,6 @@ type cachingDB struct { // Transition-specific fields // TODO ensure that this info is in the DB - LastMerkleRoot common.Hash // root hash of the read-only base tree CurrentTransitionState *TransitionState TransitionStatePerRoot lru.BasicLRU[common.Hash, *TransitionState] transitionStateLock sync.Mutex @@ -349,7 +348,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { mpt Trie err error ) - fmt.Printf("opening trie with root %x, %v %v\n", root, db.InTransition(), db.Transitioned()) + // fmt.Printf("opening trie with root %x, %v %v\n", root, db.InTransition(), db.Transitioned()) // TODO separate both cases when I can be certain that it won't // find a Verkle trie where is expects a Transitoion trie. @@ -415,8 +414,8 @@ func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre } } if db.InTransition() { - fmt.Printf("OpenStorageTrie during transition, state root=%x root=%x\n", stateRoot, root) - mpt, err := db.openStorageMPTrie(db.LastMerkleRoot, address, root, nil) + // fmt.Printf("OpenStorageTrie during transition, state root=%x root=%x\n", stateRoot, root) + mpt, err := db.openStorageMPTrie(db.baseRoot, address, root, nil) if err != nil { return nil, err } @@ -548,7 +547,7 @@ func (db *cachingDB) AddRootTranslation(originalRoot, translatedRoot common.Hash } func (db *cachingDB) SetLastMerkleRoot(merkleRoot common.Hash) { - db.LastMerkleRoot = merkleRoot + db.baseRoot = merkleRoot } func (db *cachingDB) SaveTransitionState(root common.Hash) { diff --git a/core/state/statedb.go b/core/state/statedb.go index 4f64d19f4a3..0912bc54b1f 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -177,6 +177,8 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) sdb.witness = sdb.NewAccessWitness() } if sdb.snaps != nil { + // if sdb.snap = sdb.snaps.Snapshot(root); sdb.snap == nil { + // } sdb.snap = sdb.snaps.Snapshot(root) } return sdb, nil @@ -576,7 +578,7 @@ func (s *StateDB) updateStateObject(obj *stateObject) { } // Encode the account and update the account trie addr := obj.Address() - if err := s.trie.UpdateAccount(addr, &obj.data); err != nil { + if err := s.trie.UpdateAccount(addr, &obj.data, len(obj.code)); err != nil { s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err)) } if obj.dirtyCode { diff --git a/core/state_processor.go b/core/state_processor.go index d6a01673c6a..a4aa1775880 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -21,7 +21,9 @@ import ( "errors" "fmt" "math/big" + "os" + "github.com/davecgh/go-spew/spew" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" @@ -29,8 +31,13 @@ import ( "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/logger" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" + "github.com/ethereum/go-ethereum/trie/utils" + "github.com/ethereum/go-verkle" + "github.com/pk910/dynamic-ssz" ) // StateProcessor is a basic Processor, which takes care of transitioning @@ -85,14 +92,37 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } else { ProcessParentBlockHash(statedb, block.NumberU64()-1, block.ParentHash()) } + + // var record [1 + 8]byte + // record[0] = 1 + // binary.LittleEndian.PutUint64(record[1:], block.NumberU64()) + // state.AppendBytesToFile("gas.log", record[:]) } // Iterate over and process the individual transactions for i, tx := range block.Transactions() { + // var record [1 + 32]byte + // record[0] = 2 + // copy(record[1:], tx.Hash().Bytes()) + // state.AppendBytesToFile("gas.log", record[:]) msg, err := TransactionToMessage(tx, signer, header.BaseFee) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } statedb.SetTxContext(tx.Hash(), i) + thash := tx.Hash() + if thash[0] == 0xe5 && thash[1] == 0x5a && thash[2] == 0x21 && thash[3] == 0x50 { + file, err := os.Create("bug.json") + if err != nil { + panic(err) + } + defer file.Close() + vmenv.Config.Tracer = logger.NewJSONLogger(&logger.Config{ + EnableMemory: true, + EnableReturnData: true, + }, file) + } else { + vmenv.Config.Tracer = nil + } receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) @@ -109,6 +139,89 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), withdrawals) + header.Root = statedb.IntermediateRoot(true) + // Associate current conversion state to computed state + // root and store it in the database for later recovery. + statedb.Database().SaveTransitionState(header.Root) + + var ( + proof *verkle.VerkleProof + statediff verkle.StateDiff + keys = statedb.Witness().Keys() + ) + // Open the pre-tree to prove the pre-state against + parent := p.bc.GetHeaderByNumber(header.Number.Uint64() - 1) + if parent == nil { + return nil, nil, 0, fmt.Errorf("nil parent header for block %d", header.Number) + } + + // Load transition state at beginning of block, because + // OpenTrie needs to know what the conversion status is. + // statedb.Database().LoadTransitionState(parent.Root) + + preTrie, err := statedb.Database().OpenTrie(parent.Root) + if err != nil { + return nil, nil, 0, fmt.Errorf("error opening pre-state tree root: %w", err) + } + // statedb.Database().LoadTransitionState(header.Root) + + var okpre, okpost bool + var vtrpre, vtrpost *trie.VerkleTrie + switch pre := preTrie.(type) { + case *trie.VerkleTrie: + vtrpre, okpre = preTrie.(*trie.VerkleTrie) + switch tr := statedb.GetTrie().(type) { + case *trie.VerkleTrie: + vtrpost = tr + okpost = true + // This is to handle a situation right at the start of the conversion: + // the post trie is a transition tree when the pre tree is an empty + // verkle tree. + case *trie.TransitionTrie: + vtrpost = tr.Overlay() + okpost = true + default: + okpost = false + } + case *trie.TransitionTrie: + vtrpre = pre.Overlay() + okpre = true + post, _ := statedb.GetTrie().(*trie.TransitionTrie) + vtrpost = post.Overlay() + okpost = true + default: + // This should only happen for the first block of the + // conversion, when the previous tree is a merkle tree. + // Logically, the "previous" verkle tree is an empty tree. + okpre = true + vtrpre = trie.NewVerkleTrie(verkle.New(), statedb.Database().TrieDB(), utils.NewPointCache(), false) + post := statedb.GetTrie().(*trie.TransitionTrie) + vtrpost = post.Overlay() + okpost = true + } + if okpre && okpost { + if len(keys) > 0 { + proof, statediff, err = trie.ProveAndSerialize(vtrpre, vtrpost, keys, vtrpre.FlatdbNodeResolver) + if err != nil { + return nil, nil, 0, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err) + } + } + + ew := types.ExecutionWitness{StateDiff: statediff, VerkleProof: proof} + encoder := dynssz.NewDynSsz(map[string]any{}) + encoded, err := encoder.MarshalSSZ(&ew) + if err != nil { + spew.Dump(ew) + panic(err) + } + state.AppendBytesToFile("witness_size.csv", []byte(fmt.Sprintf("%d,%d\n", header.Number, len(encoded)))) + if header.Number.Uint64()%10000 == 0 { + data := make([]byte, 8+len(encoded)) + copy(data[8:], encoded) + binary.LittleEndian.PutUint64(data[:8], block.NumberU64()) + state.AppendBytesToFile("witnesses.ssz", data) + } + } if block.NumberU64()%100 == 0 { stateRoot := statedb.GetTrie().Hash() log.Info("State root", "number", block.NumberU64(), "hash", stateRoot) @@ -176,6 +289,16 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo } // Create a new context to be used in the EVM environment blockContext := NewEVMBlockContext(header, bc, author) + istarget := blockContext.BlockNumber.Uint64() == 17366216 + if istarget { + tracer := logger.NewStructLogger(&logger.Config{ + Debug: istarget, + DisableStorage: !istarget, + //EnableMemory: false, + EnableReturnData: istarget, + }) + cfg.Tracer = tracer + } vmenv := vm.NewEVM(blockContext, vm.TxContext{BlobHashes: tx.BlobHashes()}, statedb, config, cfg) return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) } @@ -185,7 +308,7 @@ func InsertBlockHashHistoryAtEip2935Fork(statedb *state.StateDB, prevNumber uint statedb.Witness().TouchFullAccount(params.HistoryStorageAddress[:], true) ancestor := chain.GetHeader(prevHash, prevNumber) - for i := prevNumber; i > 0 && i >= prevNumber-params.Eip2935BlockHashHistorySize; i-- { + for i := prevNumber; i > 0 && i > prevNumber-params.Eip2935BlockHashHistorySize; i-- { ProcessParentBlockHash(statedb, i, ancestor.Hash()) ancestor = chain.GetHeader(ancestor.ParentHash, ancestor.Number.Uint64()-1) } diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index e61b464c062..9a8f01971a7 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -61,6 +61,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter { case evm.chainRules.IsPrague: // TODO replace with proper instruction set when fork is specified table = &shanghaiInstructionSet + // EnableEIP(4762, table) case evm.chainRules.IsShanghai: table = &shanghaiInstructionSet case evm.chainRules.IsMerge: diff --git a/core/vm/operations_verkle.go b/core/vm/operations_verkle.go index 8b55b83bb21..d748698c6b5 100644 --- a/core/vm/operations_verkle.go +++ b/core/vm/operations_verkle.go @@ -40,7 +40,7 @@ func gasSLoad4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { address := stack.peek().Bytes20() - gas := evm.Accesses.TouchBalance(address[:], false) + gas := evm.Accesses.TouchBasicData(address[:], false) if gas == 0 { gas = params.WarmStorageReadCostEIP2929 } @@ -52,8 +52,7 @@ func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, if _, isPrecompile := evm.precompile(address); isPrecompile { return 0, nil } - wgas := evm.Accesses.TouchVersion(address[:], false) - wgas += evm.Accesses.TouchCodeSize(address[:], false) + wgas := evm.Accesses.TouchBasicData(address[:], false) if wgas == 0 { wgas = params.WarmStorageReadCostEIP2929 } @@ -103,24 +102,15 @@ func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Mem } contractAddr := contract.Address() - statelessGas := evm.Accesses.TouchVersion(contractAddr[:], false) - statelessGas += evm.Accesses.TouchCodeSize(contractAddr[:], false) - statelessGas += evm.Accesses.TouchBalance(contractAddr[:], false) + statelessGas := evm.Accesses.TouchBasicData(contractAddr[:], false) if contractAddr != beneficiaryAddr { - statelessGas += evm.Accesses.TouchBalance(beneficiaryAddr[:], false) + statelessGas += evm.Accesses.TouchBasicData(beneficiaryAddr[:], false) } // Charge write costs if it transfers value if evm.StateDB.GetBalance(contractAddr).Sign() != 0 { - statelessGas += evm.Accesses.TouchBalance(contractAddr[:], true) + statelessGas += evm.Accesses.TouchBasicData(contractAddr[:], true) if contractAddr != beneficiaryAddr { - statelessGas += evm.Accesses.TouchBalance(beneficiaryAddr[:], true) - } - - // Case when the beneficiary does not exist: touch the account - // but leave code hash and size alone. - if evm.StateDB.Empty(beneficiaryAddr) { - statelessGas += evm.Accesses.TouchVersion(beneficiaryAddr[:], true) - statelessGas += evm.Accesses.TouchNonce(beneficiaryAddr[:], true) + statelessGas += evm.Accesses.TouchBasicData(beneficiaryAddr[:], true) } } return statelessGas, nil @@ -133,8 +123,7 @@ func gasExtCodeCopyEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memo return 0, err } addr := common.Address(stack.peek().Bytes20()) - wgas := evm.Accesses.TouchVersion(addr[:], false) - wgas += evm.Accesses.TouchCodeSize(addr[:], false) + wgas := evm.Accesses.TouchBasicData(addr[:], false) if wgas == 0 { wgas = params.WarmStorageReadCostEIP2929 } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index 759e3a4dd38..04db6cc596f 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -81,11 +81,12 @@ func BenchmarkTransactionTrace(b *testing.B) { } _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false) // Create the tracer, the EVM environment and run it + istarget := context.BlockNumber.Uint64() == 17366216 tracer := logger.NewStructLogger(&logger.Config{ - Debug: false, - //DisableStorage: true, + Debug: istarget, + DisableStorage: !istarget, //EnableMemory: false, - //EnableReturnData: false, + EnableReturnData: istarget, }) evm := vm.NewEVM(context, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer}) msg, err := core.TransactionToMessage(tx, signer, nil) diff --git a/go.mod b/go.mod index 3f7010a4989..17550108835 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/docker/docker v1.6.2 github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 github.com/ethereum/c-kzg-4844 v0.3.0 - github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 + github.com/ethereum/go-verkle v0.1.1-0.20240726192638-722a15c2a2b2 github.com/fatih/color v1.7.0 github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 @@ -53,6 +53,7 @@ require ( github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 + github.com/pk910/dynamic-ssz v0.0.4 github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7 github.com/rs/cors v1.7.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible @@ -63,11 +64,11 @@ require ( github.com/tyler-smith/go-bip39 v1.1.0 github.com/urfave/cli/v2 v2.24.1 go.uber.org/automaxprocs v1.5.2 - golang.org/x/crypto v0.10.0 + golang.org/x/crypto v0.17.0 golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc - golang.org/x/sync v0.4.0 - golang.org/x/sys v0.13.0 - golang.org/x/text v0.10.0 + golang.org/x/sync v0.7.0 + golang.org/x/sys v0.22.0 + golang.org/x/text v0.14.0 golang.org/x/time v0.3.0 golang.org/x/tools v0.9.1 gopkg.in/natefinch/lumberjack.v2 v2.0.0 @@ -86,7 +87,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect github.com/aws/smithy-go v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect @@ -129,6 +130,7 @@ require ( golang.org/x/net v0.10.0 // indirect golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/Knetic/govaluate.v3 v3.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 6b0fd1e7566..136c6f243e2 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= -github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= +github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= @@ -127,10 +127,10 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.3.0 h1:3Y3hD6l5i0dEYsBL50C+Om644kve3pNqoAcvE26o9zI= github.com/ethereum/c-kzg-4844 v0.3.0/go.mod h1:WI2Nd82DMZAAZI1wV2neKGost9EKjvbpQR9OqE5Qqa8= -github.com/ethereum/go-verkle v0.1.1-0.20240306114018-819f7d81e58c h1:+6lz/7jTYZSgL+I3guRRRqnD23ICKjEMvxVTgJw3P00= -github.com/ethereum/go-verkle v0.1.1-0.20240306114018-819f7d81e58c/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w= -github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 h1:KrE8I4reeVvf7C1tm8elRjj4BdscTYzz/WAbYyf/JI4= -github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w= +github.com/ethereum/go-verkle v0.1.1-0.20240719075547-25ea5ac29590 h1:SA8WB1r8TntvXH2EdSovW6xFnrobu6sKYDXIPdRbzt8= +github.com/ethereum/go-verkle v0.1.1-0.20240719075547-25ea5ac29590/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w= +github.com/ethereum/go-verkle v0.1.1-0.20240726192638-722a15c2a2b2 h1:TyI8W45Rkgznwsq5NaVPib7iEsIKwmM60og7TCmbi2A= +github.com/ethereum/go-verkle v0.1.1-0.20240726192638-722a15c2a2b2/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -371,6 +371,8 @@ github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQm github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pk910/dynamic-ssz v0.0.4 h1:DT29+1055tCEPCaR4V/ez+MOKW7BzBsmjyFvBRqx0ME= +github.com/pk910/dynamic-ssz v0.0.4/go.mod h1:b6CrLaB2X7pYA+OSEEbkgXDEcRnjLOZIxZTsMuO/Y9c= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -477,8 +479,8 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= @@ -531,8 +533,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -571,8 +573,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -584,8 +586,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= @@ -639,6 +641,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/Knetic/govaluate.v3 v3.0.0 h1:18mUyIt4ZlRlFZAAfVetz4/rzlJs9yhN+U02F4u1AOc= +gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/light/trie.go b/light/trie.go index 7e7c03bc16c..f29e67a5da7 100644 --- a/light/trie.go +++ b/light/trie.go @@ -223,7 +223,7 @@ func (t *odrTrie) GetAccount(address common.Address) (*types.StateAccount, error return acct, nil } -func (t *odrTrie) UpdateAccount(address common.Address, acc *types.StateAccount) error { +func (t *odrTrie) UpdateAccount(address common.Address, acc *types.StateAccount, _ int) error { key := crypto.Keccak256(address.Bytes()) value, err := rlp.EncodeToBytes(acc) if err != nil { diff --git a/params/config.go b/params/config.go index 6c9e95197fd..bf8ef84bf69 100644 --- a/params/config.go +++ b/params/config.go @@ -830,8 +830,8 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules IsPetersburg: c.IsPetersburg(num), IsIstanbul: c.IsIstanbul(num), IsBerlin: c.IsBerlin(num), - IsEIP2929: c.IsBerlin(num) && !c.IsPrague(num, timestamp), - IsEIP4762: c.IsPrague(num, timestamp), + IsEIP2929: c.IsBerlin(num), // && !c.IsPrague(num, timestamp), + IsEIP4762: false, //c.IsPrague(num, timestamp), IsLondon: c.IsLondon(num), IsMerge: isMerge, IsShanghai: c.IsShanghai(num, timestamp), diff --git a/trie/secure_trie.go b/trie/secure_trie.go index f4a999c2f68..9198f595796 100644 --- a/trie/secure_trie.go +++ b/trie/secure_trie.go @@ -163,7 +163,7 @@ func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error { } // UpdateAccount will abstract the write of an account to the secure trie. -func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount) error { +func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount, _ int) error { hk := t.hashKey(address.Bytes()) data, err := rlp.EncodeToBytes(acc) if err != nil { diff --git a/trie/transition.go b/trie/transition.go index 0fe19733652..87242fa416b 100644 --- a/trie/transition.go +++ b/trie/transition.go @@ -113,11 +113,11 @@ func (t *TransitionTrie) UpdateStorage(address common.Address, key []byte, value } // UpdateAccount abstract an account write to the trie. -func (t *TransitionTrie) UpdateAccount(addr common.Address, account *types.StateAccount) error { +func (t *TransitionTrie) UpdateAccount(addr common.Address, account *types.StateAccount, codelen int) error { if account.Root != (common.Hash{}) && account.Root != types.EmptyRootHash { t.overlay.db.SetStorageRootConversion(addr, account.Root) } - return t.overlay.UpdateAccount(addr, account) + return t.overlay.UpdateAccount(addr, account, codelen) } // Delete removes any existing value for key from the trie. If a node was not diff --git a/trie/utils/verkle.go b/trie/utils/verkle.go index ad6184baa99..4cdbffb774b 100644 --- a/trie/utils/verkle.go +++ b/trie/utils/verkle.go @@ -24,11 +24,13 @@ import ( ) const ( - VersionLeafKey = 0 - BalanceLeafKey = 1 - NonceLeafKey = 2 - CodeHashLeafKey = 3 - CodeSizeLeafKey = 4 + BasicDataLeafKey = 0 + CodeHashLeafKey = 1 + + BasicDataVersionOffset = 0 + BasicDataCodeSizeOffset = 4 + BasicDataNonceOffset = 8 + BasicDataBalanceOffset = 16 maxPointCacheByteSize = 100 << 20 ) @@ -72,7 +74,7 @@ func (pc *PointCache) GetTreeKeyHeader(addr []byte) *verkle.Point { func (pc *PointCache) GetTreeKeyVersionCached(addr []byte) []byte { p := pc.GetTreeKeyHeader(addr) - v := PointToHash(p, VersionLeafKey) + v := PointToHash(p, BasicDataLeafKey) return v[:] } @@ -134,29 +136,17 @@ func GetTreeKeyAccountLeaf(address []byte, leaf byte) []byte { } func GetTreeKeyVersion(address []byte) []byte { - return GetTreeKey(address, zero, VersionLeafKey) + return GetTreeKey(address, zero, BasicDataLeafKey) } func GetTreeKeyVersionWithEvaluatedAddress(addrp *verkle.Point) []byte { - return GetTreeKeyWithEvaluatedAddess(addrp, zero, VersionLeafKey) -} - -func GetTreeKeyBalance(address []byte) []byte { - return GetTreeKey(address, zero, BalanceLeafKey) -} - -func GetTreeKeyNonce(address []byte) []byte { - return GetTreeKey(address, zero, NonceLeafKey) + return GetTreeKeyWithEvaluatedAddess(addrp, zero, BasicDataLeafKey) } func GetTreeKeyCodeKeccak(address []byte) []byte { return GetTreeKey(address, zero, CodeHashLeafKey) } -func GetTreeKeyCodeSize(address []byte) []byte { - return GetTreeKey(address, zero, CodeSizeLeafKey) -} - func GetTreeKeyCodeChunk(address []byte, chunk *uint256.Int) []byte { treeIndex, subIndex := GetTreeKeyCodeChunkIndices(chunk) return GetTreeKey(address, treeIndex, subIndex) diff --git a/trie/verkle.go b/trie/verkle.go index 2615180d21e..f63cb0e8952 100644 --- a/trie/verkle.go +++ b/trie/verkle.go @@ -115,11 +115,6 @@ func (t *VerkleTrie) GetAccount(addr common.Address) (*types.StateAccount, error return nil, fmt.Errorf("GetAccount (%x) error: %v", addr, err) } - // The following code is required for the MPT->VKT conversion. - // An account can be partially migrated, where storage slots were moved to the VKT - // but not yet the account. This means some account information as (header) storage slots - // are in the VKT but basic account information must be read in the base tree (MPT). - // TODO: we can simplify this logic depending if the conversion is in progress or finished. emptyAccount := true for i := 0; values != nil && i <= utils.CodeHashLeafKey && emptyAccount; i++ { emptyAccount = emptyAccount && values[i] == nil @@ -128,62 +123,49 @@ func (t *VerkleTrie) GetAccount(addr common.Address) (*types.StateAccount, error return nil, nil } - if len(values[utils.NonceLeafKey]) > 0 { - acc.Nonce = binary.LittleEndian.Uint64(values[utils.NonceLeafKey]) + if len(values[utils.BasicDataLeafKey]) > 0 { + acc.Nonce = binary.BigEndian.Uint64(values[utils.BasicDataLeafKey][utils.BasicDataNonceOffset:]) } // if the account has been deleted, then values[10] will be 0 and not nil. If it has // been recreated after that, then its code keccak will NOT be 0. So return `nil` if // the nonce, and values[10], and code keccak is 0. - if acc.Nonce == 0 && len(values) > 10 && len(values[10]) > 0 && bytes.Equal(values[utils.CodeHashLeafKey], zero[:]) { + // XXX voir si effectivement de detruis tout + if bytes.Equal(values[utils.BasicDataLeafKey], zero[:]) && len(values) > 10 && len(values[10]) > 0 && bytes.Equal(values[utils.CodeHashLeafKey], zero[:]) { if !t.ended { return nil, errDeletedAccount } else { return nil, nil } } - var balance [32]byte - copy(balance[:], values[utils.BalanceLeafKey]) - for i := 0; i < len(balance)/2; i++ { - balance[len(balance)-i-1], balance[i] = balance[i], balance[len(balance)-i-1] - } - // var balance [32]byte - // if len(values[utils.BalanceLeafKey]) > 0 { - // for i := 0; i < len(balance); i++ { - // balance[len(balance)-i-1] = values[utils.BalanceLeafKey][i] - // } - // } + var balance [16]byte + copy(balance[:], values[utils.BasicDataLeafKey][utils.BasicDataBalanceOffset:]) acc.Balance = new(big.Int).SetBytes(balance[:]) acc.CodeHash = values[utils.CodeHashLeafKey] - // TODO fix the code size as well return acc, nil } var zero [32]byte -func (t *VerkleTrie) UpdateAccount(addr common.Address, acc *types.StateAccount) error { +func (t *VerkleTrie) UpdateAccount(addr common.Address, acc *types.StateAccount, codelen int) error { var ( - err error - nonce, balance [32]byte - values = make([][]byte, verkle.NodeWidth) - stem = t.pointCache.GetTreeKeyVersionCached(addr[:]) + err error + basicData [32]byte + values = make([][]byte, verkle.NodeWidth) + stem = t.pointCache.GetTreeKeyVersionCached(addr[:]) ) - // Only evaluate the polynomial once - values[utils.VersionLeafKey] = zero[:] - values[utils.NonceLeafKey] = nonce[:] - values[utils.BalanceLeafKey] = balance[:] + binary.BigEndian.PutUint32(basicData[utils.BasicDataCodeSizeOffset:], uint32(codelen)) + binary.BigEndian.PutUint64(basicData[utils.BasicDataNonceOffset:], acc.Nonce) + // get the lower 16 bytes of water and change its endianness + balanceBytes := acc.Balance.Bytes() + copy(basicData[32-len(balanceBytes):], balanceBytes[:]) + // XXX overwrite code size if present and not updated + // this will happen e.g. when updating the balance + values[utils.BasicDataLeafKey] = basicData[:] values[utils.CodeHashLeafKey] = acc.CodeHash[:] - binary.LittleEndian.PutUint64(nonce[:], acc.Nonce) - bbytes := acc.Balance.Bytes() - if len(bbytes) > 0 { - for i, b := range bbytes { - balance[len(bbytes)-i-1] = b - } - } - switch root := t.root.(type) { case *verkle.InternalNode: err = root.InsertValuesAtStem(stem, values, t.FlatdbNodeResolver) @@ -193,7 +175,6 @@ func (t *VerkleTrie) UpdateAccount(addr common.Address, acc *types.StateAccount) if err != nil { return fmt.Errorf("UpdateAccount (%x) error: %v", addr, err) } - // TODO figure out if the code size needs to be updated, too return nil } @@ -259,6 +240,11 @@ func (trie *VerkleTrie) Hash() common.Hash { return trie.root.Commit().Bytes() } +func nodeToDBKey(n verkle.VerkleNode) []byte { + ret := n.Commitment().Bytes() + return ret[:] +} + // Commit writes all nodes to the trie's memory database, tracking the internal // and external (for account tries) references. func (trie *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) { @@ -339,6 +325,7 @@ func ProveAndSerialize(pretrie, posttrie *VerkleTrie, keys [][]byte, resolver ve } func DeserializeAndVerifyVerkleProof(vp *verkle.VerkleProof, preStateRoot []byte, postStateRoot []byte, statediff verkle.StateDiff) error { + panic("pas appele j'espere") // TODO: check that `OtherStems` have expected length and values. proof, err := verkle.DeserializeProof(vp, statediff) @@ -354,27 +341,105 @@ func DeserializeAndVerifyVerkleProof(vp *verkle.VerkleProof, preStateRoot []byte } // TODO this should not be necessary, remove it // after the new proof generation code has stabilized. - for _, stemdiff := range statediff { - for _, suffixdiff := range stemdiff.SuffixDiffs { - var key [32]byte - copy(key[:31], stemdiff.Stem[:]) - key[31] = suffixdiff.Suffix + // for _, stemdiff := range statediff { + // method 1 + // for i, suffix := range stemdiff.Suffixes { + // var key [32]byte + // copy(key[:31], stemdiff.Stem[:]) + // key[31] = suffix + + // val, err := pretree.Get(key[:], nil) + // if err != nil { + // return fmt.Errorf("could not find key %x in tree rebuilt from proof: %w", key, err) + // } + // if len(val) > 0 { + // if !bytes.Equal(val, stemdiff.Current[i]) { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.Current[i]) + // } + // } else { + // if stemdiff.Current[i] != nil && len(stemdiff.Current[i]) != 0 { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.Current[i]) + // } + // } + // } - val, err := pretree.Get(key[:], nil) - if err != nil { - return fmt.Errorf("could not find key %x in tree rebuilt from proof: %w", key, err) - } - if len(val) > 0 { - if !bytes.Equal(val, suffixdiff.CurrentValue[:]) { - return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, *suffixdiff.CurrentValue) - } - } else { - if suffixdiff.CurrentValue != nil && len(suffixdiff.CurrentValue) != 0 { - return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, *suffixdiff.CurrentValue) - } - } - } - } + // method 2 + // for i, suffix := range stemdiff.ReadSuffixes { + // var key [32]byte + // copy(key[:31], stemdiff.Stem[:]) + // key[31] = suffix + // val, err := pretree.Get(key[:], nil) + // if err != nil { + // return fmt.Errorf("could not find key %x in tree rebuilt from proof: %w", key, err) + // } + // if len(val) > 0 { + // if !bytes.Equal(val, stemdiff.ReadCurrent[i]) { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.ReadCurrent[i]) + // } + // } else { + // if stemdiff.ReadCurrent[i] != nil && len(stemdiff.ReadCurrent[i]) != 0 { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.ReadCurrent[i]) + // } + // } + // } + // for i, suffix := range stemdiff.UpdatedSuffixes { + // var key [32]byte + // copy(key[:31], stemdiff.Stem[:]) + // key[31] = suffix + // val, err := pretree.Get(key[:], nil) + // if err != nil { + // return fmt.Errorf("could not find key %x in tree rebuilt from proof: %w", key, err) + // } + // if len(val) > 0 { + // if !bytes.Equal(val, stemdiff.UpdatedCurrent[i]) { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.UpdatedCurrent[i]) + // } + // } else { + // if stemdiff.UpdatedCurrent[i] != nil && len(stemdiff.UpdatedCurrent[i]) != 0 { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.UpdatedCurrent[i]) + // } + // } + // } + + // method 3 + // for i, suffix := range stemdiff.ReadSuffixes { + // var key [32]byte + // copy(key[:31], stemdiff.Stem[:]) + // key[31] = suffix + // val, err := pretree.Get(key[:], nil) + // if err != nil { + // return fmt.Errorf("could not find key %x in tree rebuilt from proof: %w", key, err) + // } + // if len(val) > 0 { + // if !bytes.Equal(val, stemdiff.ReadCurrent[i]) { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.ReadCurrent[i]) + // } + // } else { + // if stemdiff.ReadCurrent[i] != nil && len(stemdiff.ReadCurrent[i]) != 0 { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.ReadCurrent[i]) + // } + // } + // } + // for i, suffix := range stemdiff.UpdatedSuffixes { + // var key [32]byte + // copy(key[:31], stemdiff.Stem[:]) + // key[31] = suffix + // val, err := pretree.Get(key[:], nil) + // if err != nil { + // return fmt.Errorf("could not find key %x in tree rebuilt from proof: %w", key, err) + // } + // if len(val) > 0 { + // if !bytes.Equal(val, stemdiff.UpdatedCurrent[i]) { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.UpdatedCurrent[i]) + // } + // } else { + // if stemdiff.UpdatedCurrent[i] != nil && len(stemdiff.UpdatedCurrent[i]) != 0 { + // return fmt.Errorf("could not find correct value at %x in tree rebuilt from proof: %x != %x", key, val, stemdiff.UpdatedCurrent[i]) + // } + // } + // } + + // } // TODO: this is necessary to verify that the post-values are the correct ones. // But all this can be avoided with a even faster way. The EVM block execution can @@ -481,13 +546,6 @@ func (t *VerkleTrie) UpdateContractCode(addr common.Address, codeHash common.Has } values[groupOffset] = chunks[i : i+32] - // Reuse the calculated key to also update the code size. - if i == 0 { - cs := make([]byte, 32) - binary.LittleEndian.PutUint64(cs, uint64(len(code))) - values[utils.CodeSizeLeafKey] = cs - } - if groupOffset == 255 || len(chunks)-i <= 32 { err = t.UpdateStem(key[:31], values) diff --git a/trie/verkle_iterator_test.go b/trie/verkle_iterator_test.go index d1611feee32..a903427430a 100644 --- a/trie/verkle_iterator_test.go +++ b/trie/verkle_iterator_test.go @@ -37,7 +37,7 @@ func TestVerkleIterator(t *testing.T) { } // NOTE: the code size isn't written to the trie via TryUpdateAccount // so it will be missing from the test nodes. - trie.UpdateAccount(common.Address{}, account0) + trie.UpdateAccount(common.Address{}, account0, 0) account1 := &types.StateAccount{ Nonce: 1337, Balance: big.NewInt(2000), @@ -46,7 +46,7 @@ func TestVerkleIterator(t *testing.T) { } // This address is meant to hash to a value that has the same first byte as 0xbf var clash = common.HexToAddress("69fd8034cdb20934dedffa7dccb4fb3b8062a8be") - trie.UpdateAccount(clash, account1) + trie.UpdateAccount(clash, account1, 0) // Manually go over every node to check that we get all // the correct nodes.