@@ -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,31 +51,12 @@ 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 )
73- t .Require ().NoError (err )
74- l1BlobBaseFee := calcBlobBaseFee (l1ChainConfig , l1OriginInfo )
56+ l2UnsafeHash , l1BlobBaseFee := waitForBlockWithDivergentBlobBaseFee (t , sys )
7557
7658 // Get the L1 blob base fee from the system deposit tx.
77- info , txs , err := sys .L2EL .Escape ().EthClient ().InfoAndTxsByHash (t .Ctx (), l2UnsafeRef . Hash )
59+ info , txs , err := sys .L2EL .Escape ().EthClient ().InfoAndTxsByHash (t .Ctx (), l2UnsafeHash )
7860 t .Require ().NoError (err )
7961 blockInfo , err := derive .L1BlockInfoFromBytes (sys .L2Chain .Escape ().RollupConfig (), info .Time (), txs [0 ].Data ())
8062 t .Require ().NoError (err )
@@ -90,6 +72,49 @@ func TestBlobBaseFeeIsCorrectAfterBPOFork(gt *testing.T) {
9072 t .Require ().Equal (l1BlobBaseFee , l2BlobBaseFee )
9173}
9274
75+ // waitForBlockWithDivergentBlobBaseFee will return an L1 blob base fee that can only be calculated
76+ // using the correct BPO1 parameters (i.e., the Osaka parameters result in a different value). It
77+ // also returns an L2 block hash from the same epoch.
78+ func waitForBlockWithDivergentBlobBaseFee (t devtest.T , sys * presets.Minimal ) (common.Hash , * big.Int ) {
79+ l1ChainConfig := sys .L1Network .Escape ().ChainConfig ()
80+ l1BlockTime := sys .L1EL .EstimateBlockTime ()
81+ for {
82+ select {
83+ case <- t .Ctx ().Done ():
84+ t .Require ().Fail ("context canceled before finding a block with a divergent base fee" )
85+ case <- time .After (l1BlockTime ):
86+ }
87+
88+ l2UnsafeRef := sys .L2CL .SyncStatus ().UnsafeL2
89+
90+ l1Info , _ , err := sys .L1EL .EthClient ().InfoAndTxsByHash (t .Ctx (), l2UnsafeRef .L1Origin .Hash )
91+ if errors .Is (err , ethereum .NotFound ) { // Possible reorg, try again.
92+ continue
93+ }
94+ sys .T .Require ().NoError (err )
95+
96+ // Note that we don't need to worry about the reserve blob gas price set by EIP-7918
97+ // because it depends on the blob parameters (if it didn't, we would also need to wait for
98+ // the L1 blob base fee to be different from the reserve price).
99+
100+ // Calculate expected blob base fee with old Osaka parameters.
101+ osakaBlobBaseFee := eip4844 .CalcBlobFee (l1ChainConfig , & types.Header {
102+ Time : * l1ChainConfig .OsakaTime + 1 ,
103+ ExcessBlobGas : l1Info .ExcessBlobGas (),
104+ })
105+
106+ // Calculate expected blob base fee with new BPO1 parameters.
107+ bpo1BlobBaseFee := eip4844 .CalcBlobFee (l1ChainConfig , & types.Header {
108+ Time : l1Info .Time (),
109+ ExcessBlobGas : l1Info .ExcessBlobGas (),
110+ })
111+
112+ if bpo1BlobBaseFee .Cmp (osakaBlobBaseFee ) != 0 {
113+ return l2UnsafeRef .Hash , bpo1BlobBaseFee
114+ }
115+ }
116+ }
117+
93118func spamBlobs (t devtest.T , sys * presets.Minimal ) {
94119 l1BlockTime := sys .L1EL .EstimateBlockTime ()
95120 l1ChainConfig := sys .L1Network .Escape ().ChainConfig ()
@@ -133,12 +158,3 @@ func spamBlobs(t devtest.T, sys *presets.Minimal) {
133158 schedule .Run (t .WithCtx (ctx ), spammer )
134159 }()
135160}
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