Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add generate-proof-input for Transfer #133

Merged
merged 12 commits into from
Jun 28, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- [\#126](https://github.com/Manta-Network/manta-rs/pull/126) Add ECLAIR v0 scaffolding and deprecate old compiler patterns
- [\#128](https://github.com/Manta-Network/manta-rs/pull/128) Add more parameter loading utilities
- [\#130](https://github.com/Manta-Network/manta-rs/pull/130) Add the sage script and the hardcoded tests for the security of mds matrix
- [\#133](https://github.com/Manta-Network/manta-rs/pull/133) Add public input genenration to `Transfer`

### Changed
- [\#132](https://github.com/Manta-Network/manta-rs/pull/132) Simplify algebra APIs and removing ECC-specific design
Expand Down
39 changes: 35 additions & 4 deletions manta-accounting/src/transfer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,13 @@ where
void_number: self.void_number,
}
}

/// Extends proof public input with `self`.
#[inline]
pub fn extend_input(&self, input: &mut ProofInput<C>) {
C::ProofSystem::extend(input, self.utxo_membership_proof.output());
C::ProofSystem::extend(input, &self.void_number);
}
}

/// Sender Variable
Expand Down Expand Up @@ -1195,8 +1202,6 @@ where
/// Extends proof public input with `self`.
#[inline]
pub fn extend_input(&self, input: &mut ProofInput<C>) {
// TODO: Add a "public part" trait that extracts the public part of `Sender` (using
// `SenderVar` to determine the types), then generate this method automatically.
C::ProofSystem::extend(input, &self.utxo_accumulator_output);
C::ProofSystem::extend(input, &self.void_number);
}
Expand Down Expand Up @@ -1396,6 +1401,12 @@ where
encrypted_note: self.encrypted_note,
}
}

/// Extends proof public input with `self`.
#[inline]
pub fn extend_input(&self, input: &mut ProofInput<C>) {
C::ProofSystem::extend(input, &self.utxo);
}
}

/// Receiver Variable
Expand Down Expand Up @@ -1610,8 +1621,6 @@ where
/// Extends proof public input with `self`.
#[inline]
pub fn extend_input(&self, input: &mut ProofInput<C>) {
// TODO: Add a "public part" trait that extracts the public part of `Receiver` (using
// `ReceiverVar` to determine the types), then generate this method automatically.
C::ProofSystem::extend(input, &self.utxo);
}

Expand Down Expand Up @@ -1724,6 +1733,28 @@ where
Self::new_unchecked(asset_id, sources, senders, receivers, sinks)
}

/// Generates the public input for the [`Transfer`] validation proof.
#[inline]
pub fn generate_proof_input(&self) -> ProofInput<C> {
let mut input = Default::default();
if let Some(asset_id) = self.asset_id {
C::ProofSystem::extend(&mut input, &asset_id);
}
self.sources
.iter()
.for_each(|source| C::ProofSystem::extend(&mut input, source));
self.senders
.iter()
.for_each(|sender| sender.extend_input(&mut input));
self.receivers
.iter()
.for_each(|receiver| receiver.extend_input(&mut input));
self.sinks
.iter()
.for_each(|sink| C::ProofSystem::extend(&mut input, sink));
input
}

/// Checks that the [`Transfer`] has a valid shape.
#[inline]
fn check_shape(has_visible_asset_id: bool) {
Expand Down
32 changes: 32 additions & 0 deletions manta-accounting/src/transfer/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ use manta_crypto::{
};
use manta_util::into_array_unchecked;

use super::ProofInput;

/// Samples a distribution over `count`-many values summing to `total`.
///
/// # Warning
Expand Down Expand Up @@ -243,6 +245,36 @@ where
&post.validity_proof,
)
}

/// Checks if `generate_proof_input` from [`Transfer`] and [`TransferPost`] gives the same [`ProofInput`].
#[inline]
pub fn sample_and_check_generate_proof_input_compatibility<A, R>(
public_parameters: &ProofSystemPublicParameters<C>,
parameters: &Parameters<C>,
utxo_accumulator: &mut A,
rng: &mut R,
) -> Result<bool, ProofSystemError<C>>
where
A: Accumulator<Item = Utxo<C>, Model = C::UtxoAccumulatorModel>,
R: CryptoRng + RngCore + ?Sized,
ProofInput<C>: PartialEq,
ProofSystemError<C>: Debug,
{
let transfer = Self::sample(
TransferDistribution {
parameters,
utxo_accumulator,
},
rng,
);
let full_parameters = FullParameters::new(parameters, utxo_accumulator.model());
let (proving_context, _) = Self::generate_context(public_parameters, full_parameters, rng)?;
Ok(transfer.generate_proof_input()
== transfer
.into_post(full_parameters, &proving_context, rng)
.expect("Unable to convert `Transfer` into `TransferPost`.")
.generate_proof_input())
}
}

impl<C> TransferPost<C>
Expand Down
36 changes: 36 additions & 0 deletions manta-pay/src/test/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,42 @@ fn reclaim() {
);
}

/// Tests that `generate_proof_input` from [`Transfer`] and [`TransferPost`] gives the same [`ProofInput`].
#[test]
fn generate_proof_input_is_compatibile() {
let mut rng = OsRng;
assert!(
Mint::sample_and_check_generate_proof_input_compatibility(
&(),
&rng.gen(),
&mut UtxoAccumulator::new(rng.gen()),
&mut rng
)
.expect("For a random Mint, `generate_proof_input` from `Transfer` and `ProofInput` should give the same `ProofInput`."),
"For a random Mint, `generate_proof_input` from `Transfer` and `TransferPost` should have given the same `ProofInput`."
);
assert!(
PrivateTransfer::sample_and_check_generate_proof_input_compatibility(
&(),
&rng.gen(),
&mut UtxoAccumulator::new(rng.gen()),
&mut rng
)
.expect("For a random PrivateTransfer, `generate_proof_input` from `Transfer` and `ProofInput` should give the same `ProofInput`."),
"For a random PrivateTransfer, `generate_proof_input` from `Transfer` and `TransferPost` should have given the same `ProofInput`."
);
assert!(
Reclaim::sample_and_check_generate_proof_input_compatibility(
&(),
&rng.gen(),
&mut UtxoAccumulator::new(rng.gen()),
&mut rng
)
.expect("For a random Reclaim, `generate_proof_input` from `Transfer` and `ProofInput` should give the same `ProofInput`."),
"For a random Reclaim, `generate_proof_input` from `Transfer` and `TransferPost` should have given the same `ProofInput`."
);
}

/// Asserts that `proof` can be SCALE encoded and decoded with at least [`Vec`], [`Cursor`], and
/// [`File`](std::fs::File).
#[inline]
Expand Down