Skip to content

Commit ff1037f

Browse files
gballetjsignrjl493456442holiman
authored andcommitted
core, trie: verkle state processor tests (ethereum#30672)
Tests that are crucial to for verifying the verkle testnet functions properly. --------- Signed-off-by: Guillaume Ballet <[email protected]> Co-authored-by: Ignacio Hagopian <[email protected]> Co-authored-by: Gary Rong <[email protected]> Co-authored-by: Martin HS <[email protected]>
1 parent 8eab259 commit ff1037f

File tree

7 files changed

+1142
-224
lines changed

7 files changed

+1142
-224
lines changed

consensus/beacon/consensus.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,21 +398,25 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
398398
if parent == nil {
399399
return nil, fmt.Errorf("nil parent header for block %d", header.Number)
400400
}
401-
402401
preTrie, err := state.Database().OpenTrie(parent.Root)
403402
if err != nil {
404403
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
405404
}
406-
407405
vktPreTrie, okpre := preTrie.(*trie.VerkleTrie)
408406
vktPostTrie, okpost := state.GetTrie().(*trie.VerkleTrie)
407+
408+
// The witness is only attached iff both parent and current block are
409+
// using verkle tree.
409410
if okpre && okpost {
410411
if len(keys) > 0 {
411-
verkleProof, stateDiff, err := vktPreTrie.Proof(vktPostTrie, keys, vktPreTrie.FlatdbNodeResolver)
412+
verkleProof, stateDiff, err := vktPreTrie.Proof(vktPostTrie, keys)
412413
if err != nil {
413414
return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
414415
}
415-
block = block.WithWitness(&types.ExecutionWitness{StateDiff: stateDiff, VerkleProof: verkleProof})
416+
block = block.WithWitness(&types.ExecutionWitness{
417+
StateDiff: stateDiff,
418+
VerkleProof: verkleProof,
419+
})
416420
}
417421
}
418422
}

core/state/access_events.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func (ae *AccessEvents) ValueTransferGas(callerAddr, targetAddr common.Address)
117117
return gas
118118
}
119119

120-
// ContractCreateCPreheck charges access costs before
120+
// ContractCreatePreCheckGas charges access costs before
121121
// a contract creation is initiated. It is just reads, because the
122122
// address collision is done before the transfer, and so no write
123123
// are guaranteed to happen at this point.

