Skip to content

Commit e183aef

Browse files
committed
Fix CheckedSigned::on_if
Make `CheckedSigned.sgn` a cvar to properly push it to the witness vector
1 parent 677103e commit e183aef

File tree

8 files changed

+115
-71
lines changed

8 files changed

+115
-71
lines changed

ledger/src/proofs/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1638,7 +1638,7 @@ fn block_main<'a>(
16381638
};
16391639

16401640
let supply_increase = w.exists_no_check(match txn_stmt_ledger_hashes_didn_t_change {
1641-
Boolean::True => CheckedSigned::const_zero(),
1641+
Boolean::True => CheckedSigned::zero(),
16421642
Boolean::False => txn_snark.supply_increase.to_checked(),
16431643
});
16441644

ledger/src/proofs/numbers/currency.rs

Lines changed: 22 additions & 19 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,36 @@ 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())
87-
}
88-
89-
pub fn const_zero() -> Self {
9089
Self {
9190
magnitude: T::zero(),
92-
sgn: Sgn::Pos,
91+
sgn: CircuitVar::Constant(Sgn::Pos),
9392
value: Cell::new(None),
9493
}
9594
}
9695

9796
pub fn negate(self) -> Self {
9897
Self {
9998
magnitude: self.magnitude,
100-
sgn: self.sgn.negate(),
99+
sgn: self.sgn.map(|sgn| sgn.negate()),
101100
value: Cell::new(self.value.get().map(|f| f.neg())),
102101
}
103102
}
104103

