Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions ledger/src/proofs/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use crate::{
transaction_logic::protocol_state::{EpochLedger, ProtocolStateView},
},
staged_ledger::hash::StagedLedgerHash,
zkapps::intefaces::{SignedAmountBranchParam, SignedAmountInterface},
Inputs, ToInputs,
};

Expand Down Expand Up @@ -1375,7 +1376,6 @@ pub mod consensus {

let (new_total_currency, _overflow) = {
let total_currency: Amount = previous_state.total_currency;
w.exists(supply_increase.force_value());
total_currency
.to_checked()
.add_signed_flagged(supply_increase, w)
Expand Down Expand Up @@ -1638,10 +1638,14 @@ fn block_main<'a>(
txn_statement_ledger_hashes_equal(s1, &s2, w)
};

let supply_increase = w.exists_no_check(match txn_stmt_ledger_hashes_didn_t_change {
Boolean::True => CheckedSigned::zero(),
Boolean::False => txn_snark.supply_increase.to_checked(),
});
let supply_increase = CheckedSigned::on_if(
txn_stmt_ledger_hashes_didn_t_change.var(),
SignedAmountBranchParam {
on_true: &CheckedSigned::zero(),
on_false: &txn_snark.supply_increase.to_checked(),
},
w,
);

let (updated_consensus_state, consensus_state) = consensus::next_state_checked(
previous_state,
Expand Down
56 changes: 38 additions & 18 deletions ledger/src/proofs/numbers/currency.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::scan_state::currency::{self, Amount, Balance, Fee, Magnitude, MinMax, Sgn, Signed};
use crate::{
proofs::field::CircuitVar,
scan_state::currency::{self, Amount, Balance, Fee, Magnitude, MinMax, Sgn, Signed},
};
use std::{cell::Cell, cmp::Ordering::Less};

use crate::proofs::{
Expand Down Expand Up @@ -42,7 +45,7 @@ where
T: CheckedCurrency<F>,
{
pub magnitude: T,
pub sgn: Sgn,
pub sgn: CircuitVar<Sgn>,
pub value: Cell<Option<F>>,
}

Expand All @@ -65,7 +68,7 @@ where
F: FieldWitness + std::fmt::Debug,
T: CheckedCurrency<F> + std::fmt::Debug,
{
pub fn create(magnitude: T, sgn: Sgn, value: Option<F>) -> Self {
pub fn create(magnitude: T, sgn: CircuitVar<Sgn>, value: Option<F>) -> Self {
Self {
magnitude,
sgn,
Expand All @@ -77,32 +80,46 @@ where
let value = magnitude.to_field();
Self {
magnitude,
sgn: Sgn::Pos,
sgn: CircuitVar::Constant(Sgn::Pos),
value: Cell::new(Some(value)),
}
}

pub fn zero() -> Self {
Self::of_unsigned(T::zero())
Self {
magnitude: T::zero(),
sgn: CircuitVar::Constant(Sgn::Pos),
value: Cell::new(None),
}
}

// https://github.com/MinaProtocol/mina/blob/ca9c8c86aa21d3c346d28ea0be7ad4cb0c22bf7f/src/lib/transaction_snark/transaction_snark.ml#L1891-L1892
// https://github.com/MinaProtocol/mina/blob/ca9c8c86aa21d3c346d28ea0be7ad4cb0c22bf7f/src/lib/currency/currency.ml#L579
pub fn constant_zero() -> Self {
Self {
magnitude: T::zero(),
sgn: CircuitVar::Constant(Sgn::Pos),
value: Cell::new(Some(T::zero().to_field())),
}
}

pub fn negate(self) -> Self {
Self {
magnitude: self.magnitude,
sgn: self.sgn.negate(),
sgn: self.sgn.map(|sgn| sgn.negate()),
value: Cell::new(self.value.get().map(|f| f.neg())),
}
}

pub fn is_neg(&self) -> Boolean {
match self.sgn {
match self.sgn.value() {
Sgn::Pos => Boolean::False,
Sgn::Neg => Boolean::True,
}
}

pub fn is_pos(&self) -> Boolean {
match self.sgn {
match self.sgn.value() {
Sgn::Pos => Boolean::True,
Sgn::Neg => Boolean::False,
}
Expand All @@ -112,7 +129,7 @@ where
match self.value.get() {
Some(x) => x,
None => {
let sgn: F = self.sgn.to_field();
let sgn: F = self.sgn.value().to_field();
let magnitude: F = self.magnitude.to_field();
let value = w.exists_no_check(magnitude * sgn);
self.value.replace(Some(value));
Expand All @@ -125,7 +142,7 @@ where
match self.value.get() {
Some(x) => x,
None => {
let sgn: F = self.sgn.to_field();
let sgn: F = self.sgn.value().to_field();
let magnitude: F = self.magnitude.to_field();
magnitude * sgn
}
Expand All @@ -136,7 +153,7 @@ where
match self.value.get() {
Some(_) => {}
None => {
let sgn: F = self.sgn.to_field();
let sgn: F = self.sgn.value().to_field();
let magnitude: F = self.magnitude.to_field();
self.value.replace(Some(magnitude * sgn));
}
Expand All @@ -150,7 +167,7 @@ where
fn unchecked(&self) -> currency::Signed<T::Inner> {
currency::Signed {
magnitude: self.magnitude.to_inner(),
sgn: self.sgn,
sgn: *self.sgn.value(),
}
}

Expand Down Expand Up @@ -185,7 +202,7 @@ where

let res = Self {
magnitude: res_magnitude,
sgn,
sgn: CircuitVar::Var(sgn),
value: Cell::new(Some(res_value)),
};
(res, overflow)
Expand All @@ -211,19 +228,22 @@ where

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

Self::create(T::from_field(magnitude), sgn, Some(res_value))
Self::create(
T::from_field(magnitude),
CircuitVar::Var(sgn),
Some(res_value),
)
}

pub fn equal(&self, other: &Self, w: &mut Witness<F>) -> Boolean {
// We decompose this way because of OCaml evaluation order
let t2 = other.value(w);
let t1 = self.value(w);
let t2 = other.value(w);
field::equal(t1, t2, w)
}

pub fn const_equal(&self, other: &Self, w: &mut Witness<F>) -> Boolean {
let t2 = other.value(w);
let t1 = self.value(w);
let t2 = other.value(w);
field::equal(t1, t2, w)
}
}
Expand Down Expand Up @@ -497,7 +517,7 @@ macro_rules! impl_currency {
pub fn to_checked<F: FieldWitness>(&self) -> CheckedSigned<F, $name<F>> {
CheckedSigned {
magnitude: self.magnitude.to_checked(),
sgn: self.sgn,
sgn: CircuitVar::Var(self.sgn),
value: Cell::new(None),
}
}
Expand Down
17 changes: 9 additions & 8 deletions ledger/src/proofs/to_field_elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use crate::{

use super::{
field::{Boolean, CircuitVar, FieldWitness, GroupAffine},
numbers::currency::{CheckedCurrency, CheckedSigned},
step::PerProofWitness,
transaction::{
field_to_bits, InnerCurve, PlonkVerificationKeyEvals, StepMainProofState, StepMainStatement,
Expand Down Expand Up @@ -799,13 +798,6 @@ impl<F: FieldWitness, T: ToFieldElements<F>> ToFieldElements<F> for &T {
}
}

impl<F: FieldWitness, T: CheckedCurrency<F>> ToFieldElements<F> for CheckedSigned<F, T> {
fn to_field_elements(&self, fields: &mut Vec<F>) {
self.sgn.to_field_elements(fields);
self.magnitude.to_field_elements(fields);
}
}

impl<F: FieldWitness> ToFieldElements<F> for InnerCurve<F> {
fn to_field_elements(&self, fields: &mut Vec<F>) {
let GroupAffine::<F> { x, y, .. } = self.to_affine();
Expand All @@ -826,6 +818,15 @@ impl<F: FieldWitness> ToFieldElements<F> for CircuitVar<Boolean> {
}
}

impl<F: FieldWitness> ToFieldElements<F> for CircuitVar<Sgn> {
fn to_field_elements(&self, fields: &mut Vec<F>) {
match self {
CircuitVar::Constant(_) => (),
CircuitVar::Var(var) => var.to_field_elements(fields),
}
}
}

impl ToFieldElements<Fp> for StepMainStatement {
fn to_field_elements(&self, fields: &mut Vec<Fp>) {
let Self {
Expand Down
69 changes: 44 additions & 25 deletions ledger/src/proofs/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2285,6 +2285,7 @@ pub mod transaction_snark {
transaction_logic::{checked_cons_signed_command_payload, Coinbase},
},
sparse_ledger::SparseLedger,
zkapps::intefaces::{SignedAmountBranchParam, SignedAmountInterface},
AccountId, Inputs, PermissionTo, PermsConst, Timing, TimingAsRecordChecked, ToInputs,
};
use ark_ff::Zero;
Expand Down Expand Up @@ -3080,7 +3081,11 @@ pub mod transaction_snark {
Boolean::True => Sgn::Neg,
Boolean::False => Sgn::Pos,
};
CheckedSigned::create(CheckedAmount::of_fee(&fee), sgn, None)
CheckedSigned::create(
CheckedAmount::of_fee(&fee),
CircuitVar::Constant(sgn),
None,
)
};

let account_creation_fee = {
Expand All @@ -3090,7 +3095,7 @@ pub mod transaction_snark {
} else {
CheckedAmount::zero()
};
CheckedSigned::create(magnitude, Sgn::Neg, None)
CheckedSigned::create(magnitude, CircuitVar::Constant(Sgn::Neg), None)
};

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

let txn_global_slot = current_global_slot;
let timing = {
let txn_amount = w.exists_no_check(match amount.sgn {
let txn_amount = w.exists_no_check(match amount.sgn.value() {
Sgn::Neg => amount.magnitude,
Sgn::Pos => CheckedAmount::zero(),
});
Expand Down Expand Up @@ -3569,45 +3574,59 @@ pub mod transaction_snark {
let (fee_transfer_excess, fee_transfer_excess_overflowed) = {
let (magnitude, overflow) =
payload.body.amount.to_checked().add_flagged(&amount_fee, w);
(CheckedSigned::create(magnitude, Sgn::Neg, None), overflow)
(
CheckedSigned::create(magnitude, CircuitVar::Constant(Sgn::Neg), None),
overflow,
)
};

Boolean::assert_any(
&[is_fee_transfer.neg(), fee_transfer_excess_overflowed.neg()],
w,
);

let value = match is_fee_transfer {
Boolean::True => fee_transfer_excess,
Boolean::False => user_command_excess,
};
w.exists_no_check(value.magnitude);
value
CheckedSigned::on_if(
is_fee_transfer.var(),
SignedAmountBranchParam {
on_true: &fee_transfer_excess,
on_false: &user_command_excess,
},
w,
)
};

w.exists_no_check(match is_coinbase {
Boolean::True => then_value,
Boolean::False => else_value,
})
CheckedSigned::on_if(
is_coinbase.var(),
SignedAmountBranchParam {
on_true: &then_value,
on_false: &else_value,
},
w,
)
};

let supply_increase = {
let expected_supply_increase = match is_coinbase {
Boolean::True => CheckedSigned::of_unsigned(payload.body.amount.to_checked()),
Boolean::False => CheckedSigned::of_unsigned(CheckedAmount::zero()),
};
w.exists_no_check(expected_supply_increase.magnitude);
w.exists_no_check(expected_supply_increase.magnitude);
let expected_supply_increase = CheckedSigned::on_if(
is_coinbase.var(),
SignedAmountBranchParam {
on_true: &CheckedSigned::of_unsigned(payload.body.amount.to_checked()),
on_false: &CheckedSigned::of_unsigned(CheckedAmount::zero()),
},
w,
);

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

let new_account_fees_total = w.exists_no_check(match user_command_fails {
Boolean::True => zero_fee,
Boolean::False => new_account_fees,
});
let new_account_fees_total = CheckedSigned::on_if(
user_command_fails.var(),
SignedAmountBranchParam {
on_true: &zero_fee,
on_false: &new_account_fees,
},
w,
);

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

amt
Expand Down
4 changes: 2 additions & 2 deletions ledger/src/proofs/zkapp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1075,8 +1075,8 @@ fn zkapp_main(
ledger: witness.global_second_pass_ledger.clone(),
hash: statement.source.second_pass_ledger,
},
fee_excess: CheckedSigned::zero(),
supply_increase: CheckedSigned::zero(),
fee_excess: CheckedSigned::constant_zero(),
supply_increase: CheckedSigned::constant_zero(),
protocol_state: state_body.view(),
block_global_slot,
};
Expand Down
10 changes: 3 additions & 7 deletions ledger/src/zkapps/intefaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,7 @@ where
fn negate(&self) -> Self;
fn add_flagged(&self, other: &Self, w: &mut Self::W) -> (Self, Self::Bool);
fn of_unsigned(unsigned: Self::Amount) -> Self;
fn on_if<'a>(
b: Self::Bool,
param: SignedAmountBranchParam<&'a Self>,
w: &mut Self::W,
) -> &'a Self;
fn on_if(b: Self::Bool, param: SignedAmountBranchParam<&Self>, w: &mut Self::W) -> Self;
}

pub trait BalanceInterface
Expand Down Expand Up @@ -226,6 +222,7 @@ pub struct StackFrameMakeParams<'a, Calls> {
pub calls: &'a Calls,
}

#[derive(Debug)]
pub struct SignedAmountBranchParam<T> {
pub on_true: T,
pub on_false: T,
Expand Down Expand Up @@ -583,8 +580,7 @@ where
>;
type SignedAmount: SignedAmountInterface<W = Self::WitnessGenerator, Bool = Self::Bool, Amount = Self::Amount>
+ std::fmt::Debug
+ Clone
+ ToFieldElements<Fp>;
+ Clone;
type Amount: AmountInterface<W = Self::WitnessGenerator, Bool = Self::Bool> + Clone;
type Balance: BalanceInterface<
W = Self::WitnessGenerator,
Expand Down
Loading
Loading