Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
54 changes: 42 additions & 12 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,19 @@ use rand::{prelude::SliceRandom, CryptoRng, RngCore};
use zcash_note_encryption_zsa::NoteEncryption;

use crate::builder::BuildError::{BurnNative, BurnZero};
use crate::orchard_flavor::{OrchardVanilla, OrchardZSA};
use crate::{
action::Action,
address::Address,
bundle::{derive_bvk, Authorization, Authorized, Bundle, Flags},
circuit::{Circuit, Instance, OrchardCircuit, Proof, ProvingKey},
circuit::{Circuit, Instance, Proof, ProvingKey, Witnesses},
keys::{
FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey,
SpendingKey,
},
note::{AssetBase, Note, Rho, TransmittedNoteCiphertext},
note_encryption::{OrchardDomain, OrchardDomainCommon},
orchard_flavor::OrchardFlavor,
orchard_flavor::{Flavor, OrchardFlavor},
primitives::redpallas::{self, Binding, SpendAuth},
tree::{Anchor, MerklePath},
value::{self, NoteValue, OverflowError, ValueCommitTrapdoor, ValueCommitment, ValueSum},
Expand Down Expand Up @@ -397,7 +398,7 @@ impl ActionInfo {
fn build<D: OrchardDomainCommon>(
self,
mut rng: impl RngCore,
) -> (Action<SigningMetadata, D>, Circuit<D>) {
) -> (Action<SigningMetadata, D>, Witnesses) {
assert_eq!(
self.spend.note.asset(),
self.output.asset,
Expand Down Expand Up @@ -445,15 +446,15 @@ impl ActionInfo {
parts: SigningParts { ak, alpha },
},
),
Circuit::<D>::from_action_context_unchecked(self.spend, note, alpha, self.rcv),
Witnesses::from_action_context_unchecked(self.spend, note, alpha, self.rcv),
)
}
}

/// Type alias for an in-progress bundle that has no proofs or signatures.
///
/// This is returned by [`Builder::build`].
pub type UnauthorizedBundle<V, D> = Bundle<InProgress<Unproven<D>, Unauthorized>, V, D>;
pub type UnauthorizedBundle<V, D> = Bundle<InProgress<Unproven, Unauthorized>, V, D>;

