@@ -55,12 +55,20 @@ func (h L1IncomingMessageHeader) SeqNum() (uint64, error) {
5555 return seqNumBig .Uint64 (), nil
5656}
5757
58+ type BatchDataStats struct {
59+ Length uint64 `json:"length"`
60+ NonZeros uint64 `json:"nonzeros"`
61+ }
62+
5863type L1IncomingMessage struct {
5964 Header * L1IncomingMessageHeader `json:"header"`
6065 L2msg []byte `json:"l2Msg"`
6166
6267 // Only used for `L1MessageType_BatchPostingReport`
63- BatchGasCost * uint64 `json:"batchGasCost,omitempty" rlp:"optional"`
68+ // note: the legacy field is used in json to support older clients
69+ // in rlp it's used to distinguish old from new (old will load into first arg)
70+ LegacyBatchGasCost * uint64 `json:"batchGasCost,omitempty" rlp:"optional"`
71+ BatchDataStats * BatchDataStats `json:"batchDataTokens,omitempty" rlp:"optional"`
6472}
6573
6674var EmptyTestIncomingMessage = L1IncomingMessage {
@@ -145,41 +153,52 @@ func (h *L1IncomingMessageHeader) Equals(other *L1IncomingMessageHeader) bool {
145153 arbmath .BigEquals (h .L1BaseFee , other .L1BaseFee )
146154}
147155
148- func ComputeBatchGasCost (data []byte ) uint64 {
149- var gas uint64
156+ func GetDataStats (data []byte ) * BatchDataStats {
157+ nonZeros := uint64 ( 0 )
150158 for _ , b := range data {
151- if b == 0 {
152- gas += params .TxDataZeroGas
153- } else {
154- gas += params .TxDataNonZeroGasEIP2028
159+ if b != 0 {
160+ nonZeros += 1
155161 }
156162 }
163+ return & BatchDataStats {
164+ Length : uint64 (len (data )),
165+ NonZeros : nonZeros ,
166+ }
167+ }
157168
169+ func LegacyCostForStats (stats * BatchDataStats ) uint64 {
170+ gas := params .TxDataZeroGas * (stats .Length - stats .NonZeros ) + params .TxDataNonZeroGasEIP2028 * stats .NonZeros
158171 // the poster also pays to keccak the batch and place it and a batch-posting report into the inbox
159- keccakWords := arbmath .WordsForBytes (uint64 ( len ( data )) )
172+ keccakWords := arbmath .WordsForBytes (stats . Length )
160173 gas += params .Keccak256Gas + (keccakWords * params .Keccak256WordGas )
161174 gas += 2 * params .SstoreSetGasEIP2200
162175 return gas
163176}
164177
165- func (msg * L1IncomingMessage ) FillInBatchGasCost (batchFetcher FallibleBatchFetcher ) error {
166- if batchFetcher == nil || msg .Header .Kind != L1MessageType_BatchPostingReport || msg . BatchGasCost != nil {
178+ func (msg * L1IncomingMessage ) FillInBatchGasFields (batchFetcher FallibleBatchFetcher ) error {
179+ if batchFetcher == nil || msg .Header .Kind != L1MessageType_BatchPostingReport {
167180 return nil
168181 }
169- _ , _ , batchHash , batchNum , _ , _ , err := ParseBatchPostingReportMessageFields (bytes .NewReader (msg .L2msg ))
170- if err != nil {
171- return fmt .Errorf ("failed to parse batch posting report: %w" , err )
172- }
173- batchData , err := batchFetcher (batchNum )
174- if err != nil {
175- return fmt .Errorf ("failed to fetch batch mentioned by batch posting report: %w" , err )
182+ if msg .BatchDataStats != nil && msg .LegacyBatchGasCost != nil {
183+ return nil
176184 }
177- gotHash := crypto .Keccak256Hash (batchData )
178- if gotHash != batchHash {
179- return fmt .Errorf ("batch fetcher returned incorrect data hash %v (wanted %v for batch %v)" , gotHash , batchHash , batchNum )
185+ if msg .BatchDataStats == nil {
186+ _ , _ , batchHash , batchNum , _ , _ , err := ParseBatchPostingReportMessageFields (bytes .NewReader (msg .L2msg ))
187+ if err != nil {
188+ return fmt .Errorf ("failed to parse batch posting report: %w" , err )
189+ }
190+ batchData , err := batchFetcher (batchNum )
191+ if err != nil {
192+ return fmt .Errorf ("failed to fetch batch mentioned by batch posting report: %w" , err )
193+ }
194+ gotHash := crypto .Keccak256Hash (batchData )
195+ if gotHash != batchHash {
196+ return fmt .Errorf ("batch fetcher returned incorrect data hash %v (wanted %v for batch %v)" , gotHash , batchHash , batchNum )
197+ }
198+ msg .BatchDataStats = GetDataStats (batchData )
180199 }
181- gas := ComputeBatchGasCost ( batchData )
182- msg .BatchGasCost = & gas
200+ legacyCost := LegacyCostForStats ( msg . BatchDataStats )
201+ msg .LegacyBatchGasCost = & legacyCost
183202 return nil
184203}
185204
@@ -233,18 +252,19 @@ func ParseIncomingL1Message(rd io.Reader, batchFetcher FallibleBatchFetcher) (*L
233252 }
234253
235254 msg := & L1IncomingMessage {
236- & L1IncomingMessageHeader {
255+ Header : & L1IncomingMessageHeader {
237256 Kind : kind ,
238257 Poster : sender ,
239258 BlockNumber : blockNumber ,
240259 Timestamp : timestamp ,
241260 RequestId : & requestId ,
242261 L1BaseFee : baseFeeL1 .Big (),
243262 },
244- data ,
245- nil ,
263+ L2msg : data ,
264+ LegacyBatchGasCost : nil ,
265+ BatchDataStats : nil ,
246266 }
247- err = msg .FillInBatchGasCost (batchFetcher )
267+ err = msg .FillInBatchGasFields (batchFetcher )
248268 if err != nil {
249269 return nil , err
250270 }
0 commit comments