diff --git a/.github/workflows/stable-spec-tests.yml b/.github/workflows/stable-spec-tests.yml index 07efa0ffbea..fe13e2fd02f 100644 --- a/.github/workflows/stable-spec-tests.yml +++ b/.github/workflows/stable-spec-tests.yml @@ -8,7 +8,7 @@ on: workflow_dispatch: env: - FIXTURES_TAG: "verkle@v0.0.6" + FIXTURES_TAG: "verkle@v0.0.7-alpha-4" jobs: setup: diff --git a/.golangci.yml b/.golangci.yml index 8a054667e6d..210005686f5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -57,6 +57,21 @@ issues: text: 'SA1019: "github.com/golang/protobuf/proto" is deprecated: Use the "google.golang.org/protobuf/proto" package instead.' - path: accounts/usbwallet/trezor/ text: 'SA1019: "github.com/golang/protobuf/proto" is deprecated: Use the "google.golang.org/protobuf/proto" package instead.' + - path: accounts/scwallet/securechannel.go + linters: + - staticcheck + - path: p2p/rlpx/rlpx.go + linters: + - staticcheck + - path: crypto/ + linters: + - staticcheck + - path: rlp/ + linters: + - staticcheck + - path: miner/ + linters: + - staticcheck exclude: - 'SA1019: event.TypeMux is deprecated: use Feed' - 'SA1019: strings.Title is deprecated' diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 4400dddd10b..1a95f4cd0f3 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -69,6 +69,7 @@ type ExecutionResult struct { // Verkle witness VerkleProof *verkle.VerkleProof `json:"verkleProof,omitempty"` StateDiff verkle.StateDiff `json:"stateDiff,omitempty"` + ParentRoot common.Hash `json:"parentRoot,omitempty"` // Values to test the verkle conversion CurrentAccountAddress *common.Address `json:"currentConversionAddress,omitempty" gencodec:"optional"` @@ -163,17 +164,18 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, return h } var ( - statedb = MakePreState(rawdb.NewMemoryDatabase(), chainConfig, pre, chainConfig.IsVerkle(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp)) - vtrpre *trie.VerkleTrie - signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) - gaspool = new(core.GasPool) - blockHash = common.Hash{0x13, 0x37} - rejectedTxs []*rejectedTx - includedTxs types.Transactions - gasUsed = uint64(0) - receipts = make(types.Receipts, 0) - txIndex = 0 + parentStateRoot, statedb = MakePreState(rawdb.NewMemoryDatabase(), chainConfig, pre, chainConfig.IsVerkle(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp)) + vtrpre *trie.VerkleTrie + signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) + gaspool = new(core.GasPool) + blockHash = common.Hash{0x13, 0x37} + rejectedTxs []*rejectedTx + includedTxs types.Transactions + gasUsed = uint64(0) + receipts = make(types.Receipts, 0) + txIndex = 0 ) + gaspool.AddGas(pre.Env.GasLimit) vmContext := vm.BlockContext{ CanTransfer: core.CanTransfer, @@ -191,8 +193,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, switch tr := statedb.GetTrie().(type) { case *trie.VerkleTrie: vtrpre = tr.Copy() - case *trie.TransitionTrie: - vtrpre = tr.Overlay().Copy() } // If currentBaseFee is defined, add it to the vmContext. @@ -391,6 +391,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee), VerkleProof: vktProof, StateDiff: vktStateDiff, + ParentRoot: parentStateRoot, } if pre.Env.Withdrawals != nil { h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil)) @@ -425,7 +426,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, return statedb, execRs, nil } -func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prestate, verkle bool) *state.StateDB { +func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prestate, verkle bool) (common.Hash, *state.StateDB) { // Start with generating the MPT DB, which should be empty if it's post-verkle transition sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: true, Verkle: false}) @@ -451,9 +452,12 @@ func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prest codeHash := crypto.Keccak256Hash(acc.Code) rawdb.WriteCode(codeWriter, codeHash, acc.Code) } - statedb.Commit(0, false) + root, err := statedb.Commit(0, false) + if err != nil { + panic(err) + } - return statedb + return root, statedb } // MPT pre is the same as the pre state for first conversion block @@ -473,12 +477,13 @@ func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prest panic(err) } + parentRoot := mptRoot // If verkle mode started, establish the conversion if verkle { // If the current tree is a VerkleTrie, it means the state conversion has ended. // We don't need to continue with conversion setups and can return early. if _, ok := statedb.GetTrie().(*trie.VerkleTrie); ok { - return statedb + return parentRoot, statedb } rawdb.WritePreimages(sdb.DiskDB(), statedb.Preimages()) @@ -548,6 +553,12 @@ func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prest } root, _ := statedb.Commit(0, false) + // If the VKT prestate is empty, this means that the "parent" root is the MPT. + // If we don't do this, we'd consider the "parent" to be an empty VKT which isn't + // correct. + if pre.VKT != nil { + parentRoot = root + } // recreate the verkle db with the tree root, but this time with the mpt snapshot, // so that the conversion can proceed. @@ -565,7 +576,7 @@ func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prest if statedb.Database().InTransition() || statedb.Database().Transitioned() { log.Info("at end of makestate", "in transition", statedb.Database().InTransition(), "during", statedb.Database().Transitioned(), "account hash", statedb.Database().GetCurrentAccountHash()) } - return statedb + return parentRoot, statedb } func rlpHash(x interface{}) (h common.Hash) { diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index 76caca0fbc7..86b9c8c78fd 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -322,7 +322,7 @@ func Transition(ctx *cli.Context) error { vktleaves = make(map[common.Hash]hexutil.Bytes) s.DumpVKTLeaves(vktleaves) } - return dispatchOutput(ctx, baseDir, result, collector, vktleaves, body, result.VerkleProof, result.StateDiff) + return dispatchOutput(ctx, baseDir, result, collector, vktleaves, body, result.VerkleProof, result.StateDiff, result.ParentRoot) } // txWithKey is a helper-struct, to allow us to use the types.Transaction along with @@ -447,7 +447,7 @@ func saveFile(baseDir, filename string, data interface{}) error { // dispatchOutput writes the output data to either stderr or stdout, or to the specified // files -func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, alloc Alloc, vkt map[common.Hash]hexutil.Bytes, body hexutil.Bytes, p *verkle.VerkleProof, k verkle.StateDiff) error { +func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, alloc Alloc, vkt map[common.Hash]hexutil.Bytes, body hexutil.Bytes, p *verkle.VerkleProof, k verkle.StateDiff, proot common.Hash) error { stdOutObject := make(map[string]interface{}) stdErrObject := make(map[string]interface{}) dispatch := func(baseDir, fName, name string, obj interface{}) error { @@ -481,9 +481,10 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a } if p != nil { if err := dispatch(baseDir, ctx.String(OutputWitnessFlag.Name), "witness", struct { - Proof *verkle.VerkleProof - Diff verkle.StateDiff - }{p, k}); err != nil { + Proof *verkle.VerkleProof + Diff verkle.StateDiff + ParentRoot common.Hash + }{p, k, proot}); err != nil { return err } } diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index b792fbf3996..c7bfd1e55b0 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -400,82 +400,92 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea state.Database().SaveTransitionState(header.Root) var ( - p *verkle.VerkleProof - k verkle.StateDiff - keys = state.Witness().Keys() - proot common.Hash + proof *verkle.VerkleProof + stateDiff verkle.StateDiff + proot common.Hash ) if chain.Config().IsVerkle(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) } - proot = parent.Root - // 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) - } - } - } + var err error + stateDiff, proof, err = BuildVerkleProof(header, state, parent.Root) + if err != nil { + return nil, fmt.Errorf("error building verkle proof: %w", err) } + proot = parent.Root } // Assemble and return the final block. block := types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil)) if chain.Config().IsVerkle(header.Number, header.Time) && chain.Config().ProofInBlocks { - block.SetVerkleProof(p, k, proot) + block.SetVerkleProof(proof, stateDiff, proot) } return block, nil } +func BuildVerkleProof(header *types.Header, state *state.StateDB, parentRoot common.Hash) (verkle.StateDiff, *verkle.VerkleProof, error) { + var ( + proof *verkle.VerkleProof + stateDiff verkle.StateDiff + ) + + preTrie, err := state.Database().OpenTrie(parentRoot) + if err != nil { + return nil, 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 { + keys := state.Witness().Keys() + if len(keys) > 0 { + proof, stateDiff, err = trie.ProveAndSerialize(vtrpre, vtrpost, keys, vtrpre.FlatdbNodeResolver) + if err != nil { + return nil, nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err) + } + } + } + return stateDiff, proof, nil +} + // Seal generates a new sealing request for the given input block and pushes // the result into the given channel. // diff --git a/core/block_validator.go b/core/block_validator.go index 337b61ac339..8014fbeef68 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" @@ -131,6 +132,24 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root { return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error()) } + if blockEw := block.ExecutionWitness(); blockEw != nil { + parent := v.bc.GetHeaderByNumber(header.Number.Uint64() - 1) + if parent == nil { + return fmt.Errorf("nil parent header for block %d", header.Number) + } + stateDiff, proof, err := beacon.BuildVerkleProof(header, statedb, parent.Root) + if err != nil { + return fmt.Errorf("error building verkle proof: %w", err) + } + ew := types.ExecutionWitness{ + StateDiff: stateDiff, + VerkleProof: proof, + ParentStateRoot: parent.Root, + } + if err := ew.Equal(blockEw); err != nil { + return fmt.Errorf("invalid execution witness: %v", err) + } + } // Verify that the advertised root is correct before // it can be used as an identifier for the conversion // status. diff --git a/core/chain_makers.go b/core/chain_makers.go index 9fe06ed8c99..07a600ef735 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -432,7 +432,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine proots = append(proots, parent.Root()) // quick check that we are self-consistent - err = trie.DeserializeAndVerifyVerkleProof(block.ExecutionWitness().VerkleProof, block.ExecutionWitness().ParentStateRoot[:], block.Root().Bytes(), block.ExecutionWitness().StateDiff) + err = verkle.Verify(block.ExecutionWitness().VerkleProof, block.ExecutionWitness().ParentStateRoot[:], block.Root().Bytes(), block.ExecutionWitness().StateDiff) if err != nil { panic(err) } diff --git a/core/state_processor_test.go b/core/state_processor_test.go index d4ed7e505e7..359d6e08f7e 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -45,6 +45,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie/utils" + "github.com/ethereum/go-verkle" //"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" @@ -608,13 +609,13 @@ func TestProcessVerkle(t *testing.T) { //fmt.Printf("root= %x\n", chain[0].Root()) // check the proof for the 1st block - err = trie.DeserializeAndVerifyVerkleProof(proofs[0], genesis.Root().Bytes(), chain[0].Root().Bytes(), keyvals[0]) + err = verkle.Verify(proofs[0], genesis.Root().Bytes(), chain[0].Root().Bytes(), keyvals[0]) if err != nil { spew.Dump(genesis.Root().Bytes(), proofs[0]) t.Fatal(err) } // check the proof for the last block - err = trie.DeserializeAndVerifyVerkleProof(proofs[1], chain[0].Root().Bytes(), chain[1].Root().Bytes(), keyvals[1]) + err = verkle.Verify(proofs[1], chain[0].Root().Bytes(), chain[1].Root().Bytes(), keyvals[1]) if err != nil { t.Fatal(err) } diff --git a/core/types/block.go b/core/types/block.go index 842c9cbb717..6a6617504e5 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -62,7 +62,7 @@ func (n *BlockNonce) UnmarshalText(input []byte) error { type ExecutionWitness struct { StateDiff verkle.StateDiff `json:"stateDiff"` VerkleProof *verkle.VerkleProof `json:"verkleProof"` - ParentStateRoot common.Hash `json:"parentStateRoot"` + ParentStateRoot common.Hash `json:"parentRoot"` } func (ew *ExecutionWitness) Copy() *ExecutionWitness { @@ -73,6 +73,20 @@ func (ew *ExecutionWitness) Copy() *ExecutionWitness { } } +func (ew *ExecutionWitness) Equal(other *ExecutionWitness) error { + if ew.ParentStateRoot != other.ParentStateRoot { + return fmt.Errorf("ParentStateRoot mismatch: %v != %v", ew.ParentStateRoot, other.ParentStateRoot) + } + if err := ew.StateDiff.Equal(other.StateDiff); err != nil { + return fmt.Errorf("StateDiff mismatch: %v", err) + } + if err := ew.VerkleProof.Equal(other.VerkleProof); err != nil { + return fmt.Errorf("VerkleProof mismatch: %v", err) + } + + return nil +} + //go:generate go run github.com/fjl/gencodec -type Header -field-override headerMarshaling -out gen_header_json.go //go:generate go run ../../rlp/rlpgen -type Header -out gen_header_rlp.go @@ -435,6 +449,10 @@ func (b *Block) SetVerkleProof(vp *verkle.VerkleProof, statediff verkle.StateDif } } +func (b *Block) SetExecutionWitness(ew *ExecutionWitness) { + b.header.ExecutionWitness = ew +} + type writeCounter uint64 func (c *writeCounter) Write(b []byte) (int, error) { diff --git a/go.mod b/go.mod index b4f20617aa0..d60b1475739 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/ethereum/go-ethereum -go 1.19 +go 1.22 + +toolchain go1.22.1 require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 @@ -21,7 +23,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.2.1 github.com/fatih/color v1.7.0 github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e github.com/fsnotify/fsnotify v1.6.0 diff --git a/go.sum b/go.sum index 9c58bd9c0df..66474aea8df 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,7 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 h1:Px2UA+2RvSSvv+RvJ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= @@ -48,6 +49,7 @@ github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6 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= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -127,8 +129,8 @@ 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.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.2.1 h1:FYWEByFT19jT/ym/dy++E+f1SSw899uXGNrhCkwjYJw= +github.com/ethereum/go-verkle v0.2.1/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= 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= @@ -156,6 +158,7 @@ github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclK github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= @@ -210,6 +213,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= @@ -300,6 +304,7 @@ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4F github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -374,6 +379,7 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 9c0ee3b1a93..bc3088be093 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -61,10 +61,11 @@ type btJSON struct { } type btBlock struct { - BlockHeader *btHeader - ExpectException string - Rlp string - UncleHeaders []*btHeader + BlockHeader *btHeader + ExpectException string + Rlp string + UncleHeaders []*btHeader + ExecutionWitness *types.ExecutionWitness `json:"witness"` } //go:generate go run github.com/fjl/gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go @@ -200,6 +201,7 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %v", err) } } + // RLP decoding worked, try to insert into chain: blocks := types.Blocks{cb} i, err := blockchain.InsertChain(blocks) @@ -328,6 +330,9 @@ func (bb *btBlock) decode() (*types.Block, error) { return nil, err } var b types.Block - err = rlp.DecodeBytes(data, &b) - return &b, err + if err := rlp.DecodeBytes(data, &b); err != nil { + return nil, err + } + b.SetExecutionWitness(bb.ExecutionWitness) + return &b, nil } diff --git a/trie/verkle.go b/trie/verkle.go index 7ba85f574c6..76b5021b78c 100644 --- a/trie/verkle.go +++ b/trie/verkle.go @@ -300,60 +300,6 @@ func ProveAndSerialize(pretrie, posttrie *VerkleTrie, keys [][]byte, resolver ve return p, kvps, nil } -func DeserializeAndVerifyVerkleProof(vp *verkle.VerkleProof, preStateRoot []byte, postStateRoot []byte, statediff verkle.StateDiff) error { - // TODO: check that `OtherStems` have expected length and values. - - proof, err := verkle.DeserializeProof(vp, statediff) - if err != nil { - return fmt.Errorf("verkle proof deserialization error: %w", err) - } - - rootC := new(verkle.Point) - rootC.SetBytes(preStateRoot) - pretree, err := verkle.PreStateTreeFromProof(proof, rootC) - if err != nil { - return fmt.Errorf("error rebuilding the pre-tree from proof: %w", err) - } - // 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 - - 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) - } - } - } - } - - // 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 - // keep track of the written keys, and compare that list with this post-values list. - // This can avoid regenerating the post-tree which is somewhat expensive. - posttree, err := verkle.PostStateTreeFromStateDiff(pretree, statediff) - if err != nil { - return fmt.Errorf("error rebuilding the post-tree from proof: %w", err) - } - regeneratedPostTreeRoot := posttree.Commitment().Bytes() - if !bytes.Equal(regeneratedPostTreeRoot[:], postStateRoot) { - return fmt.Errorf("post tree root mismatch: %x != %x", regeneratedPostTreeRoot, postStateRoot) - } - - return verkle.VerifyVerkleProofWithPreState(proof, pretree) -} - // ChunkedCode represents a sequence of 32-bytes chunks of code (31 bytes of which // are actual code, and 1 byte is the pushdata offset). type ChunkedCode []byte diff --git a/trie/verkle_test.go b/trie/verkle_test.go index 5118338d9d3..0d0934649a5 100644 --- a/trie/verkle_test.go +++ b/trie/verkle_test.go @@ -71,12 +71,16 @@ func TestReproduceTree(t *testing.T) { } root.Commit() - proof, Cs, zis, yis, err := verkle.MakeVerkleMultiProof(root, nil, append(presentKeys, absentKeys...), nil) + proof, Cs, _, _, err := verkle.MakeVerkleMultiProof(root, nil, append(presentKeys, absentKeys...), nil) if err != nil { t.Fatalf("could not create proof: %v", err) } - cfg := verkle.GetConfig() - if ok, err := verkle.VerifyVerkleProof(proof, Cs, zis, yis, cfg); !ok || err != nil { + vktProof, statediff, err := verkle.SerializeProof(proof) + if err != nil { + t.Fatalf("could not serialize proof: %v", err) + } + preStateRoot := root.Commit().Bytes() + if err := verkle.Verify(vktProof, preStateRoot[:], nil, statediff); err != nil { t.Fatalf("could not verify proof: %v", err) } @@ -294,9 +298,13 @@ func TestReproduceCondrieuStemAggregationInProofOfAbsence(t *testing.T) { } root.Commit() - proof, Cs, zis, yis, _ := verkle.MakeVerkleMultiProof(root, nil, append(presentKeys, absentKeys...), nil) - cfg := verkle.GetConfig() - if ok, err := verkle.VerifyVerkleProof(proof, Cs, zis, yis, cfg); !ok || err != nil { + proof, Cs, _, _, _ := verkle.MakeVerkleMultiProof(root, nil, append(presentKeys, absentKeys...), nil) + vktProof, statediff, err := verkle.SerializeProof(proof) + if err != nil { + t.Fatalf("could not serialize proof: %v", err) + } + preStateRoot := root.Commit().Bytes() + if err := verkle.Verify(vktProof, preStateRoot[:], nil, statediff); err != nil { t.Fatal("could not verify proof") } @@ -340,9 +348,13 @@ func TestReproduceCondrieuPoAStemConflictWithAnotherStem(t *testing.T) { } root.Commit() - proof, Cs, zis, yis, _ := verkle.MakeVerkleMultiProof(root, nil, append(presentKeys, absentKeys...), nil) - cfg := verkle.GetConfig() - if ok, err := verkle.VerifyVerkleProof(proof, Cs, zis, yis, cfg); !ok || err != nil { + proof, Cs, _, _, _ := verkle.MakeVerkleMultiProof(root, nil, append(presentKeys, absentKeys...), nil) + vktProof, stateDiff, err := verkle.SerializeProof(proof) + if err != nil { + t.Fatalf("could not serialize proof: %v", err) + } + preStateRoot := root.Commit().Bytes() + if err := verkle.Verify(vktProof, preStateRoot[:], nil, stateDiff); err != nil { t.Fatal("could not verify proof") }