Skip to content

Commit af23b4a

Browse files
committed
Fix CheckedSigned::on_if behavior when sgn is a constant
Make `CheckedSigned.sgn` a cvar to properly push it to the witness vector Use `CheckedSigned::on_if` everywhere, instead of manually `match` it (which was incorrect)
1 parent 677103e commit af23b4a

File tree

9 files changed

+126
-85
lines changed

9 files changed

+126
-85
lines changed

ledger/src/proofs/block.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use crate::{
3535
transaction_logic::protocol_state::{EpochLedger, ProtocolStateView},
3636
},
3737
staged_ledger::hash::StagedLedgerHash,
38+
zkapps::intefaces::{SignedAmountBranchParam, SignedAmountInterface},
3839
Inputs, ToInputs,
3940
};
4041

@@ -1637,10 +1638,14 @@ fn block_main<'a>(
16371638
txn_statement_ledger_hashes_equal(s1, &s2, w)
16381639
};
16391640

1640-
let supply_increase = w.exists_no_check(match txn_stmt_ledger_hashes_didn_t_change {
1641-
Boolean::True => CheckedSigned::const_zero(),
1642-
Boolean::False => txn_snark.supply_increase.to_checked(),
1643-
});
1641+
let supply_increase = CheckedSigned::on_if(
1642+
txn_stmt_ledger_hashes_didn_t_change.var(),
1643+
SignedAmountBranchParam {
1644+
on_true: &CheckedSigned::zero(),
1645+
on_false: &txn_snark.supply_increase.to_checked(),
1646+
},
1647+
w,
1648+
);
16441649