/// Metadata about a bundle created by [`bundle`] or [`Builder::build`] that is not
/// necessarily recoverable from the bundle itself.
Expand Down Expand Up @@ -863,7 +864,7 @@ pub fn bundle<V: TryFrom<i64>, FL: OrchardFlavor>(
.into_bsk();

// Create the actions.
let (actions, circuits): (Vec<_>, Vec<_>) =
let (actions, witnesses): (Vec<_>, Vec<_>) =
pre_actions.into_iter().map(|a| a.build(&mut rng)).unzip();

let burn = burn
Expand Down Expand Up @@ -892,7 +893,10 @@ pub fn bundle<V: TryFrom<i64>, FL: OrchardFlavor>(
burn,
anchor,
InProgress {
proof: Unproven { circuits },
proof: Unproven {
witnesses,
circuit_flavor: FL::flavor(),
},
sigs: Unauthorized { bsk },
},
),
Expand Down Expand Up @@ -935,23 +939,49 @@ impl<P: fmt::Debug, S: InProgressSignatures> Authorization for InProgress<P, S>
///
/// This struct contains the private data needed to create a [`Proof`] for a [`Bundle`].
#[derive(Clone, Debug)]
pub struct Unproven<C: OrchardCircuit> {
circuits: Vec<Circuit<C>>,
pub struct Unproven {
witnesses: Vec<Witnesses>,
circuit_flavor: Flavor,
}

impl<S: InProgressSignatures, C: OrchardCircuit> InProgress<Unproven<C>, S> {
impl<S: InProgressSignatures> InProgress<Unproven, S> {
/// Creates the proof for this bundle.
pub fn create_proof(
&self,
pk: &ProvingKey,
instances: &[Instance],
rng: impl RngCore,
) -> Result<Proof, halo2_proofs::plonk::Error> {
Proof::create(pk, &self.proof.circuits, instances, rng)
match self.proof.circuit_flavor {
Flavor::OrchardVanillaFlavor => {
let circuits = self
.proof
.witnesses
.iter()
.map(|witnesses| Circuit::<OrchardVanilla> {
witnesses: witnesses.clone(),
phantom: std::marker::PhantomData,
})
.collect::<Vec<Circuit<OrchardVanilla>>>();
Proof::create(pk, &circuits, instances, rng)
}
Flavor::OrchardZSAFlavor => {
let circuits = self
.proof
.witnesses
.iter()
.map(|witnesses| Circuit::<OrchardZSA> {
witnesses: witnesses.clone(),
phantom: std::marker::PhantomData,
})
.collect::<Vec<Circuit<OrchardZSA>>>();
Proof::create(pk, &circuits, instances, rng)
}
}
}
}

impl<S: InProgressSignatures, V, FL: OrchardFlavor> Bundle<InProgress<Unproven<FL>, S>, V, FL> {
impl<S: InProgressSignatures, V, FL: OrchardFlavor> Bundle<InProgress<Unproven, S>, V, FL> {
/// Creates the proof for this bundle.
pub fn create_proof(
self,
Expand Down
21 changes: 13 additions & 8 deletions src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub trait OrchardCircuit: Sized + Default {

/// Wrapper for configure function of plonk::Circuit trait
fn synthesize(
circuit: &Circuit<Self>,
circuit: &Witnesses,
config: Self::Config,
layouter: impl Layouter<pallas::Base>,
) -> Result<(), plonk::Error>;
Expand All @@ -128,13 +128,20 @@ impl<C: OrchardCircuit> plonk::Circuit<pallas::Base> for Circuit<C> {
config: Self::Config,
layouter: impl Layouter<pallas::Base>,
) -> Result<(), plonk::Error> {
C::synthesize(self, config, layouter)
C::synthesize(&self.witnesses, config, layouter)
}
}

/// The Orchard Action circuit.
#[derive(Clone, Debug, Default)]
pub struct Circuit<D> {
pub(crate) witnesses: Witnesses,
pub(crate) phantom: std::marker::PhantomData<D>,
}

/// The Orchard Action witnesses
#[derive(Clone, Debug, Default)]
pub struct Witnesses {
pub(crate) path: Value<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>,
pub(crate) pos: Value<u32>,
pub(crate) g_d_old: Value<NonIdentityPallasPoint>,
Expand All @@ -157,10 +164,9 @@ pub struct Circuit<D> {
pub(crate) rcv: Value<ValueCommitTrapdoor>,
pub(crate) asset: Value<AssetBase>,
pub(crate) split_flag: Value<bool>,
phantom: std::marker::PhantomData<D>,
}

impl<D> Circuit<D> {
impl Witnesses {
/// This constructor is public to enable creation of custom builders.
/// If you are not creating a custom builder, use [`Builder`] to compose
/// and authorize a transaction.
Expand All @@ -181,7 +187,7 @@ impl<D> Circuit<D> {
output_note: Note,
alpha: pallas::Scalar,
rcv: ValueCommitTrapdoor,
) -> Option<Circuit<D>> {
) -> Option<Self> {
(Rho::from_nf_old(spend.note.nullifier(&spend.fvk)) == output_note.rho())
.then(|| Self::from_action_context_unchecked(spend, output_note, alpha, rcv))
}
Expand All @@ -191,7 +197,7 @@ impl<D> Circuit<D> {
output_note: Note,
alpha: pallas::Scalar,
rcv: ValueCommitTrapdoor,
) -> Circuit<D> {
) -> Self {
let sender_address = spend.note.recipient();
let rho_old = spend.note.rho();
let psi_old = spend.note.rseed().psi(&rho_old);
Expand All @@ -204,7 +210,7 @@ impl<D> Circuit<D> {
let psi_new = output_note.rseed().psi(&rho_new);
let rcm_new = output_note.rseed().rcm(&rho_new);

Circuit {
Witnesses {
path: Value::known(spend.merkle_path.auth_path()),
pos: Value::known(spend.merkle_path.position()),
g_d_old: Value::known(sender_address.g_d()),
Expand All @@ -227,7 +233,6 @@ impl<D> Circuit<D> {
rcv: Value::known(rcv),
asset: Value::known(spend.note.asset()),
split_flag: Value::known(spend.split_flag),
phantom: std::marker::PhantomData,
}
}
}
Expand Down
80 changes: 31 additions & 49 deletions src/circuit/circuit_vanilla.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::{
circuit::derive_nullifier::gadgets::derive_nullifier,
circuit::note_commit::gadgets::note_commit,
circuit::value_commit_orchard::gadgets::value_commit_orchard,
circuit::Config,
circuit::{Config, Witnesses},
constants::{OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains},
orchard_flavor::OrchardVanilla,
};
Expand All @@ -37,8 +37,8 @@ use super::{
commit_ivk::CommitIvkChip,
gadget::{add_chip::AddChip, assign_free_advice},
note_commit::NoteCommitChip,
Circuit, OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, NF_OLD,
RK_X, RK_Y,
OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, NF_OLD, RK_X,
RK_Y,
};

impl OrchardCircuit for OrchardVanilla {
Expand Down Expand Up @@ -235,7 +235,7 @@ impl OrchardCircuit for OrchardVanilla {

#[allow(non_snake_case)]
fn synthesize(
circuit: &Circuit<Self>,
circuit: &Witnesses,
config: Self::Config,
mut layouter: impl Layouter<pallas::Base>,
) -> Result<(), plonk::Error> {
Expand Down Expand Up @@ -620,6 +620,7 @@ mod tests {
use pasta_curves::pallas;
use rand::{rngs::OsRng, RngCore};

use crate::circuit::Witnesses;
use crate::{
bundle::Flags,
circuit::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K},
Expand Down Expand Up @@ -658,29 +659,31 @@ mod tests {

(
OrchardCircuitVanilla {
path: Value::known(path.auth_path()),
pos: Value::known(path.position()),
g_d_old: Value::known(sender_address.g_d()),
pk_d_old: Value::known(*sender_address.pk_d()),
v_old: Value::known(spent_note.value()),
rho_old: Value::known(spent_note.rho()),
psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())),
rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())),
cm_old: Value::known(spent_note.commitment()),
// For non split note, psi_nf is equal to psi_old
psi_nf: Value::known(psi_old),
alpha: Value::known(alpha),
ak: Value::known(ak),
nk: Value::known(nk),
rivk: Value::known(rivk),
g_d_new: Value::known(output_note.recipient().g_d()),
pk_d_new: Value::known(*output_note.recipient().pk_d()),
v_new: Value::known(output_note.value()),
psi_new: Value::known(output_note.rseed().psi(&output_note.rho())),
rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())),
rcv: Value::known(rcv),
asset: Value::known(spent_note.asset()),
split_flag: Value::known(false),
witnesses: Witnesses {
path: Value::known(path.auth_path()),
pos: Value::known(path.position()),
g_d_old: Value::known(sender_address.g_d()),
pk_d_old: Value::known(*sender_address.pk_d()),
v_old: Value::known(spent_note.value()),
rho_old: Value::known(spent_note.rho()),
psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())),
rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())),
cm_old: Value::known(spent_note.commitment()),
// For non split note, psi_nf is equal to psi_old
psi_nf: Value::known(psi_old),
alpha: Value::known(alpha),
ak: Value::known(ak),
nk: Value::known(nk),
rivk: Value::known(rivk),
g_d_new: Value::known(output_note.recipient().g_d()),
pk_d_new: Value::known(*output_note.recipient().pk_d()),
v_new: Value::known(output_note.value()),
psi_new: Value::known(output_note.rseed().psi(&output_note.rho())),
rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())),
rcv: Value::known(rcv),
asset: Value::known(spent_note.asset()),
split_flag: Value::known(false),
},
phantom: std::marker::PhantomData,
},
Instance {
Expand Down Expand Up @@ -858,28 +861,7 @@ mod tests {
.unwrap();

let circuit = OrchardCircuitVanilla {
path: Value::unknown(),
pos: Value::unknown(),
g_d_old: Value::unknown(),
pk_d_old: Value::unknown(),
v_old: Value::unknown(),
rho_old: Value::unknown(),
psi_old: Value::unknown(),
rcm_old: Value::unknown(),
cm_old: Value::unknown(),
psi_nf: Value::unknown(),
alpha: Value::unknown(),
ak: Value::unknown(),
nk: Value::unknown(),
rivk: Value::unknown(),
g_d_new: Value::unknown(),
pk_d_new: Value::unknown(),
v_new: Value::unknown(),
psi_new: Value::unknown(),
rcm_new: Value::unknown(),
rcv: Value::unknown(),
asset: Value::unknown(),
split_flag: Value::unknown(),
witnesses: Witnesses::default(),
phantom: std::marker::PhantomData,
};
halo2_proofs::dev::CircuitLayout::default()
Expand Down
Loading