Skip to content

Commit

Permalink
Merge tag 'v1.101411.6' into release/optimism-1.x-fh3.0
Browse files Browse the repository at this point in the history
Release v1.101411.6
  • Loading branch information
Eduard-Voiculescu committed Jan 30, 2025
2 parents 353d6b6 + 50b3422 commit 6032afd
Show file tree
Hide file tree
Showing 36 changed files with 329 additions and 115 deletions.
52 changes: 48 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ version: 2.1
orbs:
gcp-cli: circleci/[email protected]
slack: circleci/[email protected]
utils: ethereum-optimism/[email protected]

parameters:
go_version:
Expand Down Expand Up @@ -52,6 +53,43 @@ commands:
echo "export GOOGLE_APPLICATION_CREDENTIALS='<< parameters.gcp_cred_config_file_path >>'" | tee -a "$BASH_ENV"
jobs:
build-and-deploy:
machine:
image: ubuntu-2004:current
steps:
- checkout
# Fetch more history for diffing
- run:
name: Fetch git history
command: |
git fetch --depth 1000
# Build forkdiff using Docker
- run:
name: Build forkdiff
command: |
docker run --volume $(pwd):/workspace \
protolambda/forkdiff:0.1.0 \
-repo=/workspace \
-fork=/workspace/fork.yaml \
-out=/workspace/index.html
# Prepare pages directory
- run:
name: Build pages
command: |
mkdir -p /tmp/pages
mv index.html /tmp/pages/index.html
touch /tmp/pages/.nojekyll
if [ "$CIRCLE_PROJECT_REPONAME" == "op-geth" ] && [ "$CIRCLE_PROJECT_USERNAME" == "ethereum-optimism" ]; then
echo "op-geth.optimism.io" > /tmp/pages/CNAME
fi
- utils/get-github-access-token:
private-key-str: GITHUB_APP_KEY
app-id: GITHUB_APP_ID
repo: $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
- utils/github-pages-deploy:
src-pages-dir: /tmp/pages
docker-release:
environment:
DOCKER_BUILDKIT: 1
Expand Down Expand Up @@ -107,7 +145,7 @@ jobs:
-f Dockerfile .
- when:
condition:
equal: [ true, <<parameters.push_tags>> ]
equal: [true, <<parameters.push_tags>>]
steps:
- run:
name: Tag
Expand Down Expand Up @@ -136,7 +174,6 @@ jobs:
--signer-logging-level="INFO"\
--attestor-key-id="//cloudkms.googleapis.com/v1/projects/$ATTESTOR_PROJECT_NAME/locations/global/keyRings/$ATTESTOR_NAME-key-ring/cryptoKeys/$ATTESTOR_NAME-key/cryptoKeyVersions/1"
build-geth:
docker:
- image: cimg/go:<<pipeline.parameters.go_version>>
Expand Down Expand Up @@ -182,7 +219,6 @@ jobs:
event: fail
template: basic_fail_1


workflows:
main:
jobs:
Expand Down Expand Up @@ -228,8 +264,16 @@ workflows:
cron: "0 0 * * *"
filters:
branches:
only: [ "optimism" ]
only: ["optimism"]
jobs:
- check-releases:
name: Check for new upstream releases
context: slack

merge:
jobs:
- build-and-deploy:
context: circleci-repo-op-geth
filters:
branches:
only: optimism
Empty file removed .github/workflows/go.yml
Empty file.
36 changes: 0 additions & 36 deletions .github/workflows/pages.yaml

This file was deleted.

