@@ -17,13 +17,19 @@ import (
1717 "morph-l2/node/zstd"
1818)
1919
20+ const (
21+ // BlockContextLegacyLength is the length of a legacy block context without coinbase
22+ BlockContextLegacyLength = 60
23+ )
24+
2025type BlockContext struct {
2126 Number uint64 `json:"number"`
2227 Timestamp uint64 `json:"timestamp"`
2328 BaseFee * big.Int
2429 GasLimit uint64
2530 txsNum uint16
2631 l1MsgNum uint16
32+ coinbase common.Address
2733
2834 SafeL2Data * catalyst.SafeL2Data
2935 L2TxHashes []byte
@@ -36,15 +42,18 @@ func (b *BlockContext) Decode(bc []byte) error {
3642 if err != nil {
3743 return err
3844 }
39- b .Number = wb .Number
40- b .Timestamp = wb .Timestamp
4145 b .BaseFee = wb .BaseFee
4246 b .GasLimit = wb .GasLimit
4347 b .txsNum = txsNum
4448 b .l1MsgNum = l1MsgNum
49+ b .coinbase = wb .Miner
4550 return nil
4651}
4752
53+ func decodeCoinbase (bc []byte ) (common.Address , error ) {
54+ return types .DecodeCoinbase (bc )
55+ }
56+
4857type BatchInfo struct {
4958 batchIndex uint64
5059 blockNum uint64
@@ -79,143 +88,168 @@ func (bi *BatchInfo) TxNum() uint64 {
7988}
8089
8190// ParseBatch This method is externally referenced for parsing Batch
82- func (bi * BatchInfo ) ParseBatch (batch geth.RPCRollupBatch ) error {
91+ func (bi * BatchInfo ) ParseBatch (batch geth.RPCRollupBatch , morph204Time uint64 ) error {
92+ if len (batch .Sidecar .Blobs ) == 0 {
93+ return fmt .Errorf ("blobs length can not be zero" )
94+ }
95+
96+ // Parse parent batch header
8397 parentBatchHeader := types .BatchHeaderBytes (batch .ParentBatchHeader )
8498 parentBatchIndex , err := parentBatchHeader .BatchIndex ()
8599 if err != nil {
86- return fmt .Errorf ("decode batch header index error:%v" , err )
100+ return fmt .Errorf ("decode batch header index error: %v" , err )
87101 }
102+
88103 totalL1MessagePopped , err := parentBatchHeader .TotalL1MessagePopped ()
89104 if err != nil {
90- return fmt .Errorf ("decode batch header totalL1MessagePopped error:%v" , err )
105+ return fmt .Errorf ("decode batch header totalL1MessagePopped error: %v" , err )
91106 }
107+
108+ // Initialize batch info fields
92109 bi .parentTotalL1MessagePopped = totalL1MessagePopped
93110 bi .root = batch .PostStateRoot
94111 bi .batchIndex = parentBatchIndex + 1
95112 bi .withdrawalRoot = batch .WithdrawRoot
96113 bi .version = uint64 (batch .Version )
114+
97115 tq := newTxQueue ()
98- var rawBlockContexts hexutil.Bytes
99- var txsData []byte
116+ var rawBlockContextsAndTxs hexutil.Bytes
117+
118+ // Handle version upgrade scenario
119+ blobData , err := types .RetrieveBlobBytes (& batch .Sidecar .Blobs [0 ])
120+ if err != nil {
121+ return fmt .Errorf ("retrieve blob bytes error: %v" , err )
122+ }
123+
124+ batchBytes , err := zstd .DecompressBatchBytes (blobData )
125+ if err != nil {
126+ return fmt .Errorf ("decompress batch bytes error: %v" , err )
127+ }
128+
129+ // Calculate block count based on version
100130 var blockCount uint64
101131 if batch .Version > 0 {
102- parentVersion , err := parentBatchHeader .Version ()
103- if err != nil {
104- return fmt .Errorf ("decode batch header version error:%v" , err )
105- }
106- if parentVersion == 0 {
107- if len (batch .Sidecar .Blobs ) == 0 {
108- return fmt .Errorf ("blobs length can not be zero" )
109- }
110- blobData , err := types .RetrieveBlobBytes (& batch .Sidecar .Blobs [0 ])
111- if err != nil {
112- return err
113- }
114- batchBytes , err := zstd .DecompressBatchBytes (blobData )
115- if err != nil {
116- return fmt .Errorf ("decompress batch bytes error:%v" , err )
117- }
118- var startBlock BlockContext
119- if err := startBlock .Decode (batchBytes [:60 ]); err != nil {
120- return fmt .Errorf ("decode chunk block context error:%v" , err )
121- }
122- blockCount = batch .LastBlockNumber - startBlock .Number + 1
123- } else {
124- parentBatchBlock , err := parentBatchHeader .LastBlockNumber ()
125- if err != nil {
126- return fmt .Errorf ("decode batch header lastBlockNumber error:%v" , err )
127- }
128- blockCount = batch .LastBlockNumber - parentBatchBlock
132+ rawBlockContextsAndTxs = batchBytes
133+ // Ensure we have enough data for block context
134+ if len (batchBytes ) < 60 {
135+ return fmt .Errorf ("insufficient batch bytes for block context, got %d bytes" , len (batchBytes ))
129136 }
130137
131- }
132- // If BlockContexts is not nil, the block context should not be included in the blob.
133- // Therefore, the required length must be zero.
134- length := blockCount * 60
135- for _ , blob := range batch .Sidecar .Blobs {
136- blobCopy := blob
137- blobData , err := types .RetrieveBlobBytes (& blobCopy )
138- if err != nil {
139- return err
138+ var startBlock BlockContext
139+ // coinbase does not enter batch at this time
140+ if err := startBlock .Decode (batchBytes [:60 ]); err != nil {
141+ return fmt .Errorf ("decode chunk block context error: %v" , err )
140142 }
141- batchBytes , err := zstd .DecompressBatchBytes (blobData )
142- if err != nil {
143- return err
144- }
145- reader := bytes .NewReader (batchBytes )
146- if batch .BlockContexts == nil {
147- if len (batchBytes ) < int (length ) {
148- rawBlockContexts = append (rawBlockContexts , batchBytes ... )
149- length -= uint64 (len (batchBytes ))
150- reader .Reset (nil )
151- } else {
152- bcBytes := make ([]byte , length )
153- _ , err = reader .Read (bcBytes )
154- if err != nil {
155- return fmt .Errorf ("read block context error:%s" , err .Error ())
156- }
157- rawBlockContexts = append (rawBlockContexts , bcBytes ... )
158- length = 0
159- }
160- }
161- data , err := io .ReadAll (reader )
162- if err != nil {
163- return fmt .Errorf ("read txBytes error:%s" , err .Error ())
143+
144+ blockCount = batch .LastBlockNumber - startBlock .Number + 1
145+ } else {
146+ // First 2 bytes contain the block count
147+ if len (batch .BlockContexts ) < 2 {
148+ return fmt .Errorf ("insufficient block contexts data: %d bytes" , len (batch .BlockContexts ))
164149 }
165- txsData = append (txsData , data ... )
166- }
167- if batch .BlockContexts != nil {
150+
168151 blockCount = uint64 (binary .BigEndian .Uint16 (batch .BlockContexts [:2 ]))
169- rawBlockContexts = batch .BlockContexts [2 : 60 * blockCount + 2 ]
152+ rawBlockContextsAndTxs = append (rawBlockContextsAndTxs , batch .BlockContexts [2 :]... )
153+ rawBlockContextsAndTxs = append (rawBlockContextsAndTxs , batchBytes ... )
170154 }
171- data , err := types .DecodeTxsFromBytes (txsData )
172- if err != nil {
173- return err
174- }
175- tq .enqueue (data )
155+
176156 var txsNum uint64
177- var l1MsgNum uint64
178157 blockContexts := make ([]* BlockContext , int (blockCount ))
158+
159+ reader := bytes .NewReader (rawBlockContextsAndTxs )
160+ // Process block contexts
179161 for i := 0 ; i < int (blockCount ); i ++ {
180162 var block BlockContext
181- if err := block .Decode (rawBlockContexts [i * 60 : i * 60 + 60 ]); err != nil {
182- return fmt .Errorf ("decode chunk block context error:%v" , err )
163+ bcBytes := make ([]byte , BlockContextLegacyLength )
164+ _ , err = reader .Read (bcBytes )
165+ if err != nil {
166+ return fmt .Errorf ("read block context numberAndTimeBytes error:%s" , err .Error ())
167+ }
168+ if err := block .Decode (bcBytes ); err != nil {
169+ return fmt .Errorf ("decode number and timestamp error: %v" , err )
170+ }
171+ var coinbase common.Address
172+ // handle coinbase
173+ if morph204Time != 0 && block .Timestamp >= morph204Time {
174+ coinbaseBytes := make ([]byte , common .AddressLength )
175+ _ , err = reader .Read (coinbaseBytes )
176+ if err != nil {
177+ return fmt .Errorf ("read skipped block context error:%s" , err .Error ())
178+ }
179+
180+ coinbase , err = decodeCoinbase (coinbaseBytes )
181+ if err != nil {
182+ return err
183+ }
183184 }
185+
186+ // Set boundary block numbers
184187 if i == 0 {
185188 bi .firstBlockNumber = block .Number
186189 }
187190 if i == int (blockCount )- 1 {
188191 bi .lastBlockNumber = block .Number
189192 }
193+
194+ // Setup SafeL2Data
190195 var safeL2Data catalyst.SafeL2Data
191196 safeL2Data .Number = block .Number
192197 safeL2Data .GasLimit = block .GasLimit
193198 safeL2Data .BaseFee = block .BaseFee
194199 safeL2Data .Timestamp = block .Timestamp
200+ // TODO coinbase
201+ fmt .Println (coinbase )
202+
203+ // Handle zero BaseFee case
195204 if block .BaseFee != nil && block .BaseFee .Cmp (big .NewInt (0 )) == 0 {
196205 safeL2Data .BaseFee = nil
197206 }
207+
208+ // Validate transaction numbers
198209 if block .txsNum < block .l1MsgNum {
199- return fmt .Errorf ("txsNum must be or equal to or greater than l1MsgNum,txsNum:%v,l1MsgNum:%v" , block .txsNum , block .l1MsgNum )
200- }
201- var txs []* eth.Transaction
202- var err error
203- if len (batch .Sidecar .Blobs ) != 0 {
204- txs , err = tq .dequeue (int (block .txsNum ) - int (block .l1MsgNum ))
205- if err != nil {
206- return fmt .Errorf ("decode txsPayload error:%v" , err )
207- }
210+ return fmt .Errorf ("txsNum must be greater than or equal to l1MsgNum, txsNum: %v, l1MsgNum: %v" ,
211+ block .txsNum , block .l1MsgNum )
208212 }
209- txsNum += uint64 (block .txsNum )
210- l1MsgNum += uint64 (block .l1MsgNum )
211- // l1 transactions will be inserted later in front of L2 transactions
212- safeL2Data .Transactions = encodeTransactions (txs )
213- block .SafeL2Data = & safeL2Data
214213
214+ block .SafeL2Data = & safeL2Data
215215 blockContexts [i ] = & block
216216 }
217+
218+ // Read transaction data
219+ txsData , err := io .ReadAll (reader )
220+ if err != nil {
221+ return fmt .Errorf ("read transaction data error: %s" , err .Error ())
222+ }
223+
224+ // Decode transactions
225+ data , err := types .DecodeTxsFromBytes (txsData )
226+ if err != nil {
227+ return fmt .Errorf ("decode transactions error: %v" , err )
228+ }
229+
230+ // Process transactions
231+ tq .enqueue (data )
232+
233+ for i := 0 ; i < int (blockCount ); i ++ {
234+ // Skip if index is out of bounds
235+ if i >= len (blockContexts ) {
236+ return fmt .Errorf ("block context index out of bounds: %d >= %d" , i , len (blockContexts ))
237+ }
238+
239+ txCount := int (blockContexts [i ].txsNum ) - int (blockContexts [i ].l1MsgNum )
240+ txs , err := tq .dequeue (txCount )
241+ if err != nil {
242+ return fmt .Errorf ("decode transaction payload error: %v" , err )
243+ }
244+
245+ txsNum += uint64 (blockContexts [i ].txsNum )
246+ // l1 transactions will be inserted later in front of L2 transactions
247+ blockContexts [i ].SafeL2Data .Transactions = encodeTransactions (txs )
248+ }
249+
217250 bi .txNum += txsNum
218251 bi .blockContexts = blockContexts
252+
219253 return nil
220254}
221255
0 commit comments