Skip to content

Commit 0420c57

Browse files
committed
port kaustinen code on top of shapella-rebased branch
activate proof generation on fork + remove code dups use go-verkle's post-state API to verify proofs (#262) use prague as the verkle activation fork (#263) upgrade to latest go-ipa activate verkle transition in "miner" (#265) fix: do not force cancunTime upon verkle activation workaround: do not use root translation in replay workaround: deactivate overlay transition for now fixes from trying to get the devnet to work (#267) this line was left out from the previous commit upgrade to go-verkle with fixed newvalue serialization fix: ensure point cache isn't nil in copy (#268) fix: dependency cycle in tests (#269) upgrade to latest go-verkle fix: write trie preimage data to db (#274) fix: zero-root in produced block + sync (#275) upgrade go-ipa fix build fix typo include review feedback add switch to add proofs to blocks (#278) add fee recipient to witness (#279) touch all fields in withdrawal account header (#277)
1 parent db8ff7c commit 0420c57

39 files changed

+453
-332
lines changed

beacon/engine/gen_ed.go

Lines changed: 40 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

beacon/engine/types.go

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ type ExecutableData struct {
6464
Withdrawals []*types.Withdrawal `json:"withdrawals"`
6565
BlobGasUsed *uint64 `json:"blobGasUsed"`
6666
ExcessBlobGas *uint64 `json:"excessBlobGas"`
67+
68+
ExecutionWitness *types.ExecutionWitness `json:"executionWitness"`
6769
}
6870

6971
// JSON type overrides for executableData.
@@ -208,24 +210,25 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
208210
withdrawalsRoot = &h
209211
}
210212
header := &types.Header{
211-
ParentHash: params.ParentHash,
212-
UncleHash: types.EmptyUncleHash,
213-
Coinbase: params.FeeRecipient,
214-
Root: params.StateRoot,
215-
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
216-
ReceiptHash: params.ReceiptsRoot,
217-
Bloom: types.BytesToBloom(params.LogsBloom),
218-
Difficulty: common.Big0,
219-
Number: new(big.Int).SetUint64(params.Number),
220-
GasLimit: params.GasLimit,
221-
GasUsed: params.GasUsed,
222-
Time: params.Timestamp,
223-
BaseFee: params.BaseFeePerGas,
224-
Extra: params.ExtraData,
225-
MixDigest: params.Random,
226-
WithdrawalsHash: withdrawalsRoot,
227-
ExcessBlobGas: params.ExcessBlobGas,
228-
BlobGasUsed: params.BlobGasUsed,
213+
ParentHash: params.ParentHash,
214+
UncleHash: types.EmptyUncleHash,
215+
Coinbase: params.FeeRecipient,
216+
Root: params.StateRoot,
217+
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
218+
ReceiptHash: params.ReceiptsRoot,
219+
Bloom: types.BytesToBloom(params.LogsBloom),
220+
Difficulty: common.Big0,
221+
Number: new(big.Int).SetUint64(params.Number),
222+
GasLimit: params.GasLimit,
223+
GasUsed: params.GasUsed,
224+
Time: params.Timestamp,
225+
BaseFee: params.BaseFeePerGas,
226+
Extra: params.ExtraData,
227+
MixDigest: params.Random,
228+
WithdrawalsHash: withdrawalsRoot,
229+
ExcessBlobGas: params.ExcessBlobGas,
230+
BlobGasUsed: params.BlobGasUsed,
231+
ExecutionWitness: params.ExecutionWitness,
229232
}
230233
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
231234
if block.Hash() != params.BlockHash {
@@ -238,23 +241,24 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash)
238241
// fields from the given block. It assumes the given block is post-merge block.
239242
func BlockToExecutableData(block *types.Block, fees *big.Int, blobs []kzg4844.Blob, commitments []kzg4844.Commitment, proofs []kzg4844.Proof) *ExecutionPayloadEnvelope {
240243
data := &ExecutableData{
241-
BlockHash: block.Hash(),
242-
ParentHash: block.ParentHash(),
243-
FeeRecipient: block.Coinbase(),
244-
StateRoot: block.Root(),
245-
Number: block.NumberU64(),
246-
GasLimit: block.GasLimit(),
247-
GasUsed: block.GasUsed(),
248-
BaseFeePerGas: block.BaseFee(),
249-
Timestamp: block.Time(),
250-
ReceiptsRoot: block.ReceiptHash(),
251-
LogsBloom: block.Bloom().Bytes(),
252-
Transactions: encodeTransactions(block.Transactions()),
253-
Random: block.MixDigest(),
254-
ExtraData: block.Extra(),
255-
Withdrawals: block.Withdrawals(),
256-
BlobGasUsed: block.BlobGasUsed(),
257-
ExcessBlobGas: block.ExcessBlobGas(),
244+
BlockHash: block.Hash(),
245+
ParentHash: block.ParentHash(),
246+
FeeRecipient: block.Coinbase(),
247+
StateRoot: block.Root(),
248+
Number: block.NumberU64(),
249+
GasLimit: block.GasLimit(),
250+
GasUsed: block.GasUsed(),
251+
BaseFeePerGas: block.BaseFee(),
252+
Timestamp: block.Time(),
253+
ReceiptsRoot: block.ReceiptHash(),
254+
LogsBloom: block.Bloom().Bytes(),
255+
Transactions: encodeTransactions(block.Transactions()),
256+
Random: block.MixDigest(),
257+
ExtraData: block.Extra(),
258+
Withdrawals: block.Withdrawals(),
259+
BlobGasUsed: block.BlobGasUsed(),
260+
ExcessBlobGas: block.ExcessBlobGas(),
261+
ExecutionWitness: block.ExecutionWitness(),
258262
}
259263
blobsBundle := BlobsBundleV1{
260264
Commitments: make([]hexutil.Bytes, 0),

cmd/geth/config.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,9 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
171171
v := ctx.Uint64(utils.OverrideCancun.Name)
172172
cfg.Eth.OverrideCancun = &v
173173
}
174-
if ctx.IsSet(utils.OverrideVerkle.Name) {
175-
v := ctx.Uint64(utils.OverrideVerkle.Name)
176-
cfg.Eth.OverrideVerkle = &v
174+
if ctx.IsSet(utils.OverridePrague.Name) {
175+
v := ctx.Uint64(utils.OverridePrague.Name)
176+
cfg.Eth.OverridePrague = &v
177177
}
178178
backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
179179

cmd/geth/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ var (
6868
utils.USBFlag,
6969
utils.SmartCardDaemonPathFlag,
7070
utils.OverrideCancun,
71-
utils.OverrideVerkle,
71+
utils.OverridePrague,
7272
utils.EnablePersonal,
7373
utils.TxPoolLocalsFlag,
7474
utils.TxPoolNoLocalsFlag,

cmd/utils/flags.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,8 @@ var (
268268
Usage: "Manually specify the Cancun fork timestamp, overriding the bundled setting",
269269
Category: flags.EthCategory,
270270
}
271-
OverrideVerkle = &cli.Uint64Flag{
272-
Name: "override.verkle",
271+
OverridePrague = &cli.Uint64Flag{
272+
Name: "override.prague",
273273
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
274274
Category: flags.EthCategory,
275275
}

consensus/beacon/consensus.go

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/ethereum/go-ethereum/rpc"
3232
"github.com/ethereum/go-ethereum/trie"
3333
"github.com/ethereum/go-ethereum/trie/utils"
34+
"github.com/gballet/go-verkle"
3435
"github.com/holiman/uint256"
3536
)
3637

@@ -329,14 +330,14 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [
329330

330331
// Prepare implements consensus.Engine, initializing the difficulty field of a
331332
// header to conform to the beacon protocol. The changes are done inline.
332-
func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
333+
func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header, statedb *state.StateDB) error {
333334
// Transition isn't triggered yet, use the legacy rules for preparation.
334335
reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1)
335336
if err != nil {
336337
return err
337338
}
338339
if !reached {
339-
return beacon.ethone.Prepare(chain, header)
340+
return beacon.ethone.Prepare(chain, header, statedb)
340341
}
341342
header.Difficulty = beaconDifficulty
342343
return nil
@@ -356,9 +357,17 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
356357
state.AddBalance(w.Address, amount)
357358

358359
// The returned gas is not charged
360+
state.Witness().TouchAddressOnWriteAndComputeGas(w.Address[:], uint256.Int{}, utils.VersionLeafKey)
359361
state.Witness().TouchAddressOnWriteAndComputeGas(w.Address[:], uint256.Int{}, utils.BalanceLeafKey)
360-
}
361-
// No block reward which is issued by consensus layer instead.
362+
state.Witness().TouchAddressOnWriteAndComputeGas(w.Address[:], uint256.Int{}, utils.NonceLeafKey)
363+
state.Witness().TouchAddressOnWriteAndComputeGas(w.Address[:], uint256.Int{}, utils.CodeKeccakLeafKey)
364+
state.Witness().TouchAddressOnWriteAndComputeGas(w.Address[:], uint256.Int{}, utils.CodeSizeLeafKey)
365+
}
366+
state.Witness().TouchAddressOnWriteAndComputeGas(header.Coinbase[:], uint256.Int{}, utils.VersionLeafKey)
367+
state.Witness().TouchAddressOnWriteAndComputeGas(header.Coinbase[:], uint256.Int{}, utils.BalanceLeafKey)
368+
state.Witness().TouchAddressOnWriteAndComputeGas(header.Coinbase[:], uint256.Int{}, utils.NonceLeafKey)
369+
state.Witness().TouchAddressOnWriteAndComputeGas(header.Coinbase[:], uint256.Int{}, utils.CodeKeccakLeafKey)
370+
state.Witness().TouchAddressOnWriteAndComputeGas(header.Coinbase[:], uint256.Int{}, utils.CodeSizeLeafKey)
362371
}
363372