16451650
let (updated_consensus_state, consensus_state) = consensus::next_state_checked(
16461651
previous_state,

ledger/src/proofs/numbers/currency.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::scan_state::currency::{self, Amount, Balance, Fee, Magnitude, MinMax, Sgn, Signed};
1+
use crate::{
2+
proofs::field::CircuitVar,
3+
scan_state::currency::{self, Amount, Balance, Fee, Magnitude, MinMax, Sgn, Signed},
4+
};
25
use std::{cell::Cell, cmp::Ordering::Less};
36

47
use crate::proofs::{
@@ -42,7 +45,7 @@ where
4245
T: CheckedCurrency<F>,
4346
{
4447
pub magnitude: T,
45-
pub sgn: Sgn,
48+
pub sgn: CircuitVar<Sgn>,
4649
pub value: Cell<Option<F>>,
4750
}
4851

@@ -65,7 +68,7 @@ where
6568
F: FieldWitness + std::fmt::Debug,
6669
T: CheckedCurrency<F> + std::fmt::Debug,
6770
{
68-
pub fn create(magnitude: T, sgn: Sgn, value: Option<F>) -> Self {
71+
pub fn create(magnitude: T, sgn: CircuitVar<Sgn>, value: Option<F>) -> Self {
6972
Self {
7073
magnitude,
7174
sgn,
@@ -77,40 +80,46 @@ where
7780
let value = magnitude.to_field();
7881
Self {
7982
magnitude,
80-
sgn: Sgn::Pos,
83+
sgn: CircuitVar::Constant(Sgn::Pos),
8184
value: Cell::new(Some(value)),
8285
}
8386
}
8487

8588
pub fn zero() -> Self {
86-
Self::of_unsigned(T::zero())
89+
Self {
90+
magnitude: T::zero(),
91+
sgn: CircuitVar::Constant(Sgn::Pos),
92+
value: Cell::new(None),
93+
}
8794
}
8895

89-
pub fn const_zero() -> Self {
96+
// https://github.com/MinaProtocol/mina/blob/ca9c8c86aa21d3c346d28ea0be7ad4cb0c22bf7f/src/lib/transaction_snark/transaction_snark.ml#L1891-L1892
97+
// https://github.com/MinaProtocol/mina/blob/ca9c8c86aa21d3c346d28ea0be7ad4cb0c22bf7f/src/lib/currency/currency.ml#L579
98+
pub fn constant_zero() -> Self {
9099
Self {
91100
magnitude: T::zero(),
92-
sgn: Sgn::Pos,
93-
value: Cell::new(None),
101+
sgn: CircuitVar::Constant(Sgn::Pos),
102+
value: Cell::new(Some(T::zero().to_field())),
94103
}
95104
}
96105

97106
pub fn negate(self) -> Self {
98107
Self {
99108
magnitude: self.magnitude,
100-
sgn: self.sgn.negate(),
109+
sgn: self.sgn.map(|sgn| sgn.negate()),
101110
value: Cell::new(self.value.get().map(|f| f.neg())),
102111
}
103112
}
104113

105114
pub fn is_neg(&self) -> Boolean {
106-
match self.sgn {
115+
match self.sgn.value() {
107116
Sgn::Pos => Boolean::False,
108117
Sgn::Neg => Boolean::True,
109118
}
110119
}
111120

112121
pub fn is_pos(&self) -> Boolean {
113-
match self.sgn {
122+
match self.sgn.value() {
114123
Sgn::Pos => Boolean::True,
115124
Sgn::Neg => Boolean::False,
116125
}
@@ -120,7 +129,7 @@ where
120129
match self.value.get() {
121130
Some(x) => x,
122131
None => {
123-
let sgn: F = self.sgn.to_field();
132+
let sgn: F = self.sgn.value().to_field();
124133
let magnitude: F = self.magnitude.to_field();
125134
let value = w.exists_no_check(magnitude * sgn);
126135
self.value.replace(Some(value));
@@ -133,7 +142,7 @@ where
133142
match self.value.get() {
134143
Some(x) => x,
135144
None => {
136-
let sgn: F = self.sgn.to_field();
145+
let sgn: F = self.sgn.value().to_field();
137146
let magnitude: F = self.magnitude.to_field();
138147
magnitude * sgn
139148
}
@@ -144,7 +153,7 @@ where
144153
match self.value.get() {
145154
Some(_) => {}
146155
None => {
147-
let sgn: F = self.sgn.to_field();
156+
let sgn: F = self.sgn.value().to_field();
148157
let magnitude: F = self.magnitude.to_field();
149158
self.value.replace(Some(magnitude * sgn));
150159
}
@@ -158,7 +167,7 @@ where
158167
fn unchecked(&self) -> currency::Signed<T::Inner> {
159168
currency::Signed {
160169
magnitude: self.magnitude.to_inner(),
161-
sgn: self.sgn,
170+
sgn: *self.sgn.value(),
162171
}
163172
}
164173

@@ -193,7 +202,7 @@ where
193202

194203
let res = Self {
195204
magnitude: res_magnitude,
196-
sgn,
205+
sgn: CircuitVar::Var(sgn),
197206
value: Cell::new(Some(res_value)),
198207
};
199208
(res, overflow)
@@ -219,7 +228,11 @@ where
219228

220229
range_check::<F, CURRENCY_NBITS>(magnitude, w);
221230

222-
Self::create(T::from_field(magnitude), sgn, Some(res_value))
231+
Self::create(
232+
T::from_field(magnitude),
233+
CircuitVar::Var(sgn),
234+
Some(res_value),
235+
)
223236
}
224237

225238
pub fn equal(&self, other: &Self, w: &mut Witness<F>) -> Boolean {
@@ -504,7 +517,7 @@ macro_rules! impl_currency {
504517
pub fn to_checked<F: FieldWitness>(&self) -> CheckedSigned<F, $name<F>> {
505518
CheckedSigned {
506519
magnitude: self.magnitude.to_checked(),
507-
sgn: self.sgn,
520+
sgn: CircuitVar::Var(self.sgn),
508521
value: Cell::new(None),
509522
}
510523
}

ledger/src/proofs/to_field_elements.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use crate::{
3232

3333
use super::{
3434
field::{Boolean, CircuitVar, FieldWitness, GroupAffine},
35-
numbers::currency::{CheckedCurrency, CheckedSigned},
3635
step::PerProofWitness,
3736
transaction::{
3837
field_to_bits, InnerCurve, PlonkVerificationKeyEvals, StepMainProofState, StepMainStatement,
@@ -799,13 +798,6 @@ impl<F: FieldWitness, T: ToFieldElements<F>> ToFieldElements<F> for &T {
799798
}
800799
}
801800

802-
impl<F: FieldWitness, T: CheckedCurrency<F>> ToFieldElements<F> for CheckedSigned<F, T> {
803-
fn to_field_elements(&self, fields: &mut Vec<F>) {
804-
self.sgn.to_field_elements(fields);
805-
self.magnitude.to_field_elements(fields);
806-
}
807-
}
808-
809801
impl<F: FieldWitness> ToFieldElements<F> for InnerCurve<F> {
810802
fn to_field_elements(&self, fields: &mut Vec<F>) {
811803
let GroupAffine::<F> { x, y, .. } = self.to_affine();
@@ -826,6 +818,15 @@ impl<F: FieldWitness> ToFieldElements<F> for CircuitVar<Boolean> {
826818
}
827819
}
828820

821+
impl<F: FieldWitness> ToFieldElements<F> for CircuitVar<Sgn> {
822+
fn to_field_elements(&self, fields: &mut Vec<F>) {
823+
match self {
824+
CircuitVar::Constant(_) => (),
825+
CircuitVar::Var(var) => var.to_field_elements(fields),
826+
}
827+
}
828+
}
829+
829830
impl ToFieldElements<Fp> for StepMainStatement {
830831
fn to_field_elements(&self, fields: &mut Vec<Fp>) {
831832
let Self {

ledger/src/proofs/transaction.rs

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2285,6 +2285,7 @@ pub mod transaction_snark {
22852285
transaction_logic::{checked_cons_signed_command_payload, Coinbase},
22862286
},
22872287
sparse_ledger::SparseLedger,
2288+
zkapps::intefaces::{SignedAmountBranchParam, SignedAmountInterface},
22882289
AccountId, Inputs, PermissionTo, PermsConst, Timing, TimingAsRecordChecked, ToInputs,
22892290
};
22902291
use ark_ff::Zero;
@@ -3080,7 +3081,11 @@ pub mod transaction_snark {
30803081
Boolean::True => Sgn::Neg,
30813082
Boolean::False => Sgn::Pos,
30823083
};
3083-
CheckedSigned::create(CheckedAmount::of_fee(&fee), sgn, None)
3084+
CheckedSigned::create(
3085+
CheckedAmount::of_fee(&fee),
3086+
CircuitVar::Constant(sgn),
3087+
None,
3088+
)
30843089
};
30853090

30863091
let account_creation_fee = {
@@ -3090,7 +3095,7 @@ pub mod transaction_snark {
30903095
} else {
30913096
CheckedAmount::zero()
30923097
};
3093-
CheckedSigned::create(magnitude, Sgn::Neg, None)
3098+
CheckedSigned::create(magnitude, CircuitVar::Constant(Sgn::Neg), None)
30943099
};
30953100

30963101
new_account_fees = account_creation_fee.clone();
@@ -3113,7 +3118,7 @@ pub mod transaction_snark {
31133118

31143119
let txn_global_slot = current_global_slot;
31153120
let timing = {
3116-
let txn_amount = w.exists_no_check(match amount.sgn {
3121+
let txn_amount = w.exists_no_check(match amount.sgn.value() {
31173122
Sgn::Neg => amount.magnitude,
31183123
Sgn::Pos => CheckedAmount::zero(),
31193124
});
@@ -3569,45 +3574,59 @@ pub mod transaction_snark {
35693574
let (fee_transfer_excess, fee_transfer_excess_overflowed) = {
35703575
let (magnitude, overflow) =
35713576
payload.body.amount.to_checked().add_flagged(&amount_fee, w);
3572-
(CheckedSigned::create(magnitude, Sgn::Neg, None), overflow)
3577+
(
3578+
CheckedSigned::create(magnitude, CircuitVar::Constant(Sgn::Neg), None),
3579+
overflow,
3580+
)
35733581
};
35743582

35753583
Boolean::assert_any(
35763584
&[is_fee_transfer.neg(), fee_transfer_excess_overflowed.neg()],
35773585
w,
35783586
);
35793587

3580-
let value = match is_fee_transfer {
3581-
Boolean::True => fee_transfer_excess,
3582-
Boolean::False => user_command_excess,
3583-
};
3584-
w.exists_no_check(value.magnitude);
3585-
value
3588+
CheckedSigned::on_if(
3589+
is_fee_transfer.var(),
3590+
SignedAmountBranchParam {
3591+
on_true: &fee_transfer_excess,
3592+
on_false: &user_command_excess,
3593+
},
3594+
w,
3595+
)
35863596
};
35873597

3588-
w.exists_no_check(match is_coinbase {
3589-
Boolean::True => then_value,
3590-
Boolean::False => else_value,
3591-
})
3598+
CheckedSigned::on_if(
3599+
is_coinbase.var(),
3600+
SignedAmountBranchParam {
3601+
on_true: &then_value,
3602+
on_false: &else_value,
3603+
},
3604+
w,
3605+
)
35923606
};
35933607

35943608
let supply_increase = {
3595-
let expected_supply_increase = match is_coinbase {
3596-
Boolean::True => CheckedSigned::of_unsigned(payload.body.amount.to_checked()),
3597-
Boolean::False => CheckedSigned::of_unsigned(CheckedAmount::zero()),
3598-
};
3599-
w.exists_no_check(expected_supply_increase.magnitude);
3600-
w.exists_no_check(expected_supply_increase.magnitude);
3609+
let expected_supply_increase = CheckedSigned::on_if(
3610+
is_coinbase.var(),
3611+
SignedAmountBranchParam {
3612+
on_true: &CheckedSigned::of_unsigned(payload.body.amount.to_checked()),
3613+
on_false: &CheckedSigned::of_unsigned(CheckedAmount::zero()),
3614+
},
3615+
w,
3616+
);
36013617

36023618
let (amt0, _overflow0) = expected_supply_increase
36033619
.add_flagged(&CheckedSigned::of_unsigned(burned_tokens).negate(), w);
36043620

3605-
let new_account_fees_total = w.exists_no_check(match user_command_fails {
3606-
Boolean::True => zero_fee,
3607-
Boolean::False => new_account_fees,
3608-
});
3621+
let new_account_fees_total = CheckedSigned::on_if(
3622+
user_command_fails.var(),
3623+
SignedAmountBranchParam {
3624+
on_true: &zero_fee,
3625+
on_false: &new_account_fees,
3626+
},
3627+
w,
3628+
);
36093629

3610-
w.exists(new_account_fees_total.force_value()); // Made in the `add_flagged` call
36113630
let (amt, _overflow) = amt0.add_flagged(&new_account_fees_total, w);
36123631

36133632
amt

ledger/src/proofs/zkapp.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,8 +1075,8 @@ fn zkapp_main(
10751075
ledger: witness.global_second_pass_ledger.clone(),
10761076
hash: statement.source.second_pass_ledger,
10771077
},
1078-
fee_excess: CheckedSigned::zero(),
1079-
supply_increase: CheckedSigned::zero(),
1078+
fee_excess: CheckedSigned::constant_zero(),
1079+
supply_increase: CheckedSigned::constant_zero(),
10801080
protocol_state: state_body.view(),
10811081
block_global_slot,
10821082
};

ledger/src/zkapps/intefaces.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,7 @@ where
142142
fn negate(&self) -> Self;
143143
fn add_flagged(&self, other: &Self, w: &mut Self::W) -> (Self, Self::Bool);
144144
fn of_unsigned(unsigned: Self::Amount) -> Self;
145-
fn on_if<'a>(
146-
b: Self::Bool,
147-
param: SignedAmountBranchParam<&'a Self>,
148-
w: &mut Self::W,
149-
) -> &'a Self;
145+
fn on_if(b: Self::Bool, param: SignedAmountBranchParam<&Self>, w: &mut Self::W) -> Self;
150146
}
151147

152148
pub trait BalanceInterface
@@ -226,6 +222,7 @@ pub struct StackFrameMakeParams<'a, Calls> {
226222
pub calls: &'a Calls,
227223
}
228224

225+
#[derive(Debug)]
229226
pub struct SignedAmountBranchParam<T> {
230227
pub on_true: T,
231228
pub on_false: T,
@@ -583,8 +580,7 @@ where
583580
>;
584581
type SignedAmount: SignedAmountInterface<W = Self::WitnessGenerator, Bool = Self::Bool, Amount = Self::Amount>
585582
+ std::fmt::Debug
586-
+ Clone
587-
+ ToFieldElements<Fp>;
583+
+ Clone;
588584
type Amount: AmountInterface<W = Self::WitnessGenerator, Bool = Self::Bool> + Clone;
589585
type Balance: BalanceInterface<
590586
W = Self::WitnessGenerator,

ledger/src/zkapps/non_snark.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -401,15 +401,11 @@ impl SignedAmountInterface for Signed<Amount> {
401401
fn of_unsigned(unsigned: Self::Amount) -> Self {
402402
Self::of_unsigned(unsigned)
403403
}
404-
fn on_if<'a>(
405-
b: Self::Bool,
406-
param: SignedAmountBranchParam<&'a Self>,
407-
w: &mut Self::W,
408-
) -> &'a Self {
404+
fn on_if(b: Self::Bool, param: SignedAmountBranchParam<&Self>, w: &mut Self::W) -> Self {
409405
let SignedAmountBranchParam { on_true, on_false } = param;
410406
match b {
411-
true => on_true,
412-
false => on_false,
407+
true => *on_true,
408+
false => *on_false,
413409
}
414410
}
415411
}

0 commit comments

Comments
 (0)