@@ -13,13 +13,13 @@ use crate::{
1313 Transition :: { Delta , To } ,
1414 } ,
1515 math_gadget:: {
16- ConstantDivisionGadget , ContractCreateGadget , IsZeroWordGadget , LtGadget ,
17- LtWordGadget ,
16+ ConstantDivisionGadget , ContractCreateGadget , IsEqualWordGadget , IsZeroGadget ,
17+ IsZeroWordGadget , LtGadget , LtWordGadget ,
1818 } ,
1919 memory_gadget:: {
2020 CommonMemoryAddressGadget , MemoryAddressGadget , MemoryExpansionGadget ,
2121 } ,
22- not, AccountAddress , CachedRegion , Cell , StepRws ,
22+ not, or , AccountAddress , CachedRegion , Cell , StepRws ,
2323 } ,
2424 witness:: { Block , Call , ExecStep , Transaction } ,
2525 } ,
@@ -75,7 +75,9 @@ pub(crate) struct CreateGadget<F, const IS_CREATE2: bool, const S: ExecutionStat
7575 is_depth_in_range : LtGadget < F , N_BYTES_U64 > ,
7676 is_insufficient_balance : LtWordGadget < F > ,
7777 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 > > > ,
7981
8082 memory_expansion : MemoryExpansionGadget < F , 1 , N_BYTES_MEMORY_WORD_SIZE > ,
8183 gas_left : ConstantDivisionGadget < F , N_BYTES_GAS > ,
@@ -261,61 +263,61 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
261263 let prev_keccak_code_hash = cb. query_word_unchecked ( ) ;
262264 let callee_nonce = cb. query_cell ( ) ;
263265
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 ( ) ) ;
264269 // 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+ ) ;
275279
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+ ) ;
284288
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| {
286298 cb. account_read (
287299 contract_addr. to_word ( ) ,
288- AccountFieldTag :: CodeHash ,
289- prev_code_hash . to_word ( ) ,
300+ AccountFieldTag :: Nonce ,
301+ Word :: from_lo_unchecked ( callee_nonce . expr ( ) ) ,
290302 ) ;
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- )
317303 } ) ;
318304
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+
319321 for ( field_tag, value) in [
320322 (
321323 CallContextFieldTag :: ProgramCounter ,
@@ -601,7 +603,9 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
601603 callee_nonce,
602604 keccak_code_hash,
603605 keccak_output,
604- not_address_collision,
606+ //not_address_collision,
607+ is_callee_once_zero,
608+ is_empty_callee_prev_hash,
605609 is_success,
606610 prev_code_hash,
607611 prev_code_hash_is_zero,
@@ -694,14 +698,15 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
694698 . assign_u256 ( region, offset, callee_prev_code_hash) ?;
695699 self . prev_code_hash_is_zero
696700 . 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 (
698705 region,
699706 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 ( ) ,
703709 ) ?;
704-
705710 let shift = init_code_start. low_u64 ( ) % 32 ;
706711 let copy_rw_increase: u64 = step. copy_rw_counter_delta ;
707712 let values: Vec < u8 > = if is_precheck_ok {
0 commit comments