364373
// FinalizeAndAssemble implements consensus.Engine, setting the final state and
@@ -384,8 +393,65 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
384393
// Assign the final state root to header.
385394
header.Root = state.IntermediateRoot(true)
386395

396+
var (
397+
p *verkle.VerkleProof
398+
k verkle.StateDiff
399+
keys = state.Witness().Keys()
400+
)
401+
if chain.Config().IsPrague(header.Number, header.Time) && chain.Config().ProofInBlock {
402+
// Open the pre-tree to prove the pre-state against
403+
parent := chain.GetHeaderByNumber(header.Number.Uint64() - 1)
404+
if parent == nil {
405+
return nil, fmt.Errorf("nil parent header for block %d", header.Number)
406+
}
407+
408+
preTrie, err := state.Database().OpenTrie(parent.Root)
409+
if err != nil {
410+
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
411+
}
412+
413+
var okpre, okpost bool
414+
var vtrpre, vtrpost *trie.VerkleTrie
415+
switch pre := preTrie.(type) {
416+
case *trie.VerkleTrie:
417+
vtrpre, okpre = preTrie.(*trie.VerkleTrie)
418+
vtrpost, okpost = state.GetTrie().(*trie.VerkleTrie)
419+
case *trie.TransitionTrie:
420+
vtrpre = pre.Overlay()
421+
okpre = true
422+
post, _ := state.GetTrie().(*trie.TransitionTrie)
423+
vtrpost = post.Overlay()
424+
okpost = true
425+
default:
426+
panic("invalid tree type")
427+
}
428+
if okpre && okpost {
429+
// Resolve values from the pre state, the post
430+
// state should already have the values in memory.
431+
// TODO: see if this can be captured at the witness
432+
// level, like it used to.
433+
for _, key := range keys {
434+
_, err := vtrpre.GetWithHashedKey(key)
435+
if err != nil {
436+
panic(err)
437+
}
438+
}
439+
440+
if len(keys) > 0 {
441+
p, k, err = trie.ProveAndSerialize(vtrpre, vtrpost, keys, vtrpre.FlatdbNodeResolver)
442+
if err != nil {
443+
return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
444+
}
445+
}
446+
}
447+
}
448+
387449
// Assemble and return the final block.
388-
return types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil)), nil
450+
block := types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil))
451+
if chain.Config().IsPrague(header.Number, header.Time) && chain.Config().ProofInBlock {
452+
block.SetVerkleProof(p, k)
453+
}
454+
return block, nil
389455
}
390456

