99 "io"
1010 "time"
1111
12+ "github.com/pkg/errors"
13+
1214 sdk "github.com/cosmos/cosmos-sdk/types"
1315 executortypes "github.com/initia-labs/opinit-bots-go/executor/types"
1416 nodetypes "github.com/initia-labs/opinit-bots-go/node/types"
@@ -27,92 +29,115 @@ func (bs *BatchSubmitter) rawBlockHandler(args nodetypes.RawBlockArgs) error {
2729 pbb := new (cmtproto.Block )
2830 err := proto .Unmarshal (args .BlockBytes , pbb )
2931 if err != nil {
30- return err
32+ return errors . Wrap ( err , "failed to unmarshal block" )
3133 }
3234
3335 err = bs .prepareBatch (args .BlockHeight , pbb .Header .Time )
3436 if err != nil {
35- return err
37+ return errors . Wrap ( err , "failed to prepare batch" )
3638 }
39+
3740 err = bs .handleBatch (args .BlockBytes )
3841 if err != nil {
39- return err
42+ return errors . Wrap ( err , "failed to handle batch" )
4043 }
4144
4245 err = bs .checkBatch (args .BlockHeight , pbb .Header .Time )
4346 if err != nil {
44- return err
47+ return errors . Wrap ( err , "failed to check batch" )
4548 }
4649
50+ // store the processed state into db with batch operation
4751 batchKVs := make ([]types.RawKV , 0 )
4852 batchKVs = append (batchKVs , bs .node .SyncInfoToRawKV (args .BlockHeight ))
49- batchMsgkvs , err := bs .da .ProcessedMsgsToRawKV (bs .processedMsgs , false )
53+ batchMsgKVs , err := bs .da .ProcessedMsgsToRawKV (bs .processedMsgs , false )
5054 if err != nil {
51- return err
55+ return errors . Wrap ( err , "failed to convert processed messages to raw key value" )
5256 }
53- batchKVs = append (batchKVs , batchMsgkvs ... )
54- if len (batchMsgkvs ) > 0 {
57+ batchKVs = append (batchKVs , batchMsgKVs ... )
58+ if len (batchMsgKVs ) > 0 {
5559 batchKVs = append (batchKVs , bs .SubmissionInfoToRawKV (pbb .Header .Time .UnixNano ()))
5660 }
5761 err = bs .db .RawBatchSet (batchKVs ... )
5862 if err != nil {
59- return err
63+ return errors . Wrap ( err , "failed to set raw batch" )
6064 }
65+
66+ // broadcast processed messages
6167 for _ , processedMsg := range bs .processedMsgs {
6268 bs .da .BroadcastMsgs (processedMsg )
6369 }
70+
71+ // clear processed messages
6472 bs .processedMsgs = bs .processedMsgs [:0 ]
73+
6574 return nil
6675}
6776
6877func (bs * BatchSubmitter ) prepareBatch (blockHeight uint64 , blockTime time.Time ) error {
78+
79+ // check whether the requested block height is reached to the l2 block number of the next batch info.
6980 if nextBatchInfo := bs .NextBatchInfo (); nextBatchInfo != nil && nextBatchInfo .Output .L2BlockNumber < blockHeight {
81+
82+ // if the next batch info is reached, finalize the current batch and update the batch info.
7083 if bs .batchWriter != nil {
7184 err := bs .batchWriter .Close ()
7285 if err != nil {
73- return err
86+ return errors . Wrap ( err , "failed to close batch writer" )
7487 }
7588 }
7689 err := bs .batchFile .Truncate (0 )
7790 if err != nil {
78- return err
91+ return errors . Wrap ( err , "failed to truncate batch file" )
7992 }
8093 _ , err = bs .batchFile .Seek (0 , 0 )
8194 if err != nil {
82- return err
95+ return errors . Wrap ( err , "failed to seek batch file" )
8396 }
97+
98+ // save sync info
8499 err = bs .node .SaveSyncInfo (nextBatchInfo .Output .L2BlockNumber )
85100 if err != nil {
86- return err
101+ return errors . Wrap ( err , "failed to save sync info" )
87102 }
103+
88104 // set last processed block height to l2 block number
89105 bs .node .SetSyncInfo (nextBatchInfo .Output .L2BlockNumber )
90- bs .PopBatchInfo ()
106+ bs .DequeueBatchInfo ()
91107
92108 // error will restart block process from nextBatchInfo.Output.L2BlockNumber + 1
93109 return fmt .Errorf ("batch info updated: reset from %d" , nextBatchInfo .Output .L2BlockNumber )
94110 }
95111
96112 if bs .batchHeader != nil {
113+ // if the batch header end is not set, it means the batch is not finalized yet.
97114 if bs .batchHeader .End == 0 {
98115 return nil
99116 }
117+
100118 err := bs .finalizeBatch (blockHeight )
101119 if err != nil {
102- return err
120+ return errors . Wrap ( err , "failed to finalize batch" )
103121 }
122+
123+ // update last submission time
104124 bs .lastSubmissionTime = blockTime
105125 }
106- bs .batchHeader = & executortypes.BatchHeader {}
126+
127+ // reset batch header
107128 var err error
129+ bs .batchHeader = & executortypes.BatchHeader {}
130+
108131 // linux command gzip use level 6 as default
109132 bs .batchWriter , err = gzip .NewWriterLevel (bs .batchFile , 6 )
110133 if err != nil {
111134 return err
112135 }
136+
113137 return nil
114138}
115139
140+ // write block bytes to batch file
116141func (bs * BatchSubmitter ) handleBatch (blockBytes []byte ) error {
117142 encodedBlockBytes := base64 .StdEncoding .EncodeToString (blockBytes )
118143 _ , err := bs .batchWriter .Write (append ([]byte (encodedBlockBytes ), ',' ))
@@ -122,23 +147,27 @@ func (bs *BatchSubmitter) handleBatch(blockBytes []byte) error {
122147 return nil
123148}
124149
150+ // finalize batch and create batch messages
125151func (bs * BatchSubmitter ) finalizeBatch (blockHeight uint64 ) error {
152+
153+ // write last block's commit to batch file
126154 rawCommit , err := bs .node .QueryRawCommit (int64 (blockHeight ))
127155 if err != nil {
128- return err
156+ return errors . Wrap ( err , "failed to query raw commit" )
129157 }
130158 encodedRawCommit := base64 .StdEncoding .EncodeToString (rawCommit )
131159 _ , err = bs .batchWriter .Write ([]byte (encodedRawCommit ))
132160 if err != nil {
133- return err
161+ return errors . Wrap ( err , "failed to write raw commit" )
134162 }
135163 err = bs .batchWriter .Close ()
136164 if err != nil {
137- return err
165+ return errors . Wrap ( err , "failed to close batch writer" )
138166 }
139167
140168 batchBuffer := make ([]byte , bs .batchCfg .MaxChunkSize )
141169 checksums := make ([][]byte , 0 )
170+
142171 // room for batch header
143172 bs .processedMsgs = append (bs .processedMsgs , nodetypes.ProcessedMsgs {
144173 Timestamp : time .Now ().UnixNano (),
@@ -152,7 +181,9 @@ func (bs *BatchSubmitter) finalizeBatch(blockHeight uint64) error {
152181 } else if readLength == 0 {
153182 break
154183 }
155- batchBuffer = batchBuffer [:readLength ]
184+
185+ // trim the buffer to the actual read length
186+ batchBuffer := batchBuffer [:readLength ]
156187 msg , err := bs .createBatchMsg (batchBuffer )
157188 if err != nil {
158189 return err
@@ -168,6 +199,8 @@ func (bs *BatchSubmitter) finalizeBatch(blockHeight uint64) error {
168199 break
169200 }
170201 }
202+
203+ // update batch header
171204 bs .batchHeader .Chunks = checksums
172205 headerBytes , err := json .Marshal (bs .batchHeader )
173206 if err != nil {
@@ -178,6 +211,8 @@ func (bs *BatchSubmitter) finalizeBatch(blockHeight uint64) error {
178211 return err
179212 }
180213 bs .processedMsgs [0 ].Msgs = []sdk.Msg {msg }
214+
215+ // reset batch file
181216 err = bs .batchFile .Truncate (0 )
182217 if err != nil {
183218 return err
@@ -186,23 +221,32 @@ func (bs *BatchSubmitter) finalizeBatch(blockHeight uint64) error {
186221 if err != nil {
187222 return err
188223 }
224+
189225 return nil
190226}
191227
192228func (bs * BatchSubmitter ) checkBatch (blockHeight uint64 , blockTime time.Time ) error {
193229 info , err := bs .batchFile .Stat ()
194230 if err != nil {
195- return err
231+ return errors . Wrap ( err , "failed to get batch file stat" )
196232 }
197233
234+ // if the block time is after the last submission time + submission interval * 2/3
235+ // or the block time is after the last submission time + max submission time
236+ // or the batch file size is greater than (max chunks - 1) * max chunk size
237+ // then finalize the batch
198238 if blockTime .After (bs .lastSubmissionTime .Add (bs .bridgeInfo .BridgeConfig .SubmissionInterval * 2 / 3 )) ||
199239 blockTime .After (bs .lastSubmissionTime .Add (time .Duration (bs .batchCfg .MaxSubmissionTime )* time .Second )) ||
200240 info .Size () > (bs .batchCfg .MaxChunks - 1 )* bs .batchCfg .MaxChunkSize {
241+
242+ // finalize the batch
201243 bs .batchHeader .End = blockHeight
202244 }
245+
203246 return nil
204247}
205248
249+ // TODO: support celestia
206250func (bs * BatchSubmitter ) createBatchMsg (batchBytes []byte ) (sdk.Msg , error ) {
207251 submitter , err := bs .da .GetAddressStr ()
208252 if err != nil {
@@ -216,6 +260,7 @@ func (bs *BatchSubmitter) createBatchMsg(batchBytes []byte) (sdk.Msg, error) {
216260 ), nil
217261}
218262
263+ // UpdateBatchInfo appends the batch info with the given chain, submitter, output index, and l2 block number
219264func (bs * BatchSubmitter ) UpdateBatchInfo (chain string , submitter string , outputIndex uint64 , l2BlockNumber uint64 ) {
220265 bs .batchInfoMu .Lock ()
221266 defer bs .batchInfoMu .Unlock ()
@@ -231,13 +276,15 @@ func (bs *BatchSubmitter) UpdateBatchInfo(chain string, submitter string, output
231276 })
232277}
233278
279+ // BatchInfo returns the current batch info
234280func (bs * BatchSubmitter ) BatchInfo () * ophosttypes.BatchInfoWithOutput {
235281 bs .batchInfoMu .Lock ()
236282 defer bs .batchInfoMu .Unlock ()
237283
238284 return & bs .batchInfos [0 ]
239285}
240286
287+ // NextBatchInfo returns the next batch info in the queue
241288func (bs * BatchSubmitter ) NextBatchInfo () * ophosttypes.BatchInfoWithOutput {
242289 bs .batchInfoMu .Lock ()
243290 defer bs .batchInfoMu .Unlock ()
@@ -247,7 +294,8 @@ func (bs *BatchSubmitter) NextBatchInfo() *ophosttypes.BatchInfoWithOutput {
247294 return & bs .batchInfos [1 ]
248295}
249296
250- func (bs * BatchSubmitter ) PopBatchInfo () {
297+ // DequeueBatchInfo removes the first batch info from the queue
298+ func (bs * BatchSubmitter ) DequeueBatchInfo () {
251299 bs .batchInfoMu .Lock ()
252300 defer bs .batchInfoMu .Unlock ()
253301
0 commit comments