@@ -3,6 +3,7 @@ package fusaka
33import (
44 "context"
55 "crypto/rand"
6+ "errors"
67 "math/big"
78 "sync"
89 "testing"
@@ -18,10 +19,10 @@ import (
1819 "github.com/ethereum-optimism/optimism/op-service/txintent/bindings"
1920 "github.com/ethereum-optimism/optimism/op-service/txintent/contractio"
2021 "github.com/ethereum-optimism/optimism/op-service/txplan"
22+ "github.com/ethereum/go-ethereum"
2123 "github.com/ethereum/go-ethereum/common"
2224 "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
2325 "github.com/ethereum/go-ethereum/core/types"
24- "github.com/ethereum/go-ethereum/params"
2526)
2627
2728func TestSafeHeadAdvancesAfterOsaka (gt * testing.T ) {
@@ -50,46 +51,68 @@ func TestBlobBaseFeeIsCorrectAfterBPOFork(gt *testing.T) {
5051 sys .L1EL .WaitForTime (* sys .L1Network .Escape ().ChainConfig ().BPO1Time )
5152 t .Log ("BPO1 activated" )
5253
53- sys .L1EL .WaitForBlock ()
54- l1BlockTime := sys .L1EL .EstimateBlockTime ()
55- l1ChainConfig := sys .L1Network .Escape ().ChainConfig ()
56-
5754 spamBlobs (t , sys ) // Raise the blob base fee to make blob parameter changes visible.
5855
59- // Wait for the blob base fee to rise above 1 so the blob parameter changes will be visible.
60- for range time .Tick (l1BlockTime ) {
61- info , _ , err := sys .L1EL .EthClient ().InfoAndTxsByLabel (t .Ctx (), eth .Unsafe )
62- t .Require ().NoError (err )
63- if calcBlobBaseFee (l1ChainConfig , info ).Cmp (big .NewInt (1 )) > 0 {
64- break
65- }
66- t .Logf ("Waiting for blob base fee to rise above 1" )
67- }
68-
69- l2UnsafeRef := sys .L2CL .SyncStatus ().UnsafeL2
70-
71- // Get the L1 blob base fee.
72- l1OriginInfo , err := sys .L1EL .EthClient ().InfoByHash (t .Ctx (), l2UnsafeRef .L1Origin .Hash )
56+ l2UnsafeHash , l1BlobBaseFee := waitForBlockWithDivergentBlobBaseFee (t , sys )
57+ l2BlockInfo , l2Txs , err := sys .L2EL .Escape ().EthClient ().InfoAndTxsByHash (t .Ctx (), l2UnsafeHash )
7358 t .Require ().NoError (err )
74- l1BlobBaseFee := calcBlobBaseFee (l1ChainConfig , l1OriginInfo )
7559
7660 // Get the L1 blob base fee from the system deposit tx.
77- info , txs , err := sys .L2EL .Escape ().EthClient ().InfoAndTxsByHash (t .Ctx (), l2UnsafeRef .Hash )
78- t .Require ().NoError (err )
79- blockInfo , err := derive .L1BlockInfoFromBytes (sys .L2Chain .Escape ().RollupConfig (), info .Time (), txs [0 ].Data ())
61+ blockInfo , err := derive .L1BlockInfoFromBytes (sys .L2Chain .Escape ().RollupConfig (), l2BlockInfo .Time (), l2Txs [0 ].Data ())
8062 t .Require ().NoError (err )
8163 l2BlobBaseFee := blockInfo .BlobBaseFee
8264
8365 t .Require ().Equal (l1BlobBaseFee , l2BlobBaseFee )
8466
8567 // Get the L1 Blob base fee from the L1Block contract.
8668 l1Block := bindings .NewL1Block (bindings .WithClient (sys .L2EL .Escape ().EthClient ()), bindings .WithTo (predeploys .L1BlockAddr ))
87- l2BlobBaseFee , err = contractio .Read (l1Block .BlobBaseFee (), t .Ctx ())
69+ l2BlobBaseFee , err = contractio .Read (l1Block .BlobBaseFee (), t .Ctx (), func (tx * txplan.PlannedTx ) {
70+ tx .AgainstBlock .Set (l2BlockInfo )
71+ })
8872 t .Require ().NoError (err )
8973
9074 t .Require ().Equal (l1BlobBaseFee , l2BlobBaseFee )
9175}
9276
77+ // waitForBlockWithDivergentBlobBaseFee will return an L1 blob base fee that can only be calculated
78+ // using the correct BPO1 parameters (i.e., the Osaka parameters result in a different value). It
79+ // also returns an L2 block hash from the same epoch.
80+ func waitForBlockWithDivergentBlobBaseFee (t devtest.T , sys * presets.Minimal ) (common.Hash , * big.Int ) {
81+ l1ChainConfig := sys .L1Network .Escape ().ChainConfig ()
82+ l1BlockTime := sys .L1EL .EstimateBlockTime ()
83+ for {
84+ select {
85+ case <- t .Ctx ().Done ():
86+ t .Require ().Fail ("context canceled before finding a block with a divergent base fee" )
87+ case <- time .After (l1BlockTime ):
88+ }
89+
90+ l2UnsafeRef := sys .L2CL .SyncStatus ().UnsafeL2
91+
92+ l1Info , _ , err := sys .L1EL .EthClient ().InfoAndTxsByHash (t .Ctx (), l2UnsafeRef .L1Origin .Hash )
93+ if errors .Is (err , ethereum .NotFound ) { // Possible reorg, try again.
94+ continue
95+ }
96+ t .Require ().NoError (err )
97+
98+ // Calculate expected blob base fee with old Osaka parameters.
99+ osakaBlobBaseFee := eip4844 .CalcBlobFee (l1ChainConfig , & types.Header {
100+ Time : * l1ChainConfig .OsakaTime ,
101+ ExcessBlobGas : l1Info .ExcessBlobGas (),
102+ })
103+
104+ // Calculate expected blob base fee with new BPO1 parameters.
105+ bpo1BlobBaseFee := eip4844 .CalcBlobFee (l1ChainConfig , & types.Header {
106+ Time : l1Info .Time (),
107+ ExcessBlobGas : l1Info .ExcessBlobGas (),
108+ })
109+
110+ if bpo1BlobBaseFee .Cmp (osakaBlobBaseFee ) != 0 {
111+ return l2UnsafeRef .Hash , bpo1BlobBaseFee
112+ }
113+ }
114+ }
115+
93116func spamBlobs (t devtest.T , sys * presets.Minimal ) {
94117 l1BlockTime := sys .L1EL .EstimateBlockTime ()
95118 l1ChainConfig := sys .L1Network .Escape ().ChainConfig ()
@@ -133,12 +156,3 @@ func spamBlobs(t devtest.T, sys *presets.Minimal) {
133156 schedule .Run (t .WithCtx (ctx ), spammer )
134157 }()
135158}
136-
137- func calcBlobBaseFee (cfg * params.ChainConfig , info eth.BlockInfo ) * big.Int {
138- return eip4844 .CalcBlobFee (cfg , & types.Header {
139- // It's unfortunate that we can't build a proper header from a BlockInfo.
140- // We do our best to work around deficiencies in the BlockInfo implementation here.
141- Time : info .Time (),
142- ExcessBlobGas : info .ExcessBlobGas (),
143- })
144- }
0 commit comments