Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions op-e2e/actions/fork_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package actions

import (
"testing"

"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"

"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/testlog"
)

func TestShapellaL1Fork(gt *testing.T) {
t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)

sd := e2eutils.Setup(t, dp, defaultAlloc)
activation := sd.L1Cfg.Timestamp + 24
sd.L1Cfg.Config.ShanghaiTime = &activation
log := testlog.Logger(t, log.LvlDebug)

_, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log)

require.False(t, sd.L1Cfg.Config.IsShanghai(miner.l1Chain.CurrentBlock().Time()), "not active yet")

// start op-nodes
sequencer.ActL2PipelineFull(t)
verifier.ActL2PipelineFull(t)

// build empty L1 blocks, crossing the fork boundary
miner.ActEmptyBlock(t)
miner.ActEmptyBlock(t)
miner.ActEmptyBlock(t)

// verify Shanghai is active
l1Head := miner.l1Chain.CurrentBlock()
require.True(t, sd.L1Cfg.Config.IsShanghai(l1Head.Time()))

// build L2 chain up to and including L2 blocks referencing shanghai L1 blocks
sequencer.ActL1HeadSignal(t)
sequencer.ActBuildToL1Head(t)
miner.ActL1StartBlock(12)(t)
batcher.ActSubmitAll(t)
miner.ActL1IncludeTx(batcher.batcherAddr)(t)
miner.ActL1EndBlock(t)

// sync verifier
verifier.ActL1HeadSignal(t)
verifier.ActL2PipelineFull(t)
// verify verifier accepted shanghai L1 inputs
require.Equal(t, l1Head.Hash(), verifier.SyncStatus().SafeL2.L1Origin.Hash, "verifier synced L1 chain that includes shanghai headers")
require.Equal(t, sequencer.SyncStatus().UnsafeL2, verifier.SyncStatus().UnsafeL2, "verifier and sequencer agree")
}
6 changes: 6 additions & 0 deletions op-e2e/actions/l1_miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action {
header.GasLimit = parent.GasLimit * s.l1Cfg.Config.ElasticityMultiplier()
}
}
if s.l1Cfg.Config.IsShanghai(header.Time) {
header.WithdrawalsHash = &types.EmptyWithdrawalsHash
}

s.l1Building = true
s.l1BuildingHeader = header
Expand Down Expand Up @@ -135,6 +138,9 @@ func (s *L1Miner) ActL1EndBlock(t Testing) {
s.l1BuildingHeader.GasUsed = s.l1BuildingHeader.GasLimit - uint64(*s.l1GasPool)
s.l1BuildingHeader.Root = s.l1BuildingState.IntermediateRoot(s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number))
block := types.NewBlock(s.l1BuildingHeader, s.l1Transactions, nil, s.l1Receipts, trie.NewStackTrie(nil))
if s.l1Cfg.Config.IsShanghai(s.l1BuildingHeader.Time) {
block = block.WithWithdrawals(make([]*types.Withdrawal, 0))
}

// Write state changes to db
root, err := s.l1BuildingState.Commit(s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number))
Expand Down
64 changes: 36 additions & 28 deletions op-node/sources/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ type HeaderInfo struct {
txHash common.Hash
receiptHash common.Hash
gasUsed uint64

// withdrawalsRoot was added in Shapella and is thus optional
withdrawalsRoot *common.Hash
}

var _ eth.BlockInfo = (*HeaderInfo)(nil)
Expand Down Expand Up @@ -113,7 +116,10 @@ type rpcHeader struct {
Nonce types.BlockNonce `json:"nonce"`

// BaseFee was added by EIP-1559 and is ignored in legacy headers.
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
BaseFee *hexutil.Big `json:"baseFeePerGas"`

// WithdrawalsRoot was added by EIP-4895 and is ignored in legacy headers.
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot"`

// untrusted info included by RPC, may have to be checked
Hash common.Hash `json:"hash"`
Expand Down Expand Up @@ -144,22 +150,23 @@ func (hdr *rpcHeader) checkPostMerge() error {

func (hdr *rpcHeader) computeBlockHash() common.Hash {
gethHeader := types.Header{
ParentHash: hdr.ParentHash,
UncleHash: hdr.UncleHash,
Coinbase: hdr.Coinbase,
Root: hdr.Root,
TxHash: hdr.TxHash,
ReceiptHash: hdr.ReceiptHash,
Bloom: types.Bloom(hdr.Bloom),
Difficulty: (*big.Int)(&hdr.Difficulty),
Number: new(big.Int).SetUint64(uint64(hdr.Number)),
GasLimit: uint64(hdr.GasLimit),
GasUsed: uint64(hdr.GasUsed),
Time: uint64(hdr.Time),
Extra: hdr.Extra,
MixDigest: hdr.MixDigest,
Nonce: hdr.Nonce,
BaseFee: (*big.Int)(hdr.BaseFee),
ParentHash: hdr.ParentHash,
UncleHash: hdr.UncleHash,
Coinbase: hdr.Coinbase,
Root: hdr.Root,
TxHash: hdr.TxHash,
ReceiptHash: hdr.ReceiptHash,
Bloom: types.Bloom(hdr.Bloom),
Difficulty: (*big.Int)(&hdr.Difficulty),
Number: new(big.Int).SetUint64(uint64(hdr.Number)),
GasLimit: uint64(hdr.GasLimit),
GasUsed: uint64(hdr.GasUsed),
Time: uint64(hdr.Time),
Extra: hdr.Extra,
MixDigest: hdr.MixDigest,
Nonce: hdr.Nonce,
BaseFee: (*big.Int)(hdr.BaseFee),
WithdrawalsHash: hdr.WithdrawalsRoot,
}
return gethHeader.Hash()
}
Expand All @@ -177,17 +184,18 @@ func (hdr *rpcHeader) Info(trustCache bool, mustBePostMerge bool) (*HeaderInfo,
}

info := HeaderInfo{
hash: hdr.Hash,
parentHash: hdr.ParentHash,
coinbase: hdr.Coinbase,
root: hdr.Root,
number: uint64(hdr.Number),
time: uint64(hdr.Time),
mixDigest: hdr.MixDigest,
baseFee: (*big.Int)(hdr.BaseFee),
txHash: hdr.TxHash,
receiptHash: hdr.ReceiptHash,
gasUsed: uint64(hdr.GasUsed),
hash: hdr.Hash,
parentHash: hdr.ParentHash,
coinbase: hdr.Coinbase,
root: hdr.Root,
number: uint64(hdr.Number),
time: uint64(hdr.Time),
mixDigest: hdr.MixDigest,
baseFee: (*big.Int)(hdr.BaseFee),
txHash: hdr.TxHash,
receiptHash: hdr.ReceiptHash,
gasUsed: uint64(hdr.GasUsed),
withdrawalsRoot: hdr.WithdrawalsRoot,
}
return &info, nil
}
Expand Down
Loading