105104
pub fn is_neg(&self) -> Boolean {
106-
match self.sgn {
105+
match self.sgn.value() {
107106
Sgn::Pos => Boolean::False,
108107
Sgn::Neg => Boolean::True,
109108
}
110109
}
111110

112111
pub fn is_pos(&self) -> Boolean {
113-
match self.sgn {
112+
match self.sgn.value() {
114113
Sgn::Pos => Boolean::True,
115114
Sgn::Neg => Boolean::False,
116115
}
@@ -120,7 +119,7 @@ where
120119
match self.value.get() {
121120
Some(x) => x,
122121
None => {
123-
let sgn: F = self.sgn.to_field();
122+
let sgn: F = self.sgn.value().to_field();
124123
let magnitude: F = self.magnitude.to_field();
125124
let value = w.exists_no_check(magnitude * sgn);
126125
self.value.replace(Some(value));
@@ -133,7 +132,7 @@ where
133132
match self.value.get() {
134133
Some(x) => x,
135134
None => {
136-
let sgn: F = self.sgn.to_field();
135+
let sgn: F = self.sgn.value().to_field();
137136
let magnitude: F = self.magnitude.to_field();
138137
magnitude * sgn
139138
}
@@ -144,7 +143,7 @@ where
144143
match self.value.get() {
145144
Some(_) => {}
146145
None => {
147-
let sgn: F = self.sgn.to_field();
146+
let sgn: F = self.sgn.value().to_field();
148147
let magnitude: F = self.magnitude.to_field();
149148
self.value.replace(Some(magnitude * sgn));
150149
}
@@ -158,7 +157,7 @@ where
158157
fn unchecked(&self) -> currency::Signed<T::Inner> {
159158
currency::Signed {
160159
magnitude: self.magnitude.to_inner(),
161-
sgn: self.sgn,
160+
sgn: *self.sgn.value(),
162161
}
163162
}
164163

@@ -193,7 +192,7 @@ where
193192

194193
let res = Self {
195194
magnitude: res_magnitude,
196-
sgn,
195+
sgn: CircuitVar::Var(sgn),
197196
value: Cell::new(Some(res_value)),
198197
};
199198
(res, overflow)
@@ -219,7 +218,11 @@ where
219218

220219
range_check::<F, CURRENCY_NBITS>(magnitude, w);
221220

222-
Self::create(T::from_field(magnitude), sgn, Some(res_value))
221+
Self::create(
222+
T::from_field(magnitude),
223+
CircuitVar::Var(sgn),
224+
Some(res_value),
225+
)
223226
}
224227

225228
pub fn equal(&self, other: &Self, w: &mut Witness<F>) -> Boolean {
@@ -504,7 +507,7 @@ macro_rules! impl_currency {
504507
pub fn to_checked<F: FieldWitness>(&self) -> CheckedSigned<F, $name<F>> {
505508
CheckedSigned {
506509
magnitude: self.magnitude.to_checked(),
507-
sgn: self.sgn,
510+
sgn: CircuitVar::Var(self.sgn),
508511
value: Cell::new(None),
509512
}
510513
}

ledger/src/proofs/to_field_elements.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,24 @@ impl<F: FieldWitness> ToFieldElements<F> for CircuitVar<Boolean> {
826826
}
827827
}
828828

829+
impl<F: FieldWitness> ToFieldElements<F> for CircuitVar<Sgn> {
830+
fn to_field_elements(&self, fields: &mut Vec<F>) {
831+
match self {
832+
CircuitVar::Constant(_) => (),
833+
CircuitVar::Var(var) => var.to_field_elements(fields),
834+
}
835+
}
836+
}
837+
838+
// impl<F: FieldWitness, T: ToFieldElements<F>> ToFieldElements<F> for CircuitVar<T> {
839+
// fn to_field_elements(&self, fields: &mut Vec<F>) {
840+
// match self {
841+
// CircuitVar::Constant(_) => (),
842+
// CircuitVar::Var(var) => var.to_field_elements(fields),
843+
// }
844+
// }
845+
// }
846+
829847
impl ToFieldElements<Fp> for StepMainStatement {
830848
fn to_field_elements(&self, fields: &mut Vec<Fp>) {
831849
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/zkapps/intefaces.rs

Lines changed: 2 additions & 5 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<'a>(b: Self::Bool, param: SignedAmountBranchParam<&'a 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,

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<'a>(b: Self::Bool, param: SignedAmountBranchParam<&'a 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.clone(),
408+
false => on_false.clone(),
413409
}
414410
}
415411
}

ledger/src/zkapps/snark.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{fmt::Write, marker::PhantomData};
1+
use std::{cell::Cell, fmt::Write, marker::PhantomData};
22

33
use ark_ff::Zero;
44
use mina_hasher::Fp;
@@ -189,7 +189,7 @@ impl SignedAmountInterface for CheckedSigned<Fp, CheckedAmount<Fp>> {
189189
type Amount = SnarkAmount;
190190

191191
fn zero() -> Self {
192-
CheckedSigned::zero()
192+
CheckedSigned::of_unsigned(<CheckedAmount<_> as CheckedCurrency<Fp>>::zero())
193193
}
194194
fn is_neg(&self) -> Self::Bool {
195195
CheckedSigned::is_neg(self).var()
@@ -210,21 +210,32 @@ impl SignedAmountInterface for CheckedSigned<Fp, CheckedAmount<Fp>> {
210210
fn of_unsigned(unsigned: Self::Amount) -> Self {
211211
Self::of_unsigned(unsigned)
212212
}
213-
fn on_if<'a>(
214-
b: Self::Bool,
215-
param: SignedAmountBranchParam<&'a Self>,
216-
w: &mut Self::W,
217-
) -> &'a Self {
213+
fn on_if<'a>(b: Self::Bool, param: SignedAmountBranchParam<&'a Self>, w: &mut Self::W) -> Self {
218214
let SignedAmountBranchParam { on_true, on_false } = param;
219215

220-
let amount = w.exists_no_check(match b.as_boolean() {
216+
let amount = match b.as_boolean() {
221217
Boolean::True => on_true,
222218
Boolean::False => on_false,
223-
});
224-
if on_true.try_get_value().is_some() && on_false.try_get_value().is_some() {
225-
w.exists_no_check(amount.force_value());
219+
};
220+
221+
// TODO: This should be moved in a `Sgn::on_if`
222+
let sgn = match (on_true.sgn, on_false.sgn) {
223+
(CircuitVar::Constant(_), CircuitVar::Constant(_)) => {
224+
CircuitVar::Var(*amount.sgn.value())
225+
}
226+
_ => CircuitVar::Var(w.exists_no_check(*amount.sgn.value())),
227+
};
228+
w.exists_no_check(&amount.magnitude);
229+
230+
let value = match (on_true.try_get_value(), on_false.try_get_value()) {
231+
(Some(_), Some(_)) => Some(w.exists_no_check(amount.force_value())),
232+
_ => None,
233+
};
234+
Self {
235+
value: Cell::new(value),
236+
sgn,
237+
..amount.clone()
226238
}
227-
amount
228239
}
229240
}
230241

0 commit comments

Comments
 (0)