Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Commit 8d4d596

Browse files
merge transfer gadgets ugly
1 parent 39b2ead commit 8d4d596

File tree

5 files changed

+51
-132
lines changed

5 files changed

+51
-132
lines changed

zkevm-circuits/src/evm_circuit/execution/begin_tx.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
step::ExecutionState,
66
util::{
77
and,
8-
common_gadget::TransferWithGasFeeGadget,
8+
common_gadget::TransferGadget,
99
constraint_builder::{
1010
ConstrainBuilderCommon, EVMConstraintBuilder, ReversionInfo, StepStateTransition,
1111
Transition::{Delta, To},
@@ -14,7 +14,7 @@ use crate::{
1414
math_gadget::{
1515
ContractCreateGadget, IsEqualWordGadget, IsZeroWordGadget, RangeCheckGadget,
1616
},
17-
not, or,
17+
not,
1818
tx::{BeginTxHelperGadget, TxDataGadget},
1919
AccountAddress, CachedRegion, Cell, StepRws,
2020
},
@@ -41,7 +41,7 @@ pub(crate) struct BeginTxGadget<F> {
4141
call_callee_address: AccountAddress<F>,
4242
reversion_info: ReversionInfo<F>,
4343
sufficient_gas_left: RangeCheckGadget<F, N_BYTES_GAS>,
44-
transfer_with_gas_fee: TransferWithGasFeeGadget<F>,
44+
transfer_with_gas_fee: TransferGadget<F, true>,
4545
code_hash: WordLoHiCell<F>,
4646
is_empty_code_hash: IsEqualWordGadget<F, WordLoHi<Expression<F>>, WordLoHi<Expression<F>>>,
4747
caller_nonce_hash_bytes: Word32Cell<F>,
@@ -170,17 +170,20 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
170170
AccountFieldTag::CodeHash,
171171
code_hash.to_word(),
172172
);
173-
173+
cb.require_equal(
174+
"is create: callee_not_exists",
175+
tx.is_create.expr(),
176+
callee_not_exists.expr(),
177+
);
174178
// Transfer value from caller to callee, creating account if necessary.
175-
let transfer_with_gas_fee = TransferWithGasFeeGadget::construct(
179+
let transfer_with_gas_fee = TransferGadget::construct(
176180
cb,
177181
tx.caller_address.to_word(),
178182
tx.callee_address.to_word(),
179183
not::expr(callee_not_exists.expr()),
180-
or::expr([tx.is_create.expr(), callee_not_exists.expr()]),
181184
tx.value.clone(),
182-
tx.mul_gas_fee_by_gas.product().clone(),
183185
&mut reversion_info,
186+
Some(tx.mul_gas_fee_by_gas.product().clone()),
184187
);
185188

186189
let caller_nonce_hash_bytes = cb.query_word32();
@@ -505,11 +508,14 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
505508
self.transfer_with_gas_fee.assign(
506509
region,
507510
offset,
508-
caller_balance_sub_fee_pair,
511+
(
512+
Some(caller_balance_sub_fee_pair.0),
513+
Some(caller_balance_sub_fee_pair.1),
514+
),
509515
caller_balance_sub_value_pair,
510516
callee_balance_pair,
511517
tx.value,
512-
gas_fee,
518+
Some(gas_fee),
513519
)?;
514520
self.code_hash
515521
.assign_u256(region, offset, callee_code_hash)?;

zkevm-circuits/src/evm_circuit/execution/callop.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ pub(crate) struct CallOpGadget<F> {
6060
is_warm: Cell<F>,
6161
is_warm_prev: Cell<F>,
6262
callee_reversion_info: ReversionInfo<F>,
63-
transfer: TransferGadget<F>,
63+
transfer: TransferGadget<F, false>,
6464
// current handling Call* opcode's caller balance
6565
caller_balance: WordLoHi<Cell<F>>,
6666
// check if insufficient balance case
@@ -242,9 +242,9 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
242242
caller_address.to_word(),
243243
callee_address.to_word(),
244244
not::expr(call_gadget.callee_not_exists.expr()),
245-
false,
246245
call_gadget.value.clone(),
247246
&mut callee_reversion_info,
247+
None,
248248
)
249249
});
250250
// rwc_delta = 8 + is_delegatecall * 2 + call_gadget.rw_delta() +
@@ -876,9 +876,11 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
876876
self.transfer.assign(
877877
region,
878878
offset,
879+
(None, None),
879880
caller_balance_pair,
880881
callee_balance_pair,
881882
value,
883+
None,
882884
)?;
883885
}
884886