391457
// Seal generates a new sealing request for the given input block and pushes

consensus/clique/clique.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ func (c *Clique) verifySeal(snap *Snapshot, header *types.Header, parents []*typ
499499

500500
// Prepare implements consensus.Engine, preparing all the consensus fields of the
501501
// header for running the transactions on top.
502-
func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
502+
func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header, _ *state.StateDB) error {
503503
// If the block isn't a checkpoint, cast a random vote (good enough for now)
504504
header.Coinbase = common.Address{}
505505
header.Nonce = types.BlockNonce{}

consensus/consensus.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ type Engine interface {
8181

8282
// Prepare initializes the consensus fields of a block header according to the
8383
// rules of a particular engine. The changes are executed inline.
84-
Prepare(chain ChainHeaderReader, header *types.Header) error
84+
Prepare(chain ChainHeaderReader, header *types.Header, state *state.StateDB) error
8585

8686
// Finalize runs any post-transaction state modifications (e.g. block rewards
8787
// or process withdrawals) but does not assemble the block.

consensus/ethash/consensus.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ var DynamicDifficultyCalculator = makeDifficultyCalculator
479479

480480
// Prepare implements consensus.Engine, initializing the difficulty field of a
481481
// header to conform to the ethash protocol. The changes are done inline.
482-
func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
482+
func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.Header, _ *state.StateDB) error {
483483
parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
484484
if parent == nil {
485485
return consensus.ErrUnknownAncestor
@@ -568,15 +568,15 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header
568568
r.Div(r, big8)
569569

570570
// This should not happen, but it's useful for replay tests
571-
if config.IsVerkle(header.Number, header.Time) {
571+
if config.IsPrague(header.Number, header.Time) {
572572
state.Witness().TouchAddressOnReadAndComputeGas(uncle.Coinbase.Bytes(), uint256.Int{}, utils.BalanceLeafKey)
573573
}
574574
state.AddBalance(uncle.Coinbase, r)
575575

576576
r.Div(blockReward, big32)
577577
reward.Add(reward, r)
578578
}
579-
if config.IsVerkle(header.Number, header.Time) {
579+
if config.IsPrague(header.Number, header.Time) {
580580
state.Witness().TouchAddressOnReadAndComputeGas(header.Coinbase.Bytes(), uint256.Int{}, utils.BalanceLeafKey)
581581
state.Witness().TouchAddressOnReadAndComputeGas(header.Coinbase.Bytes(), uint256.Int{}, utils.VersionLeafKey)
582582
state.Witness().TouchAddressOnReadAndComputeGas(header.Coinbase.Bytes(), uint256.Int{}, utils.NonceLeafKey)

0 commit comments

Comments
 (0)