core/state/statedb.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,8 @@ func (s *StateDB) handleDestruction() (map[common.Hash]*accountDelete, []*trieno
10681068
deletes[addrHash] = op
10691069

10701070
// Short circuit if the origin storage was empty.
1071-
if prev.Root == types.EmptyRootHash {
1071+
1072+
if prev.Root == types.EmptyRootHash || s.db.TrieDB().IsVerkle() {
10721073
continue
10731074
}
10741075
// Remove storage slots belonging to the account.

core/state_processor_test.go

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

1919
import (
2020
"crypto/ecdsa"
21-
"encoding/binary"
2221
"math"
2322
"math/big"
2423
"testing"
@@ -30,14 +29,11 @@ import (
3029
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
3130
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
3231
"github.com/ethereum/go-ethereum/core/rawdb"
33-
"github.com/ethereum/go-ethereum/core/state"
3432
"github.com/ethereum/go-ethereum/core/types"
3533
"github.com/ethereum/go-ethereum/core/vm"
3634
"github.com/ethereum/go-ethereum/crypto"
3735
"github.com/ethereum/go-ethereum/params"
3836
"github.com/ethereum/go-ethereum/trie"
39-
"github.com/ethereum/go-ethereum/triedb"
40-
"github.com/ethereum/go-verkle"
4137
"github.com/holiman/uint256"
4238
"golang.org/x/crypto/sha3"
4339
)
@@ -426,193 +422,3 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
426422
}
427423
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))
428424
}
429-
430-
var (
431-
code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`)
432-
intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, true, true, true, true)
433-
// A contract creation that calls EXTCODECOPY in the constructor. Used to ensure that the witness
434-
// will not contain that copied data.
435-
// Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985
436-
codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`)
437-
intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, true, true, true, true)
438-
)
439-
440-
func TestProcessVerkle(t *testing.T) {
441-
var (
442-
config = &params.ChainConfig{
443-
ChainID: big.NewInt(1),
444-
HomesteadBlock: big.NewInt(0),
445-
EIP150Block: big.NewInt(0),
446-
EIP155Block: big.NewInt(0),
447-
EIP158Block: big.NewInt(0),
448-
ByzantiumBlock: big.NewInt(0),
449-
ConstantinopleBlock: big.NewInt(0),
450-
PetersburgBlock: big.NewInt(0),
451-
IstanbulBlock: big.NewInt(0),
452-
MuirGlacierBlock: big.NewInt(0),
453-
BerlinBlock: big.NewInt(0),
454-
LondonBlock: big.NewInt(0),
455-
Ethash: new(params.EthashConfig),
456-
ShanghaiTime: u64(0),
457-
VerkleTime: u64(0),
458-
TerminalTotalDifficulty: common.Big0,
459-
}
460-
signer = types.LatestSigner(config)
461-
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
462-
bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain
463-
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
464-
gspec = &Genesis{
465-
Config: config,
466-
Alloc: GenesisAlloc{
467-
coinbase: GenesisAccount{
468-
Balance: big.NewInt(1000000000000000000), // 1 ether
469-
Nonce: 0,
470-
},
471-
},
472-
}
473-
)
474-
// Verkle trees use the snapshot, which must be enabled before the
475-
// data is saved into the tree+database.
476-
// genesis := gspec.MustCommit(bcdb, triedb)
477-
cacheConfig := DefaultCacheConfigWithScheme("path")
478-
cacheConfig.SnapshotLimit = 0
479-
blockchain, _ := NewBlockChain(bcdb, cacheConfig, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
480-
defer blockchain.Stop()
481-
482-
txCost1 := params.TxGas
483-
txCost2 := params.TxGas
484-
contractCreationCost := intrinsicContractCreationGas +
485-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation */
486-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* creation with value */
487-
739 /* execution costs */
488-
codeWithExtCodeCopyGas := intrinsicCodeWithExtCodeCopyGas +
489-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation (tx) */
490-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation (CREATE at pc=0x20) */
491-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* write code hash */
492-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #0 */
493-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #1 */
494-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #2 */
495-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #3 */
496-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #4 */
497-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #5 */
498-
params.WitnessChunkReadCost + /* SLOAD in constructor */
499-
params.WitnessChunkWriteCost + /* SSTORE in constructor */
500-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + params.WitnessBranchReadCost + params.WitnessBranchWriteCost + /* creation (CREATE at PC=0x121) */
501-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* write code hash */
502-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #0 */
503-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #1 */
504-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #2 */
505-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #3 */
506-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #4 */
507-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* code chunk #5 */
508-
params.WitnessChunkReadCost + /* SLOAD in constructor */
509-
params.WitnessChunkWriteCost + /* SSTORE in constructor */
510-
params.WitnessChunkReadCost + params.WitnessChunkWriteCost + /* write code hash for tx creation */
511-
15*(params.WitnessChunkReadCost+params.WitnessChunkWriteCost) + /* code chunks #0..#14 */
512-
4844 /* execution costs */
513-
blockGasUsagesExpected := []uint64{
514-
txCost1*2 + txCost2,
515-
txCost1*2 + txCost2 + contractCreationCost + codeWithExtCodeCopyGas,
516-
}
517-
_, chain, _, proofs, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
518-
gen.SetPoS()
519-
520-
// TODO need to check that the tx cost provided is the exact amount used (no remaining left-over)
521-
tx, _ := types.SignTx(types.NewTransaction(uint64(i)*3, common.Address{byte(i), 2, 3}, big.NewInt(999), txCost1, big.NewInt(875000000), nil), signer, testKey)
522-
gen.AddTx(tx)
523-
tx, _ = types.SignTx(types.NewTransaction(uint64(i)*3+1, common.Address{}, big.NewInt(999), txCost1, big.NewInt(875000000), nil), signer, testKey)
524-
gen.AddTx(tx)
525-
tx, _ = types.SignTx(types.NewTransaction(uint64(i)*3+2, common.Address{}, big.NewInt(0), txCost2, big.NewInt(875000000), nil), signer, testKey)
526-
gen.AddTx(tx)
527-
528-
// Add two contract creations in block #2
529-
if i == 1 {
530-
tx, _ = types.SignTx(types.NewContractCreation(6, big.NewInt(16), 3000000, big.NewInt(875000000), code), signer, testKey)
531-
gen.AddTx(tx)
532-
533-
tx, _ = types.SignTx(types.NewContractCreation(7, big.NewInt(0), 3000000, big.NewInt(875000000), codeWithExtCodeCopy), signer, testKey)
534-
gen.AddTx(tx)
535-
}
536-
})
537-
538-
// Check proof for both blocks
539-
err := verkle.Verify(proofs[0], gspec.ToBlock().Root().Bytes(), chain[0].Root().Bytes(), statediffs[0])
540-
if err != nil {
541-
t.Fatal(err)
542-
}
543-
err = verkle.Verify(proofs[1], chain[0].Root().Bytes(), chain[1].Root().Bytes(), statediffs[1])
544-
if err != nil {
545-
t.Fatal(err)
546-
}
547-
548-
t.Log("verified verkle proof, inserting blocks into the chain")
549-
550-
endnum, err := blockchain.InsertChain(chain)
551-
if err != nil {
552-
t.Fatalf("block %d imported with error: %v", endnum, err)
553-
}
554-
555-
for i := 0; i < 2; i++ {
556-
b := blockchain.GetBlockByNumber(uint64(i) + 1)
557-
if b == nil {
558-
t.Fatalf("expected block %d to be present in chain", i+1)
559-
}
560-
if b.Hash() != chain[i].Hash() {
561-
t.Fatalf("block #%d not found at expected height", b.NumberU64())
562-
}
563-
if b.GasUsed() != blockGasUsagesExpected[i] {
564-
t.Fatalf("expected block #%d txs to use %d, got %d\n", b.NumberU64(), blockGasUsagesExpected[i], b.GasUsed())
565-
}
566-
}
567-
}
568-
569-
func TestProcessParentBlockHash(t *testing.T) {
570-
var (
571-
chainConfig = params.MergedTestChainConfig
572-
hashA = common.Hash{0x01}
573-
hashB = common.Hash{0x02}
574-
header = &types.Header{ParentHash: hashA, Number: big.NewInt(2), Difficulty: big.NewInt(0)}
575-
parent = &types.Header{ParentHash: hashB, Number: big.NewInt(1), Difficulty: big.NewInt(0)}
576-
coinbase = common.Address{}
577-
)
578-
test := func(statedb *state.StateDB) {
579-
statedb.SetNonce(params.HistoryStorageAddress, 1)
580-
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
581-
statedb.IntermediateRoot(true)
582-
583-
vmContext := NewEVMBlockContext(header, nil, &coinbase)
584-
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{})
585-
ProcessParentBlockHash(header.ParentHash, evm, statedb)
586-
587-
vmContext = NewEVMBlockContext(parent, nil, &coinbase)
588-
evm = vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{})
589-
ProcessParentBlockHash(parent.ParentHash, evm, statedb)
590-
591-
// make sure that the state is correct
592-
if have := getParentBlockHash(statedb, 1); have != hashA {
593-
t.Errorf("want parent hash %v, have %v", hashA, have)
594-
}
595-
if have := getParentBlockHash(statedb, 0); have != hashB {
596-
t.Errorf("want parent hash %v, have %v", hashB, have)
597-
}
598-
}
599-
t.Run("MPT", func(t *testing.T) {
600-
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
601-
test(statedb)
602-
})
603-
t.Run("Verkle", func(t *testing.T) {
604-
db := rawdb.NewMemoryDatabase()
605-
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
606-
cacheConfig.SnapshotLimit = 0
607-
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
608-
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
609-
test(statedb)
610-
})
611-
}
612-
613-
func getParentBlockHash(statedb *state.StateDB, number uint64) common.Hash {
614-
ringIndex := number % params.HistoryServeWindow
615-
var key common.Hash
616-
binary.BigEndian.PutUint64(key[24:], ringIndex)
617-
return statedb.GetState(params.HistoryStorageAddress, key)
618-
}

0 commit comments

Comments
 (0)