zkevm-circuits/src/evm_circuit/execution/create.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub(crate) struct CreateGadget<F, const IS_CREATE2: bool, const S: ExecutionStat
6363
callee_nonce: Cell<F>,
6464
prev_code_hash: WordLoHiCell<F>,
6565
prev_code_hash_is_zero: IsZeroWordGadget<F, WordLoHi<Expression<F>>>,
66-
transfer: TransferGadget<F>,
66+
transfer: TransferGadget<F, false>,
6767
create: ContractCreateGadget<F, IS_CREATE2>,
6868

6969
init_code: MemoryAddressGadget<F>,
@@ -334,9 +334,9 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
334334
create.caller_address(),
335335
contract_addr.to_word(),
336336
0.expr(),
337-
true,
338337
value.clone(),
339338
&mut callee_reversion_info,
339+
None,
340340
);
341341

342342
// EIP 161, the nonce of a newly created contract is 1
@@ -650,9 +650,11 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
650650
self.transfer.assign(
651651
region,
652652
offset,
653+
(None, None),
653654
caller_balance_pair,
654655
callee_balance_pair,
655656
value,
657+
None,
656658
)?;
657659
}
658660

zkevm-circuits/src/evm_circuit/execution/end_tx.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
107107
cb,
108108
coinbase.to_word(),
109109
1.expr() - coinbase_code_hash_is_zero.expr(),
110-
false.expr(),
111110
mul_effective_tip_by_gas_used.product().clone(),
112111
None,
113112
);

zkevm-circuits/src/evm_circuit/util/common_gadget.rs

Lines changed: 28 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
Transition::{Delta, Same, To},
1818
},
1919
math_gadget::{AddWordsGadget, RangeCheckGadget},
20-
not, or, Cell,
20+
not, Cell,
2121
},
2222
},
2323
table::{AccountFieldTag, CallContextFieldTag},
@@ -370,7 +370,6 @@ impl<F: Field, const N_ADDENDS: usize, const INCREASE: bool>
370370
pub(crate) struct TransferToGadget<F> {
371371
receiver: UpdateBalanceGadget<F, 2, true>,
372372
receiver_exists: Expression<F>,
373-
must_create: Expression<F>,
374373
value_is_zero: IsZeroWordGadget<F, Word32Cell<F>>,
375374
}
376375

