77 "math/big"
88 "testing"
99
10+ "github.com/ethereum-optimism/optimism/op-service/eth"
11+ "github.com/ethereum/go-ethereum/common"
1012 "github.com/ethereum/go-ethereum/core/types"
1113 "github.com/stretchr/testify/require"
1214 "github.com/taikoxyz/gaiko/tests/fixtures"
@@ -64,6 +66,75 @@ func TestShastaGuestInputsDoesNotFallbackToDefaultManifest(t *testing.T) {
6466 require .Equal (t , len (input .Inputs ), count )
6567}
6668
69+ func TestShastaDefaultManifest_ForceInclusionUsesLastAnchor (t * testing.T ) {
70+ var observedAnchor uint64
71+ shastaDefaultManifestObserver = func (anchorBlockNumber uint64 , isForceInclusion bool ) {
72+ if isForceInclusion {
73+ observedAnchor = anchorBlockNumber
74+ }
75+ }
76+ defer func () {
77+ shastaDefaultManifestObserver = nil
78+ }()
79+
80+ input := BatchGuestInput {
81+ Inputs : []* SingleGuestInput {makeShastaGuestInputWithAnchorTx (20 , 21 , 200 , 30_000_000 , false )},
82+ Taiko : & TaikoGuestBatchInput {
83+ BatchID : 1 ,
84+ BatchProposed : NewShastaBlockProposed (& ShastaEventData {
85+ Proposal : ShastaProposal {
86+ Timestamp : 200 ,
87+ Proposer : common.Address {0x11 },
88+ OriginBlockNumber : 99 ,
89+ OriginBlockHash : common.Hash {0x22 },
90+ ParentProposalHash : common.Hash {0x33 },
91+ Sources : []ShastaDerivationSource {
92+ {
93+ IsForcedInclusion : true ,
94+ BlobSlice : ShastaBlobSlice {
95+ Offset : 0 ,
96+ },
97+ },
98+ {
99+ IsForcedInclusion : false ,
100+ BlobSlice : ShastaBlobSlice {
101+ Offset : 0 ,
102+ },
103+ },
104+ },
105+ },
106+ }),
107+ ChainSpec : & ChainSpec {
108+ Name : TaikoDevNetwork ,
109+ ChainID : 1 ,
110+ MaxSpecID : SpecID (ShastaHardFork ),
111+ HardForks : HardForks {{SpecID : SpecID (ShastaHardFork ), Condition : BlockNumber (0 )}},
112+ Eip1559Constants : & Eip1559Constants {
113+ BaseFeeChangeDenominator : big .NewInt (8 ),
114+ BaseFeeMaxIncreaseDenominator : big .NewInt (8 ),
115+ BaseFeeMaxDecreaseDenominator : big .NewInt (8 ),
116+ ElasticityMultiplier : big .NewInt (2 ),
117+ },
118+ L1Contract : map [SpecID ]* common.Address {},
119+ VerifierAddressForks : map [SpecID ]VerifierAddressFork {},
120+ GenesisTime : 0 ,
121+ SecondsPerSlot : 12 ,
122+ IsTaiko : true ,
123+ },
124+ ProverData : & TaikoProverData {
125+ LastAnchorBlockNumber : 42 ,
126+ },
127+ DataSources : []* TaikoGuestDataSource {
128+ {IsForcedInclusion : true , TxDataFromBlob : emptyManifestBlob ()},
129+ {IsForcedInclusion : false , TxDataFromBlob : emptyManifestBlob ()},
130+ },
131+ },
132+ }
133+
134+ collectGuestInputs (& input )
135+ require .Equal (t , uint64 (42 ), observedAnchor )
136+ }
137+
67138func TestShastaAnchorLinkageDecodesCheckpoint (t * testing.T ) {
68139 payload , err := fixtures .ReadShastaFixture ("input-52.json" )
69140 require .NoError (t , err )
@@ -84,6 +155,90 @@ func TestShastaAnchorLinkageDecodesCheckpoint(t *testing.T) {
84155 ))
85156}
86157
158+ func makeShastaGuestInput (parentNumber uint64 , blockNumber uint64 , timestamp uint64 , gasLimit uint64 ) * SingleGuestInput {
159+ return makeShastaGuestInputWithAnchorTx (parentNumber , blockNumber , timestamp , gasLimit , true )
160+ }
161+
162+ func makeShastaGuestInputWithAnchorTx (
163+ parentNumber uint64 ,
164+ blockNumber uint64 ,
165+ timestamp uint64 ,
166+ gasLimit uint64 ,
167+ withAnchorTx bool ,
168+ ) * SingleGuestInput {
169+ parentHeader := & types.Header {
170+ Number : new (big.Int ).SetUint64 (parentNumber ),
171+ Time : timestamp - 1 ,
172+ GasLimit : gasLimit ,
173+ GasUsed : gasLimit - 1 ,
174+ BaseFee : big .NewInt (5_000_000 ),
175+ }
176+ blockHeader := & types.Header {
177+ Number : new (big.Int ).SetUint64 (blockNumber ),
178+ ParentHash : parentHeader .Hash (),
179+ Time : timestamp ,
180+ GasLimit : gasLimit ,
181+ GasUsed : gasLimit - 2 ,
182+ BaseFee : big .NewInt (5_000_000 ),
183+ }
184+ block := types .NewBlockWithHeader (blockHeader )
185+
186+ var anchorTx * types.Transaction
187+ if withAnchorTx {
188+ anchorTx = types .NewTx (& types.LegacyTx {Data : make ([]byte , 4 )})
189+ }
190+
191+ return & SingleGuestInput {
192+ Block : block ,
193+ ParentHeader : parentHeader ,
194+ ChainSpec : & ChainSpec {
195+ Name : TaikoDevNetwork ,
196+ ChainID : 1 ,
197+ MaxSpecID : SpecID (ShastaHardFork ),
198+ HardForks : HardForks {{SpecID : SpecID (ShastaHardFork ), Condition : BlockNumber (0 )}},
199+ Eip1559Constants : & Eip1559Constants {
200+ BaseFeeChangeDenominator : big .NewInt (8 ),
201+ BaseFeeMaxIncreaseDenominator : big .NewInt (8 ),
202+ BaseFeeMaxDecreaseDenominator : big .NewInt (8 ),
203+ ElasticityMultiplier : big .NewInt (2 ),
204+ },
205+ L1Contract : map [SpecID ]* common.Address {},
206+ VerifierAddressForks : map [SpecID ]VerifierAddressFork {},
207+ GenesisTime : 0 ,
208+ SecondsPerSlot : 12 ,
209+ IsTaiko : true ,
210+ },
211+ Taiko : & TaikoGuestInput {
212+ AnchorTx : anchorTx ,
213+ },
214+ }
215+ }
216+
217+ func emptyManifestBlob () [][eth .BlobSize ]byte {
218+ var blob [eth .BlobSize ]byte
219+ return [][eth .BlobSize ]byte {blob }
220+ }
221+
222+ func collectGuestInputs (input * BatchGuestInput ) []struct {
223+ input * SingleGuestInput
224+ txs types.Transactions
225+ } {
226+ pairs := make ([]struct {
227+ input * SingleGuestInput
228+ txs types.Transactions
229+ }, 0 )
230+ for pair := range input .GuestInputs () {
231+ pairs = append (pairs , struct {
232+ input * SingleGuestInput
233+ txs types.Transactions
234+ }{
235+ input : pair .Input ,
236+ txs : pair .Txs ,
237+ })
238+ }
239+ return pairs
240+ }
241+
87242func TestValidateShastaBlockBaseFee_UsesGrandparent (t * testing.T ) {
88243 parentHeader := & types.Header {
89244 GasLimit : 16_000_000 ,
0 commit comments