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

Commit 3af8f8f

Browse files
authored
Merge branch 'main' into fix/begintx-missingconstraint
2 parents 2291146 + 41e3408 commit 3af8f8f

File tree

10 files changed

+170
-360
lines changed

10 files changed

+170
-360
lines changed

bus-mapping/src/circuit_input_builder/input_state_ref.rs

+11-58
Original file line numberDiff line numberDiff line change
@@ -559,13 +559,13 @@ impl<'a> CircuitInputStateRef<'a> {
559559
/// balance by `value`. If `fee` is existing (not None), also need to push 1
560560
/// non-reversible [`AccountOp`] to update `sender` balance by `fee`.
561561
#[allow(clippy::too_many_arguments)]
562-
pub fn transfer_with_fee(
562+
pub fn transfer(
563563
&mut self,
564564
step: &mut ExecStep,
565565
sender: Address,
566566
receiver: Address,
567567
receiver_exists: bool,
568-
must_create: bool,
568+
is_create: bool,
569569
value: Word,
570570
fee: Option<Word>,
571571
) -> Result<(), Error> {
@@ -608,82 +608,35 @@ impl<'a> CircuitInputStateRef<'a> {
608608
sender_balance_prev,
609609
sender_balance
610610
);
611-
// If receiver doesn't exist, create it
612-
if !receiver_exists && (!value.is_zero() || must_create) {
611+
612+
if !value.is_zero() {
613613
self.push_op_reversible(
614614
step,
615615
AccountOp {
616-
address: receiver,
617-
field: AccountField::CodeHash,
618-
value: CodeDB::empty_code_hash().to_word(),
619-
value_prev: Word::zero(),
616+
address: sender,
617+
field: AccountField::Balance,
618+
value: sender_balance,
619+
value_prev: sender_balance_prev,
620620
},
621621
)?;
622622
}
623-
if value.is_zero() {
624-
// Skip transfer if value == 0
625-
return Ok(());
626-
}
627623

628-
self.push_op_reversible(
629-
step,
630-
AccountOp {
631-
address: sender,
632-
field: AccountField::Balance,
633-
value: sender_balance,
634-
value_prev: sender_balance_prev,
635-
},
636-
)?;
637-
638-
let (_found, receiver_account) = self.sdb.get_account(&receiver);
639-
let receiver_balance_prev = receiver_account.balance;
640-
let receiver_balance = receiver_account.balance + value;
641-
self.push_op_reversible(
642-
step,
643-
AccountOp {
644-
address: receiver,
645-
field: AccountField::Balance,
646-
value: receiver_balance,
647-
value_prev: receiver_balance_prev,
648-
},
649-
)?;
624+
self.transfer_to(step, receiver, receiver_exists, is_create, value, true)?;
650625

651626
Ok(())
652627
}
653628

654-
/// Same functionality with `transfer_with_fee` but with `fee` set zero.
655-
pub fn transfer(
656-
&mut self,
657-
step: &mut ExecStep,
658-
sender: Address,
659-
receiver: Address,
660-
receiver_exists: bool,
661-
must_create: bool,
662-
value: Word,
663-
) -> Result<(), Error> {
664-
self.transfer_with_fee(
665-
step,
666-
sender,
667-
receiver,
668-
receiver_exists,
669-
must_create,
670-
value,
671-
None,
672-
)
673-
}
674-
675629
/// Transfer to an address. Create an account if it is not existed before.
676630
pub fn transfer_to(
677631
&mut self,
678632
step: &mut ExecStep,
679633
receiver: Address,
680634
receiver_exists: bool,
681-
must_create: bool,
635+
is_create: bool,
682636
value: Word,
683637
reversible: bool,
684638
) -> Result<(), Error> {
685-
// If receiver doesn't exist, create it
686-
if (!receiver_exists && !value.is_zero()) || must_create {
639+
if !receiver_exists && (!value.is_zero() || is_create) {
687640
self.account_write(
688641
step,
689642
receiver,

bus-mapping/src/evm/opcodes/begin_end_tx.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ fn gen_begin_tx_steps(state: &mut CircuitInputStateRef) -> Result<ExecStep, Erro
124124
}
125125

126126
// Transfer with fee
127-
state.transfer_with_fee(
127+
state.transfer(
128128
&mut exec_step,
129129
call.caller_address,
130130
call.address,

bus-mapping/src/evm/opcodes/callop.rs

+1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ impl<const N_ARGS: usize> Opcode for CallOpcode<N_ARGS> {
195195
callee_exists,
196196
false,
197197
call.value,
198+
None,
198199
)?;
199200
}
200201

bus-mapping/src/evm/opcodes/create.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,9 @@ impl<const IS_CREATE2: bool> Opcode for Create<IS_CREATE2> {
217217
caller.address,
218218
callee.address,
219219
callee_exists,
220-
!callee_exists,
220+
true,
221221
callee.value,
222+
None,
222223
)?;
223224

224225
// EIP 161, increase callee's nonce

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

+14-27
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},
@@ -42,7 +42,7 @@ pub(crate) struct BeginTxGadget<F> {
4242
call_callee_address: AccountAddress<F>,
4343
reversion_info: ReversionInfo<F>,
4444
sufficient_gas_left: RangeCheckGadget<F, N_BYTES_GAS>,
45-
transfer_with_gas_fee: TransferWithGasFeeGadget<F>,
45+
transfer_with_gas_fee: TransferGadget<F, true>,
4646
code_hash: WordLoHiCell<F>,
4747
is_empty_code_hash: IsEqualWordGadget<F, WordLoHi<Expression<F>>, WordLoHi<Expression<F>>>,
4848
caller_nonce_hash_bytes: Word32Cell<F>,
@@ -174,17 +174,16 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
174174
AccountFieldTag::CodeHash,
175175
code_hash.to_word(),
176176
);
177-
178177
// Transfer value from caller to callee, creating account if necessary.
179-
let transfer_with_gas_fee = TransferWithGasFeeGadget::construct(
178+
let transfer_with_gas_fee = TransferGadget::construct(
180179
cb,
181180
tx.caller_address.to_word(),
182181
tx.callee_address.to_word(),
183182
not::expr(callee_not_exists.expr()),
184-
or::expr([tx.is_create.expr(), callee_not_exists.expr()]),
183+
tx.is_create.expr(),
185184
tx.value.clone(),
186-
tx.mul_gas_fee_by_gas.product().clone(),
187185
&mut reversion_info,
186+
Some(tx.mul_gas_fee_by_gas.product().clone()),
188187
);
189188

190189
let caller_nonce_hash_bytes = cb.query_word32();
@@ -509,18 +508,15 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
509508
}
510509
let callee_exists =
511510
is_precompiled(&tx.to_or_contract_addr()) || !callee_code_hash.is_zero();
512-
let caller_balance_sub_fee_pair = rws.next().account_balance_pair();
513-
let must_create = tx.is_create();
514-
if !callee_exists && (!tx.value.is_zero() || must_create) {
515-
callee_code_hash = rws.next().account_codehash_pair().1;
516-
}
517-
let mut caller_balance_sub_value_pair = (zero, zero);
518-
let mut callee_balance_pair = (zero, zero);
519-
if !tx.value.is_zero() {
520-
caller_balance_sub_value_pair = rws.next().account_balance_pair();
521-
callee_balance_pair = rws.next().account_balance_pair();
522-
};
523-
511+
self.transfer_with_gas_fee.assign(
512+
region,
513+
offset,
514+
&mut rws,
515+
callee_exists,
516+
tx.value,
517+
tx.is_create(),
518+
Some(gas_fee),
519+
)?;
524520
self.begin_tx.assign(region, offset, tx)?;
525521
self.tx.assign(region, offset, tx)?;
526522

@@ -544,15 +540,6 @@ impl<F: Field> ExecutionGadget<F> for BeginTxGadget<F> {
544540
)?;
545541
self.sufficient_gas_left
546542
.assign(region, offset, F::from(tx.gas() - step.gas_cost))?;
547-
self.transfer_with_gas_fee.assign(
548-
region,
549-
offset,
550-
caller_balance_sub_fee_pair,
551-
caller_balance_sub_value_pair,
552-
callee_balance_pair,
553-
tx.value,
554-
gas_fee,
555-
)?;
556543
self.code_hash
557544
.assign_u256(region, offset, callee_code_hash)?;
558545
self.is_empty_code_hash.assign_u256(

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

+6-16
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,10 @@ 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-
0.expr(),
245+
false.expr(),
246246
call_gadget.value.clone(),
247247
&mut callee_reversion_info,
248+
None,
248249
)
249250
});
250251
// rwc_delta = 8 + is_delegatecall * 2 + call_gadget.rw_delta() +
@@ -866,20 +867,9 @@ impl<F: Field> ExecutionGadget<F> for CallOpGadget<F> {
866867
depth.low_u64() < 1025 && (!(is_call || is_callcode) || caller_balance >= value);
867868

868869
// conditionally assign
869-
if is_call && is_precheck_ok && !value.is_zero() {
870-
if !callee_exists {
871-
rws.next().account_codehash_pair(); // callee hash
872-
}
873-
874-
let caller_balance_pair = rws.next().account_balance_pair();
875-
let callee_balance_pair = rws.next().account_balance_pair();
876-
self.transfer.assign(
877-
region,
878-
offset,
879-
caller_balance_pair,
880-
callee_balance_pair,
881-
value,
882-
)?;
870+
if is_call && is_precheck_ok {
871+
self.transfer
872+
.assign(region, offset, &mut rws, callee_exists, value, false, None)?;
883873
}
884874

885875
self.opcode

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

+8-14
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>,
@@ -333,10 +333,11 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
333333
cb,
334334
create.caller_address(),
335335
contract_addr.to_word(),
336-
0.expr(),
337-
1.expr(),
336+
false.expr(),
337+
true.expr(),
338338
value.clone(),
339339
&mut callee_reversion_info,
340+
None,
340341
);
341342

342343
// EIP 161, the nonce of a newly created contract is 1
@@ -638,21 +639,14 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
638639

639640
let code_hash = if is_precheck_ok {
640641
if !is_address_collision {
641-
// transfer
642-
if callee_prev_code_hash.is_zero() {
643-
rws.next(); // codehash update
644-
}
645-
let [caller_balance_pair, callee_balance_pair] = if !value.is_zero() {
646-
[(); 2].map(|_| rws.next().account_balance_pair())
647-
} else {
648-
[(0.into(), 0.into()), (0.into(), 0.into())]
649-
};
650642
self.transfer.assign(
651643
region,
652644
offset,
653-
caller_balance_pair,
654-
callee_balance_pair,
645+
&mut rws,
646+
!callee_prev_code_hash.is_zero(),
655647
value,
648+
true,
649+
None,
656650
)?;
657651
}
658652

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

+16-26
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
MulWordByU64Gadget,
1212
},
1313
tx::EndTxHelperGadget,
14-
CachedRegion, Cell,
14+
CachedRegion, Cell, StepRws,
1515
},
1616
witness::{Block, Call, ExecStep, Transaction},
1717
},
@@ -75,10 +75,9 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
7575
tx_gas_price.clone(),
7676
effective_refund.min() + cb.curr.state.gas_left.expr(),
7777
);
78-
let gas_fee_refund = UpdateBalanceGadget::construct(
79-
cb,
78+
let gas_fee_refund = cb.increase_balance(
8079
tx_caller_address.to_word(),
81-
vec![mul_gas_price_by_refund.product().clone()],
80+
mul_gas_price_by_refund.product().clone(),
8281
None,
8382
);
8483

@@ -111,7 +110,6 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
111110
false.expr(),
112111
mul_effective_tip_by_gas_used.product().clone(),
113112
None,
114-
true,
115113
);
116114

117115
let end_tx = EndTxHelperGadget::construct(
@@ -152,9 +150,11 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
152150
step: &ExecStep,
153151
) -> Result<(), Error> {
154152
let gas_used = tx.gas() - step.gas_left;
155-
let (refund, _) = block.get_rws(step, 2).tx_refund_value_pair();
156-
let (caller_balance, caller_balance_prev) = block.get_rws(step, 3).account_balance_pair();
157-
let (coinbase_code_hash_prev, _) = block.get_rws(step, 4).account_codehash_pair();
153+
let mut rws = StepRws::new(block, step);
154+
rws.offset_add(2);
155+
let (refund, _) = rws.next().tx_refund_value_pair();
156+
let (caller_balance, caller_balance_prev) = rws.next().account_balance_pair();
157+
let (coinbase_code_hash_prev, _) = rws.next().account_codehash_pair();
158158

159159
self.tx_id
160160
.assign(region, offset, Value::known(F::from(tx.id)))?;
@@ -208,24 +208,14 @@ impl<F: Field> ExecutionGadget<F> for EndTxGadget<F> {
208208
.assign_u256(region, offset, coinbase_code_hash_prev)?;
209209
self.coinbase_code_hash_is_zero
210210
.assign_u256(region, offset, coinbase_code_hash_prev)?;
211-
if !coinbase_reward.is_zero() {
212-
let coinbase_balance_pair = block
213-
.get_rws(
214-
step,
215-
if coinbase_code_hash_prev.is_zero() {
216-
6
217-
} else {
218-
5
219-
},
220-
)
221-
.account_balance_pair();
222-
self.coinbase_reward.assign(
223-
region,
224-
offset,
225-
coinbase_balance_pair,
226-
effective_tip * gas_used,
227-
)?;
228-
}
211+
self.coinbase_reward.assign(
212+
region,
213+
offset,
214+
&mut rws,
215+
!coinbase_code_hash_prev.is_zero(),
216+
coinbase_reward,
217+
false,
218+
)?;
229219
self.is_persistent.assign(
230220
region,
231221
offset,

0 commit comments

Comments
 (0)