@@ -380,16 +379,16 @@ impl<F: Field> TransferToGadget<F> {
380379
cb: &mut EVMConstraintBuilder<F>,
381380
receiver_address: WordLoHi<Expression<F>>,
382381
receiver_exists: Expression<F>,
383-
must_create: Expression<F>,
384382
value: Word32Cell<F>,
385383
mut reversion_info: Option<&mut ReversionInfo<F>>,
386384
) -> Self {
387385
let value_is_zero = cb.is_zero_word(&value);
386+
388387
// Create account
389388
cb.condition(
390389
and::expr([
391390
not::expr(receiver_exists.expr()),
392-
or::expr([not::expr(value_is_zero.expr()), must_create.clone()]),
391+
not::expr(value_is_zero.expr()),
393392
]),
394393
|cb| {
395394
cb.account_write(
@@ -409,7 +408,6 @@ impl<F: Field> TransferToGadget<F> {
409408
Self {
410409
receiver,
411410
receiver_exists,
412-
must_create,
413411
value_is_zero,
414412
}
415413
}
@@ -436,8 +434,7 @@ impl<F: Field> TransferToGadget<F> {
436434
pub(crate) fn rw_delta(&self) -> Expression<F> {
437435
// +1 Write Account (receiver) CodeHash (account creation via code_hash update)
438436
and::expr([
439-
not::expr(self.receiver_exists.expr()),
440-
or::expr([not::expr(self.value_is_zero.expr()), self.must_create.clone()]),
437+
not::expr(self.receiver_exists.expr()),not::expr(self.value_is_zero.expr())
441438
]) +
442439
// +1 Write Account (receiver) Balance
443440
not::expr(self.value_is_zero.expr())
@@ -452,26 +449,29 @@ impl<F: Field> TransferToGadget<F> {
452449
/// setting it's code_hash = EMPTY_HASH. The receiver account is also created
453450
/// unconditionally if must_create is true. This gadget is used in BeginTx.
454451
#[derive(Clone, Debug)]
455-
pub(crate) struct TransferWithGasFeeGadget<F> {
456-
sender_sub_fee: UpdateBalanceGadget<F, 2, false>,
452+
pub(crate) struct TransferGadget<F, const WITH_FEE: bool> {
453+
sender_sub_fee: Option<UpdateBalanceGadget<F, 2, false>>,
457454
sender_sub_value: UpdateBalanceGadget<F, 2, false>,
458455
receiver: TransferToGadget<F>,
459-
value_is_zero: IsZeroWordGadget<F, Word32Cell<F>>,
456+
pub(crate) value_is_zero: IsZeroWordGadget<F, Word32Cell<F>>,
460457
}
461458

462-
impl<F: Field> TransferWithGasFeeGadget<F> {
459+
impl<F: Field, const WITH_FEE: bool> TransferGadget<F, WITH_FEE> {
463460
#[allow(clippy::too_many_arguments)]
464461
pub(crate) fn construct(
465462
cb: &mut EVMConstraintBuilder<F>,
466463
sender_address: WordLoHi<Expression<F>>,
467464
receiver_address: WordLoHi<Expression<F>>,
468465
receiver_exists: Expression<F>,
469-
must_create: Expression<F>,
470466
value: Word32Cell<F>,
471-
gas_fee: Word32Cell<F>,
472467
reversion_info: &mut ReversionInfo<F>,
468+
gas_fee: Option<Word32Cell<F>>,
473469
) -> Self {
474-
let sender_sub_fee = cb.decrease_balance(sender_address.to_word(), gas_fee, None);
470+
let sender_sub_fee = if WITH_FEE {
471+
Some(cb.decrease_balance(sender_address.to_word(), gas_fee.expect("fee exists"), None))
472+
} else {
473+
None
474+
};
475475
let value_is_zero = cb.is_zero_word(&value);
476476
// Skip transfer if value == 0
477477
let sender_sub_value = cb.condition(not::expr(value_is_zero.expr()), |cb| {
@@ -481,7 +481,6 @@ impl<F: Field> TransferWithGasFeeGadget<F> {
481481
cb,
482482
receiver_address,
483483
receiver_exists,
484-
must_create,
485484
value,
486485
Some(reversion_info),
487486
);
@@ -496,12 +495,9 @@ impl<F: Field> TransferWithGasFeeGadget<F> {
496495

497496
pub(crate) fn rw_delta(&self) -> Expression<F> {
498497
// +1 Write Account (sender) Balance (Not Reversible tx fee)
499-
1.expr() +
498+
WITH_FEE.expr() +
500499
// +1 Write Account (receiver) CodeHash (account creation via code_hash update)
501-
and::expr([not::expr(self.receiver.receiver_exists.expr()), or::expr([
502-
not::expr(self.value_is_zero.expr()),
503-
self.receiver.must_create.clone()]
504-
)]) * 1.expr() +
500+
self.receiver.rw_delta()+
505501
// +1 Write Account (sender) Balance
506502
// +1 Write Account (receiver) Balance
507503
not::expr(self.value_is_zero.expr()) * 2.expr()
@@ -510,10 +506,7 @@ impl<F: Field> TransferWithGasFeeGadget<F> {
510506
pub(crate) fn reversible_w_delta(&self) -> Expression<F> {
511507
// NOTE: Write Account (sender) Balance (Not Reversible tx fee)
512508
// +1 Write Account (receiver) CodeHash (account creation via code_hash update)
513-
and::expr([not::expr(self.receiver.receiver_exists.expr()), or::expr([
514-
not::expr(self.value_is_zero.expr()),
515-
self.receiver.must_create.clone()]
516-
)]) +
509+
self.receiver.rw_delta()+
517510
// +1 Write Account (sender) Balance
518511
// +1 Write Account (receiver) Balance
519512
not::expr(self.value_is_zero.expr()) * 2.expr()
@@ -524,19 +517,21 @@ impl<F: Field> TransferWithGasFeeGadget<F> {
524517
&self,
525518
region: &mut CachedRegion<'_, '_, F>,
526519
offset: usize,
527-
(sender_balance_sub_fee, prev_sender_balance_sub_fee): (U256, U256),
520+
(sender_balance_sub_fee, prev_sender_balance_sub_fee): (Option<U256>, Option<U256>),
528521
(sender_balance_sub_value, prev_sender_balance_sub_value): (U256, U256),
529522
(receiver_balance, prev_receiver_balance): (U256, U256),
530523
value: U256,
531-
gas_fee: U256,
524+
gas_fee: Option<U256>,
532525
) -> Result<(), Error> {
533-
self.sender_sub_fee.assign(
534-
region,
535-
offset,
536-
prev_sender_balance_sub_fee,
537-
vec![gas_fee],
538-
sender_balance_sub_fee,
539-
)?;
526+
if WITH_FEE {
527+
self.sender_sub_fee.as_ref().expect("Exists").assign(
528+
region,
529+
offset,
530+
prev_sender_balance_sub_fee.expect("exists"),
531+
vec![gas_fee.expect("exists")],
532+
sender_balance_sub_fee.expect("exists"),
533+
)?;
534+
}
540535
self.sender_sub_value.assign(
541536
region,
542537
offset,
@@ -556,91 +551,6 @@ impl<F: Field> TransferWithGasFeeGadget<F> {
556551
}
557552
}
558553

559-
/// The TransferGadget handles a transfer of value from sender to receiver. The
560-
/// transfer is only performed if the value is not zero. If the transfer is
561-
/// performed and the receiver account doesn't exist, it will be created by
562-
/// setting it's code_hash = EMPTY_HASH. This gadget is used in callop.
563-
#[derive(Clone, Debug)]
564-
pub(crate) struct TransferGadget<F> {
565-
sender: UpdateBalanceGadget<F, 2, false>,
566-
receiver: TransferToGadget<F>,
567-
pub(crate) value_is_zero: IsZeroWordGadget<F, Word32Cell<F>>,
568-
}
569-
570-
impl<F: Field> TransferGadget<F> {
571-
pub(crate) fn construct(
572-
cb: &mut EVMConstraintBuilder<F>,
573-
sender_address: WordLoHi<Expression<F>>,
574-
receiver_address: WordLoHi<Expression<F>>,
575-
receiver_exists: Expression<F>,
576-
must_create: bool,
577-
value: Word32Cell<F>,
578-
reversion_info: &mut ReversionInfo<F>,
579-
) -> Self {
580-
let value_is_zero = cb.is_zero_word(&value);
581-
// Skip transfer if value == 0
582-
let sender = cb.condition(not::expr(value_is_zero.expr()), |cb| {
583-
cb.decrease_balance(sender_address, value.clone(), Some(reversion_info))
584-
});
585-
let receiver = TransferToGadget::construct(
586-
cb,
587-
receiver_address,
588-
receiver_exists,
589-
must_create.expr(),
590-
value,
591-
Some(reversion_info),
592-
);
593-
594-
Self {
595-
sender,
596-
receiver,
597-
value_is_zero,
598-
}
599-
}
600-
601-
pub(crate) fn reversible_w_delta(&self) -> Expression<F> {
602-
// +1 Write Account (receiver) CodeHash (account creation via code_hash update)
603-
or::expr([
604-
not::expr(self.value_is_zero.expr()) * not::expr(self.receiver.receiver_exists.clone()),
605-
self.receiver.must_create.clone()]
606-
) * 1.expr() +
607-
// +1 Write Account (sender) Balance
608-
// +1 Write Account (receiver) Balance
609-
not::expr(self.value_is_zero.expr()) * 2.expr()
610-
}
611-
612-
pub(crate) fn assign(
613-
&self,
614-
region: &mut CachedRegion<'_, '_, F>,
615-
offset: usize,
616-
(sender_balance, sender_balance_prev): (U256, U256),
617-
(receiver_balance, receiver_balance_prev): (U256, U256),
618-
value: U256,
619-
) -> Result<(), Error> {
620-
self.sender.assign(
621-
region,
622-
offset,
623-
sender_balance_prev,
624-
vec![value],
625-
sender_balance,
626-
)?;
627-
self.receiver.assign(
628-
region,
629-
offset,
630-
(receiver_balance, receiver_balance_prev),
631-
value,
632-
)?;
633-
self.value_is_zero
634-
.assign_value(region, offset, Value::known(WordLoHi::from(value)))?;
635-
Ok(())
636-
}
637-
638-
pub(crate) fn rw_delta(&self) -> Expression<F> {
639-
// +1 Write Account (sender) Balance
640-
not::expr(self.value_is_zero.expr()) + self.receiver.rw_delta()
641-
}
642-
}
643-
644554
#[derive(Clone, Debug)]
645555
pub(crate) struct CommonCallGadget<F, MemAddrGadget, const IS_SUCCESS_CALL: bool> {
646556
pub is_success: Cell<F>,

0 commit comments

Comments
 (0)