@@ -13,13 +13,13 @@ use crate::{
13
13
Transition :: { Delta , To } ,
14
14
} ,
15
15
math_gadget:: {
16
- ConstantDivisionGadget , ContractCreateGadget , IsZeroWordGadget , LtGadget ,
17
- LtWordGadget ,
16
+ ConstantDivisionGadget , ContractCreateGadget , IsEqualWordGadget , IsZeroGadget ,
17
+ IsZeroWordGadget , LtGadget , LtWordGadget ,
18
18
} ,
19
19
memory_gadget:: {
20
20
CommonMemoryAddressGadget , MemoryAddressGadget , MemoryExpansionGadget ,
21
21
} ,
22
- not, AccountAddress , CachedRegion , Cell , StepRws ,
22
+ not, or , AccountAddress , CachedRegion , Cell , StepRws ,
23
23
} ,
24
24
witness:: { Block , Call , ExecStep , Transaction } ,
25
25
} ,
@@ -75,7 +75,9 @@ pub(crate) struct CreateGadget<F, const IS_CREATE2: bool, const S: ExecutionStat
75
75
is_depth_in_range : LtGadget < F , N_BYTES_U64 > ,
76
76
is_insufficient_balance : LtWordGadget < F > ,
77
77
is_nonce_in_range : LtGadget < F , N_BYTES_U64 > ,
78
- not_address_collision : IsZeroWordGadget < F , Word < Expression < F > > > ,
78
+ // both is_callee_once_zero and is_empty_callee_prev_hash are for checking address collision.
79
+ is_callee_once_zero : IsZeroGadget < F > ,
80
+ is_empty_callee_prev_hash : IsEqualWordGadget < F , Word < Expression < F > > , Word < Expression < F > > > ,
79
81
80
82
memory_expansion : MemoryExpansionGadget < F , 1 , N_BYTES_MEMORY_WORD_SIZE > ,
81
83
gas_left : ConstantDivisionGadget < F , N_BYTES_GAS > ,
@@ -261,61 +263,61 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
261
263
let prev_keccak_code_hash = cb. query_word_unchecked ( ) ;
262
264
let callee_nonce = cb. query_cell ( ) ;
263
265
266
+ let is_callee_once_zero = IsZeroGadget :: construct ( cb, callee_nonce. expr ( ) ) ;
267
+ let is_empty_callee_prev_hash =
268
+ IsEqualWordGadget :: construct ( cb, & prev_code_hash. to_word ( ) , & cb. empty_code_hash ( ) ) ;
264
269
// callee address's nonce
265
- let ( prev_code_hash_is_zero, not_address_collision) =
266
- cb. condition ( is_precheck_ok. expr ( ) , |cb| {
267
- // increase caller's nonce
268
- cb. account_write (
269
- create. caller_address ( ) ,
270
- AccountFieldTag :: Nonce ,
271
- Word :: from_lo_unchecked ( caller_nonce. expr ( ) + 1 . expr ( ) ) ,
272
- Word :: from_lo_unchecked ( caller_nonce. expr ( ) ) ,
273
- Some ( & mut reversion_info) ,
274
- ) ;
270
+ let prev_code_hash_is_zero = cb. condition ( is_precheck_ok. expr ( ) , |cb| {
271
+ // increase caller's nonce
272
+ cb. account_write (
273
+ create. caller_address ( ) ,
274
+ AccountFieldTag :: Nonce ,
275
+ Word :: from_lo_unchecked ( caller_nonce. expr ( ) + 1 . expr ( ) ) ,
276
+ Word :: from_lo_unchecked ( caller_nonce. expr ( ) ) ,
277
+ Some ( & mut reversion_info) ,
278
+ ) ;
275
279
276
- // add callee to access list
277
- cb. account_access_list_write_unchecked (
278
- tx_id. expr ( ) ,
279
- contract_addr. to_word ( ) ,
280
- 1 . expr ( ) ,
281
- was_warm. expr ( ) ,
282
- Some ( & mut reversion_info) ,
283
- ) ;
280
+ // add callee to access list
281
+ cb. account_access_list_write_unchecked (
282
+ tx_id. expr ( ) ,
283
+ contract_addr. to_word ( ) ,
284
+ 1 . expr ( ) ,
285
+ was_warm. expr ( ) ,
286
+ Some ( & mut reversion_info) ,
287
+ ) ;
284
288
285
- // read contract's previous hash
289
+ // read contract's previous hash
290
+ cb. account_read (
291
+ contract_addr. to_word ( ) ,
292
+ AccountFieldTag :: CodeHash ,
293
+ prev_code_hash. to_word ( ) ,
294
+ ) ;
295
+
296
+ let prev_code_hash_is_zero = IsZeroWordGadget :: construct ( cb, & prev_code_hash) ;
297
+ cb. condition ( not:: expr ( prev_code_hash_is_zero. expr ( ) ) , |cb| {
286
298
cb. account_read (
287
299
contract_addr. to_word ( ) ,
288
- AccountFieldTag :: CodeHash ,
289
- prev_code_hash . to_word ( ) ,
300
+ AccountFieldTag :: Nonce ,
301
+ Word :: from_lo_unchecked ( callee_nonce . expr ( ) ) ,
290
302
) ;
291
-
292
- let prev_code_hash_is_zero = IsZeroWordGadget :: construct ( cb, & prev_code_hash) ;
293
- cb. condition ( not:: expr ( prev_code_hash_is_zero. expr ( ) ) , |cb| {
294
- cb. account_read (
295
- contract_addr. to_word ( ) ,
296
- AccountFieldTag :: Nonce ,
297
- Word :: from_lo_unchecked ( callee_nonce. expr ( ) ) ,
298
- ) ;
299
- } ) ;
300
- // ErrContractAddressCollision, if any one of following criteria meets.
301
- // Nonce is not zero or account code hash is not either 0 or EMPTY_CODE_HASH.
302
- // Here use `isZeroGadget(callee_nonce + prev_code_hash * (prev_code_hash -
303
- // empty_code_hash))` to represent `(callee_nonce == 0 && (prev_code_hash == 0
304
- // or prev_code_hash == empty_code_hash))`
305
- let prev_code_hash_word = prev_code_hash. to_word ( ) ;
306
- (
307
- prev_code_hash_is_zero,
308
- IsZeroWordGadget :: construct (
309
- cb,
310
- & Word :: from_lo_unchecked ( callee_nonce. expr ( ) ) . add_unchecked (
311
- prev_code_hash_word. clone ( ) . mul_unchecked (
312
- prev_code_hash_word. sub_unchecked ( cb. empty_code_hash ( ) ) ,
313
- ) ,
314
- ) ,
315
- ) ,
316
- )
317
303
} ) ;
318
304
305
+ prev_code_hash_is_zero
306
+ } ) ;
307
+
308
+ // ErrContractAddressCollision, if any one of following criteria meets.
309
+ // Nonce is not zero or account code hash is not either 0 or EMPTY_CODE_HASH.
310
+ // Here use `isZeroGadget(callee_nonce + prev_code_hash * (prev_code_hash -
311
+ // empty_code_hash))` to represent `(callee_nonce == 0 && (prev_code_hash == 0
312
+ // or prev_code_hash == empty_code_hash))`
313
+ let not_address_collision = and:: expr ( [
314
+ is_callee_once_zero. expr ( ) ,
315
+ or:: expr ( [
316
+ is_empty_callee_prev_hash. expr ( ) ,
317
+ prev_code_hash_is_zero. expr ( ) ,
318
+ ] ) ,
319
+ ] ) ;
320
+
319
321
for ( field_tag, value) in [
320
322
(
321
323
CallContextFieldTag :: ProgramCounter ,
@@ -601,7 +603,9 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
601
603
callee_nonce,
602
604
keccak_code_hash,
603
605
keccak_output,
604
- not_address_collision,
606
+ //not_address_collision,
607
+ is_callee_once_zero,
608
+ is_empty_callee_prev_hash,
605
609
is_success,
606
610
prev_code_hash,
607
611
prev_code_hash_is_zero,
@@ -694,14 +698,15 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
694
698
. assign_u256 ( region, offset, callee_prev_code_hash) ?;
695
699
self . prev_code_hash_is_zero
696
700
. assign_u256 ( region, offset, callee_prev_code_hash) ?;
697
- self . not_address_collision . assign_u256 (
701
+
702
+ self . is_callee_once_zero
703
+ . assign ( region, offset, F :: from ( callee_nonce) ) ?;
704
+ self . is_empty_callee_prev_hash . assign_u256 (
698
705
region,
699
706
offset,
700
- U256 :: from ( callee_nonce)
701
- + callee_prev_code_hash
702
- * ( CodeDB :: empty_code_hash ( ) . to_word ( ) - callee_prev_code_hash) ,
707
+ callee_prev_code_hash,
708
+ CodeDB :: empty_code_hash ( ) . to_word ( ) ,
703
709
) ?;
704
-
705
710
let shift = init_code_start. low_u64 ( ) % 32 ;
706
711
let copy_rw_increase: u64 = step. copy_rw_counter_delta ;
707
712
let values: Vec < u8 > = if is_precheck_ok {
0 commit comments