6 changes: 6 additions & 0 deletions beacon/engine/gen_ed.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 22 additions & 4 deletions beacon/engine/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ type ExecutableData struct {
ExcessBlobGas *uint64 `json:"excessBlobGas"`
Deposits types.Deposits `json:"depositRequests"`
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`

// OP-Stack Isthmus specific field:
// instead of computing the root from a withdrawals list, set it directly.
// The "withdrawals" list attribute must be non-nil but empty.
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
}

// JSON type overrides for executableData.
Expand Down Expand Up @@ -225,8 +230,8 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
// and that the blockhash of the constructed block matches the parameters. Nil
// Withdrawals value will propagate through the returned block. Empty
// Withdrawals value must be passed via non-nil, length 0 value in data.
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot)
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, bType types.BlockType) (*types.Block, error) {
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot, bType)
if err != nil {
return nil, err
}
Expand All @@ -239,7 +244,7 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
// ExecutableDataToBlockNoHash is analogous to ExecutableDataToBlock, but is used
// for stateless execution, so it skips checking if the executable data hashes to
// the requested hash (stateless has to *compute* the root hash, it's not given).
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, bType types.BlockType) (*types.Block, error) {
txs, err := decodeTransactions(data.Transactions)
if err != nil {
return nil, err
Expand Down Expand Up @@ -270,7 +275,18 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
// ExecutableData before withdrawals are enabled by marshaling
// Withdrawals as the json null value.
var withdrawalsRoot *common.Hash
if data.Withdrawals != nil {
if bType.HasOptimismWithdrawalsRoot(data.Timestamp) {
if data.WithdrawalsRoot == nil {
return nil, fmt.Errorf("attribute WithdrawalsRoot is required for Isthmus blocks")
}
if data.Withdrawals == nil || len(data.Withdrawals) > 0 {
return nil, fmt.Errorf("expected non-nil empty withdrawals operation list in Isthmus, but got: %v", data.Withdrawals)
}
}
if data.WithdrawalsRoot != nil {
h := *data.WithdrawalsRoot // copy, avoid any sharing of memory
withdrawalsRoot = &h
} else if data.Withdrawals != nil {
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
withdrawalsRoot = &h
}
Expand Down Expand Up @@ -337,6 +353,8 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
BlobGasUsed: block.BlobGasUsed(),
ExcessBlobGas: block.ExcessBlobGas(),
ExecutionWitness: block.ExecutionWitness(),
// OP-Stack addition: withdrawals list alone does not express the withdrawals storage-root.
WithdrawalsRoot: block.WithdrawalsRoot(),
}
bundle := BlobsBundleV1{
Commitments: make([]hexutil.Bytes, 0),
Expand Down
15 changes: 14 additions & 1 deletion consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,21 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
// Assign the final state root to header.
header.Root = state.IntermediateRoot(true)

if chain.Config().IsOptimismIsthmus(header.Time) {
if body.Withdrawals == nil || len(body.Withdrawals) > 0 { // We verify nil/empty withdrawals in the CL pre-Isthmus
return nil, fmt.Errorf("expected non-nil empty withdrawals operation list in Isthmus, but got: %v", body.Withdrawals)
}
// State-root has just been computed, we can get an accurate storage-root now.
h := state.GetStorageRoot(params.OptimismL2ToL1MessagePasser)
header.WithdrawalsHash = &h
sa := state.AccessEvents()
if sa != nil {
sa.AddAccount(params.OptimismL2ToL1MessagePasser, false) // include in execution witness
}
}

// Assemble the final block.
block := types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))
block := types.NewBlock(header, body, receipts, trie.NewStackTrie(nil), chain.Config())

// Create the block witness and attach to block.
// This step needs to happen as late as possible to catch all access events.
Expand Down
4 changes: 2 additions & 2 deletions consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
}
// Verify the non-existence of withdrawalsHash.
if header.WithdrawalsHash != nil {
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
return fmt.Errorf("invalid withdrawalsHash: have %s, expected nil", header.WithdrawalsHash)
}
if chain.Config().IsCancun(header.Number, header.Time) {
return errors.New("clique does not support cancun fork")
Expand Down Expand Up @@ -597,7 +597,7 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))

// Assemble and return the final block for sealing.
return types.NewBlock(header, &types.Body{Transactions: body.Transactions}, receipts, trie.NewStackTrie(nil)), nil
return types.NewBlock(header, &types.Body{Transactions: body.Transactions}, receipts, trie.NewStackTrie(nil), chain.Config()), nil
}

// Authorize injects a private key into the consensus engine to mint new blocks
Expand Down
4 changes: 2 additions & 2 deletions consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
}
// Verify the non-existence of withdrawalsHash.
if header.WithdrawalsHash != nil {
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
return fmt.Errorf("invalid withdrawalsHash: have %s, expected nil", header.WithdrawalsHash)
}
if chain.Config().IsCancun(header.Number, header.Time) {
return errors.New("ethash does not support cancun fork")
Expand Down Expand Up @@ -520,7 +520,7 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))

// Header seems complete, assemble into a block and return
return types.NewBlock(header, &types.Body{Transactions: body.Transactions, Uncles: body.Uncles}, receipts, trie.NewStackTrie(nil)), nil
return types.NewBlock(header, &types.Body{Transactions: body.Transactions, Uncles: body.Uncles, Withdrawals: body.Withdrawals}, receipts, trie.NewStackTrie(nil), chain.Config()), nil
}

// SealHash returns the hash of a block prior to it being sealed.
Expand Down
18 changes: 16 additions & 2 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,13 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
if block.Withdrawals() == nil {
return errors.New("missing withdrawals in block body")
}
if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash {
return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash)
if v.config.IsOptimismIsthmus(header.Time) {
if len(block.Withdrawals()) > 0 {
return errors.New("no withdrawal block-operations allowed, withdrawalsRoot is set to storage root")
}
// The withdrawalsHash is verified in ValidateState, like the state root, as verification requires state merkleization.
} else if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash {
return fmt.Errorf("withdrawals root hash mismatch (header value %s, calculated %s)", *header.WithdrawalsHash, hash)
}
} else if block.Withdrawals() != nil {
// Withdrawals are not allowed prior to Shanghai fork
Expand Down Expand Up @@ -155,6 +160,15 @@ 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 v.config.IsOptimismIsthmus(block.Time()) {
if header.WithdrawalsHash == nil {
return errors.New("expected withdrawals root in OP-Stack post-Isthmus block header")
}
// Validate the withdrawals root against the L2 withdrawals storage, similar to how the StateRoot is verified.
if root := statedb.GetStorageRoot(params.OptimismL2ToL1MessagePasser); *header.WithdrawalsHash != root {
return fmt.Errorf("invalid withdrawals hash (remote: %s local: %s) dberr: %w", *header.WithdrawalsHash, root, statedb.Error())
}
}
return nil
}

Expand Down
5 changes: 5 additions & 0 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,11 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
b.header.Difficulty = big.NewInt(0)
}
}
if config.IsOptimismIsthmus(b.header.Time) {
b.withdrawals = make([]*types.Withdrawal, 0)
h := types.EmptyWithdrawalsHash
b.header.WithdrawalsHash = &h
}
// Mutate the state and block according to any hard-fork specs
if daoBlock := config.DAOForkBlock; daoBlock != nil {
limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
Expand Down
Loading

0 comments on commit 6032afd

Please sign in to comment.