@@ -15,7 +15,7 @@ pub use self::block::BlockHead;
15
15
use crate :: {
16
16
error:: Error ,
17
17
evm:: opcodes:: { gen_associated_ops, gen_begin_tx_ops, gen_end_tx_ops} ,
18
- operation:: { CallContextField , Operation , RWCounter , StartOp , RW } ,
18
+ operation:: { self , CallContextField , Operation , RWCounter , StartOp , StorageOp , RW } ,
19
19
rpc:: GethClient ,
20
20
state_db:: { self , CodeDB , StateDB } ,
21
21
} ;
@@ -48,7 +48,7 @@ use std::{
48
48
collections:: { BTreeMap , HashMap } ,
49
49
iter,
50
50
} ;
51
- pub use transaction:: { Transaction , TransactionContext } ;
51
+ pub use transaction:: { Transaction , TransactionContext , TxL1Fee , TX_L1_FEE_PRECISION } ;
52
52
53
53
/// Circuit Setup Parameters
54
54
#[ derive( Debug , Clone , Copy ) ]
@@ -243,23 +243,28 @@ impl<'a> CircuitInputBuilder {
243
243
check_last_tx : bool ,
244
244
) -> Result < ( ) , Error > {
245
245
// accumulates gas across all txs in the block
246
- log:: info!( "handling block {:?}" , eth_block. number) ;
246
+ log:: info!(
247
+ "handling block {:?}, tx num {}" ,
248
+ eth_block. number,
249
+ eth_block. transactions. len( )
250
+ ) ;
247
251
for ( tx_index, tx) in eth_block. transactions . iter ( ) . enumerate ( ) {
252
+ let batch_tx_idx = self . block . txs . len ( ) ;
248
253
if self . block . txs . len ( ) >= self . block . circuits_params . max_txs {
249
254
log:: warn!(
250
- "skip tx outside MAX_TX limit {}, {}th(inner idx: {}) tx {:?}" ,
255
+ "skip tx outside MAX_TX limit {}, {}th tx (inner idx: {}) {:?}" ,
251
256
self . block. circuits_params. max_txs,
257
+ batch_tx_idx,
252
258
tx. transaction_index. unwrap_or_default( ) ,
253
- self . block. txs. len( ) ,
254
259
tx. hash
255
260
) ;
256
261
continue ;
257
262
}
258
263
let geth_trace = & geth_traces[ tx_index] ;
259
264
log:: info!(
260
- "handling {}th(inner idx: {}) tx: {:?} rwc {:?}, to: {:?}, input_len {:?}" ,
265
+ "handling {}th tx(inner idx: {}): {:?} rwc {:?}, to: {:?}, input_len {:?}" ,
266
+ batch_tx_idx,
261
267
tx. transaction_index. unwrap_or_default( ) ,
262
- self . block. txs. len( ) ,
263
268
tx. hash,
264
269
self . block_ctx. rwc,
265
270
tx. to,
@@ -273,6 +278,12 @@ impl<'a> CircuitInputBuilder {
273
278
geth_trace,
274
279
check_last_tx && tx_index + 1 == eth_block. transactions . len ( ) ,
275
280
) ?;
281
+ log:: debug!(
282
+ "after handle {}th tx: rwc {:?}, block total gas {:?}" ,
283
+ batch_tx_idx,
284
+ self . block_ctx. rwc,
285
+ self . block_ctx. cumulative_gas_used
286
+ ) ;
276
287
}
277
288
if handle_rwc_reversion {
278
289
self . set_value_ops_call_context_rwc_eor ( ) ;
@@ -285,8 +296,81 @@ impl<'a> CircuitInputBuilder {
285
296
Ok ( ( ) )
286
297
}
287
298
299
+ fn print_rw_usage ( & self ) {
300
+ // opcode -> (count, mem_rw_len, stack_rw_len)
301
+ let mut opcode_info_map = BTreeMap :: new ( ) ;
302
+ for t in & self . block . txs {
303
+ for step in t. steps ( ) {
304
+ if let ExecState :: Op ( op) = step. exec_state {
305
+ opcode_info_map. entry ( op) . or_insert ( ( 0 , 0 , 0 ) ) ;
306
+ let mut values = opcode_info_map[ & op] ;
307
+ values. 0 += 1 ;
308
+ values. 1 += step
309
+ . bus_mapping_instance
310
+ . iter ( )
311
+ . filter ( |rw| rw. 0 == operation:: Target :: Memory )
312
+ . count ( ) ;
313
+ values. 2 += step
314
+ . bus_mapping_instance
315
+ . iter ( )
316
+ . filter ( |rw| rw. 0 == operation:: Target :: Stack )
317
+ . count ( ) ;
318
+ opcode_info_map. insert ( op, values) ;
319
+ }
320
+ }
321
+ }
322
+ for ( op, ( count, mem, stack) ) in opcode_info_map
323
+ . iter ( )
324
+ . sorted_by_key ( |( _, ( _, m, _) ) | m)
325
+ . rev ( )
326
+ {
327
+ log:: debug!(
328
+ "op {:?}, count {}, mem rw {}(avg {:.2}), stack rw {}(avg {:.2})" ,
329
+ op,
330
+ count,
331
+ mem,
332
+ * mem as f32 / * count as f32 ,
333
+ stack,
334
+ * stack as f32 / * count as f32
335
+ ) ;
336
+ }
337
+ log:: debug!( "memory num: {}" , self . block. container. memory. len( ) ) ;
338
+ log:: debug!( "stack num: {}" , self . block. container. stack. len( ) ) ;
339
+ log:: debug!( "storage num: {}" , self . block. container. storage. len( ) ) ;
340
+ log:: debug!(
341
+ "tx_access_list_account num: {}" ,
342
+ self . block. container. tx_access_list_account. len( )
343
+ ) ;
344
+ log:: debug!(
345
+ "tx_access_list_account_storage num: {}" ,
346
+ self . block. container. tx_access_list_account_storage. len( )
347
+ ) ;
348
+ log:: debug!( "tx_refund num: {}" , self . block. container. tx_refund. len( ) ) ;
349
+ log:: debug!( "account num: {}" , self . block. container. account. len( ) ) ;
350
+ log:: debug!(
351
+ "call_context num: {}" ,
352
+ self . block. container. call_context. len( )
353
+ ) ;
354
+ log:: debug!( "tx_receipt num: {}" , self . block. container. tx_receipt. len( ) ) ;
355
+ log:: debug!( "tx_log num: {}" , self . block. container. tx_log. len( ) ) ;
356
+ log:: debug!( "start num: {}" , self . block. container. start. len( ) ) ;
357
+ }
358
+
288
359
/// ..
289
360
pub fn set_end_block ( & mut self ) -> Result < ( ) , Error > {
361
+ use crate :: l2_predeployed:: message_queue:: {
362
+ ADDRESS as MESSAGE_QUEUE , WITHDRAW_TRIE_ROOT_SLOT ,
363
+ } ;
364
+
365
+ let withdraw_root = * self
366
+ . sdb
367
+ . get_storage ( & MESSAGE_QUEUE , & WITHDRAW_TRIE_ROOT_SLOT )
368
+ . 1 ;
369
+ let withdraw_root_before = * self
370
+ . sdb
371
+ . get_committed_storage ( & MESSAGE_QUEUE , & WITHDRAW_TRIE_ROOT_SLOT )
372
+ . 1 ;
373
+
290
374
let max_rws = self . block . circuits_params . max_rws ;
291
375
let mut end_block_not_last = self . block . block_steps . end_block_not_last . clone ( ) ;
292
376
let mut end_block_last = self . block . block_steps . end_block_last . clone ( ) ;
@@ -297,15 +381,30 @@ impl<'a> CircuitInputBuilder {
297
381
let mut dummy_tx_ctx = TransactionContext :: default ( ) ;
298
382
let mut state = self . state_ref ( & mut dummy_tx, & mut dummy_tx_ctx) ;
299
383
384
+ let dummy_tx_id = state. block . txs . len ( ) ;
300
385
if let Some ( call_id) = state. block . txs . last ( ) . map ( |tx| tx. calls [ 0 ] . call_id ) {
301
386
state. call_context_read (
302
387
& mut end_block_last,
303
388
call_id,
304
389
CallContextField :: TxId ,
305
- Word :: from ( state . block . txs . len ( ) as u64 ) ,
390
+ Word :: from ( dummy_tx_id as u64 ) ,
306
391
) ;
307
392
}
308
393
394
+ // increase the total rwc by 1
395
+ state. push_op (
396
+ & mut end_block_last,
397
+ RW :: READ ,
398
+ StorageOp :: new (
399
+ * MESSAGE_QUEUE ,
400
+ * WITHDRAW_TRIE_ROOT_SLOT ,
401
+ withdraw_root,
402
+ withdraw_root,
403
+ dummy_tx_id,
404
+ withdraw_root_before,
405
+ ) ,
406
+ ) ;
407
+
309
408
let mut push_op = |step : & mut ExecStep , rwc : RWCounter , rw : RW , op : StartOp | {
310
409
let op_ref = state. block . container . insert ( Operation :: new ( rwc, rw, op) ) ;
311
410
step. bus_mapping_instance . push ( op_ref) ;
@@ -333,6 +432,8 @@ impl<'a> CircuitInputBuilder {
333
432
StartOp { } ,
334
433
) ;
335
434
435
+ self . block . withdraw_root = withdraw_root;
436
+ self . block . prev_withdraw_root = withdraw_root_before;
336
437
self . block . block_steps . end_block_not_last = end_block_not_last;
337
438
self . block . block_steps . end_block_last = end_block_last;
338
439
Ok ( ( ) )
@@ -350,6 +451,17 @@ impl<'a> CircuitInputBuilder {
350
451
is_last_tx : bool ,
351
452
) -> Result < ( ) , Error > {
352
453
let mut tx = self . new_tx ( eth_tx, !geth_trace. failed ) ?;
454
+
455
+ // Sanity check for transaction L1 fee.
456
+ let tx_l1_fee = tx. l1_fee ( ) ;
457
+ if tx_l1_fee != geth_trace. l1_fee {
458
+ log:: error!(
459
+ "Mismatch tx_l1_fee: calculated = {}, real = {}" ,
460
+ tx_l1_fee,
461
+ geth_trace. l1_fee
462
+ ) ;
463
+ }
464
+
353
465
let mut tx_ctx = TransactionContext :: new ( eth_tx, geth_trace, is_last_tx) ?;
354
466
let mut debug_tx = tx. clone ( ) ;
355
467
debug_tx. input . clear ( ) ;
@@ -370,19 +482,22 @@ impl<'a> CircuitInputBuilder {
370
482
gen_begin_tx_ops ( & mut self . state_ref ( & mut tx, & mut tx_ctx) , geth_trace) ?;
371
483
372
484
for ( index, geth_step) in geth_trace. struct_logs . iter ( ) . enumerate ( ) {
485
+ let tx_gas = tx. gas ;
373
486
let mut state_ref = self . state_ref ( & mut tx, & mut tx_ctx) ;
374
487
log:: trace!(
375
- "handle {}th tx depth {} {}th opcode {:?} pc: {} gas_left: {} rwc: {} call_id: {} msize: {} args: {}" ,
488
+ "handle {}th tx depth {} {}th/{} opcode {:?} pc: {} gas_left: {} gas_used : {} rwc: {} call_id: {} msize: {} args: {}" ,
376
489
eth_tx. transaction_index. unwrap_or_default( ) ,
377
490
geth_step. depth,
378
491
index,
492
+ geth_trace. struct_logs. len( ) ,
379
493
geth_step. op,
380
494
geth_step. pc. 0 ,
381
495
geth_step. gas. 0 ,
496
+ tx_gas - geth_step. gas. 0 ,
382
497
state_ref. block_ctx. rwc. 0 ,
383
498
state_ref. call( ) . map( |c| c. call_id) . unwrap_or( 0 ) ,
384
499
state_ref. call_ctx( ) ?. memory. len( ) ,
385
- if geth_step. op. is_push ( ) {
500
+ if geth_step. op. is_push_with_data ( ) {
386
501
format!( "{:?}" , geth_trace. struct_logs[ index + 1 ] . stack. last( ) )
387
502
} else if geth_step. op. is_call_without_value( ) {
388
503
format!(
@@ -478,6 +593,7 @@ pub fn keccak_inputs(block: &Block, code_db: &CodeDB) -> Result<Vec<Vec<u8>>, Er
478
593
keccak_inputs. push ( keccak_inputs_pi_circuit (
479
594
block. chain_id ( ) . as_u64 ( ) ,
480
595
block. prev_state_root ,
596
+ block. withdraw_root ,
481
597
& block. headers ,
482
598
block. txs ( ) ,
483
599
block. circuits_params . max_txs ,
@@ -564,13 +680,12 @@ pub fn get_dummy_tx_hash(chain_id: u64) -> H256 {
564
680
fn keccak_inputs_pi_circuit (
565
681
chain_id : u64 ,
566
682
prev_state_root : Word ,
683
+ withdraw_trie_root : Word ,
567
684
block_headers : & BTreeMap < u64 , BlockHead > ,
568
685
transactions : & [ Transaction ] ,
569
686
max_txs : usize ,
570
687
) -> Vec < u8 > {
571
688
let dummy_tx_hash = get_dummy_tx_hash ( chain_id) ;
572
- // TODO: use real-world withdraw trie root
573
- let withdraw_trie_root = Word :: zero ( ) ; // zero for now
574
689
575
690
let result = iter:: empty ( )
576
691
// state roots
0 commit comments