Merge pull request #258 from therealyingtong/zip212-esk-plaintext-impl
ZIP212 implementation
This commit is contained in:
commit
81c3b54b24
|
@ -1,5 +1,6 @@
|
|||
use pairing::bls12_381::Bls12;
|
||||
use zcash_primitives::{
|
||||
consensus,
|
||||
note_encryption::{try_sapling_note_decryption, try_sapling_output_recovery, Memo},
|
||||
primitives::{Note, PaymentAddress},
|
||||
transaction::Transaction,
|
||||
|
@ -30,7 +31,8 @@ pub struct DecryptedOutput {
|
|||
|
||||
/// Scans a [`Transaction`] for any information that can be decrypted by the set of
|
||||
/// [`ExtendedFullViewingKey`]s.
|
||||
pub fn decrypt_transaction(
|
||||
pub fn decrypt_transaction<P: consensus::Parameters>(
|
||||
height: u32,
|
||||
tx: &Transaction,
|
||||
extfvks: &[ExtendedFullViewingKey],
|
||||
) -> Vec<DecryptedOutput> {
|
||||
|
@ -49,21 +51,27 @@ pub fn decrypt_transaction(
|
|||
};
|
||||
|
||||
for (account, (ivk, ovk)) in vks.iter().enumerate() {
|
||||
let ((note, to, memo), outgoing) =
|
||||
match try_sapling_note_decryption(ivk, &epk, &output.cmu, &output.enc_ciphertext) {
|
||||
Some(ret) => (ret, false),
|
||||
None => match try_sapling_output_recovery(
|
||||
ovk,
|
||||
&output.cv,
|
||||
&output.cmu,
|
||||
&epk,
|
||||
&output.enc_ciphertext,
|
||||
&output.out_ciphertext,
|
||||
) {
|
||||
Some(ret) => (ret, true),
|
||||
None => continue,
|
||||
},
|
||||
};
|
||||
let ((note, to, memo), outgoing) = match try_sapling_note_decryption::<P>(
|
||||
height,
|
||||
ivk,
|
||||
&epk,
|
||||
&output.cmu,
|
||||
&output.enc_ciphertext,
|
||||
) {
|
||||
Some(ret) => (ret, false),
|
||||
None => match try_sapling_output_recovery::<P>(
|
||||
height,
|
||||
ovk,
|
||||
&output.cv,
|
||||
&output.cmu,
|
||||
&epk,
|
||||
&output.enc_ciphertext,
|
||||
&output.out_ciphertext,
|
||||
) {
|
||||
Some(ret) => (ret, true),
|
||||
None => continue,
|
||||
},
|
||||
};
|
||||
decrypted.push(DecryptedOutput {
|
||||
index,
|
||||
note,
|
||||
|
|
|
@ -4,6 +4,7 @@ use ff::PrimeField;
|
|||
use std::collections::HashSet;
|
||||
use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||
use zcash_primitives::{
|
||||
consensus,
|
||||
jubjub::fs::Fs,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
note_encryption::try_sapling_compact_note_decryption,
|
||||
|
@ -22,7 +23,8 @@ use crate::wallet::{WalletShieldedOutput, WalletShieldedSpend, WalletTx};
|
|||
///
|
||||
/// The given [`CommitmentTree`] and existing [`IncrementalWitness`]es are incremented
|
||||
/// with this output's commitment.
|
||||
fn scan_output(
|
||||
fn scan_output<P: consensus::Parameters>(
|
||||
height: u32,
|
||||
(index, output): (usize, CompactOutput),
|
||||
ivks: &[Fs],
|
||||
spent_from_accounts: &HashSet<usize>,
|
||||
|
@ -49,10 +51,11 @@ fn scan_output(
|
|||
tree.append(node).unwrap();
|
||||
|
||||
for (account, ivk) in ivks.iter().enumerate() {
|
||||
let (note, to) = match try_sapling_compact_note_decryption(ivk, &epk, &cmu, &ct) {
|
||||
Some(ret) => ret,
|
||||
None => continue,
|
||||
};
|
||||
let (note, to) =
|
||||
match try_sapling_compact_note_decryption::<P>(height, ivk, &epk, &cmu, &ct) {
|
||||
Some(ret) => ret,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
// A note is marked as "change" if the account that received it
|
||||
// also spent notes in the same transaction. This will catch,
|
||||
|
@ -83,7 +86,7 @@ fn scan_output(
|
|||
///
|
||||
/// The given [`CommitmentTree`] and existing [`IncrementalWitness`]es are
|
||||
/// incremented appropriately.
|
||||
pub fn scan_block(
|
||||
pub fn scan_block<P: consensus::Parameters>(
|
||||
block: CompactBlock,
|
||||
extfvks: &[ExtendedFullViewingKey],
|
||||
nullifiers: &[(&[u8], usize)],
|
||||
|
@ -150,7 +153,8 @@ pub fn scan_block(
|
|||
.map(|output| &mut output.witness)
|
||||
.collect();
|
||||
|
||||
if let Some(output) = scan_output(
|
||||
if let Some(output) = scan_output::<P>(
|
||||
block.height as u32,
|
||||
to_scan,
|
||||
&ivks,
|
||||
&spent_from_accounts,
|
||||
|
@ -187,11 +191,13 @@ mod tests {
|
|||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use rand_core::{OsRng, RngCore};
|
||||
use zcash_primitives::{
|
||||
consensus::TestNetwork,
|
||||
jubjub::{fs::Fs, FixedGenerators, JubjubParams, ToUniform},
|
||||
merkle_tree::CommitmentTree,
|
||||
note_encryption::{Memo, SaplingNoteEncryption},
|
||||
primitives::Note,
|
||||
transaction::components::Amount,
|
||||
util::generate_random_rseed,
|
||||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
||||
JUBJUB,
|
||||
};
|
||||
|
@ -249,11 +255,12 @@ mod tests {
|
|||
|
||||
// Create a fake Note for the account
|
||||
let mut rng = OsRng;
|
||||
let rseed = generate_random_rseed::<TestNetwork, OsRng>(height as u32, &mut rng);
|
||||
let note = Note {
|
||||
g_d: to.diversifier().g_d::<Bls12>(&JUBJUB).unwrap(),
|
||||
pk_d: to.pk_d().clone(),
|
||||
value: value.into(),
|
||||
r: Fs::random(&mut rng),
|
||||
rseed,
|
||||
};
|
||||
let encryptor = SaplingNoteEncryption::new(
|
||||
extfvk.fvk.ovk,
|
||||
|
@ -318,7 +325,7 @@ mod tests {
|
|||
assert_eq!(cb.vtx.len(), 2);
|
||||
|
||||
let mut tree = CommitmentTree::new();
|
||||
let txs = scan_block(cb, &[extfvk], &[], &mut tree, &mut []);
|
||||
let txs = scan_block::<TestNetwork>(cb, &[extfvk], &[], &mut tree, &mut []);
|
||||
assert_eq!(txs.len(), 1);
|
||||
|
||||
let tx = &txs[0];
|
||||
|
@ -350,7 +357,7 @@ mod tests {
|
|||
assert_eq!(cb.vtx.len(), 3);
|
||||
|
||||
let mut tree = CommitmentTree::new();
|
||||
let txs = scan_block(cb, &[extfvk], &[], &mut tree, &mut []);
|
||||
let txs = scan_block::<TestNetwork>(cb, &[extfvk], &[], &mut tree, &mut []);
|
||||
assert_eq!(txs.len(), 1);
|
||||
|
||||
let tx = &txs[0];
|
||||
|
@ -378,7 +385,7 @@ mod tests {
|
|||
assert_eq!(cb.vtx.len(), 2);
|
||||
|
||||
let mut tree = CommitmentTree::new();
|
||||
let txs = scan_block(cb, &[], &[(&nf, account)], &mut tree, &mut []);
|
||||
let txs = scan_block::<TestNetwork>(cb, &[], &[(&nf, account)], &mut tree, &mut []);
|
||||
assert_eq!(txs.len(), 1);
|
||||
|
||||
let tx = &txs[0];
|
||||
|
|
|
@ -33,12 +33,17 @@ use zcash_primitives::zip32::ExtendedFullViewingKey;
|
|||
use zcash_client_backend::constants::mainnet::{
|
||||
HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, HRP_SAPLING_PAYMENT_ADDRESS,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "mainnet"))]
|
||||
use zcash_client_backend::constants::testnet::{
|
||||
HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, HRP_SAPLING_PAYMENT_ADDRESS,
|
||||
};
|
||||
|
||||
#[cfg(feature = "mainnet")]
|
||||
pub use zcash_primitives::consensus::MainNetwork as Network;
|
||||
|
||||
#[cfg(not(feature = "mainnet"))]
|
||||
pub use zcash_primitives::consensus::TestNetwork as Network;
|
||||
|
||||
pub mod address;
|
||||
pub mod chain;
|
||||
pub mod error;
|
||||
|
@ -89,7 +94,8 @@ fn get_target_and_anchor_heights(data: &Connection) -> Result<(u32, u32), error:
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ff::{Field, PrimeField};
|
||||
use crate::Network;
|
||||
use ff::PrimeField;
|
||||
use pairing::bls12_381::Bls12;
|
||||
use protobuf::Message;
|
||||
use rand_core::{OsRng, RngCore};
|
||||
|
@ -100,10 +106,10 @@ mod tests {
|
|||
};
|
||||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
jubjub::fs::Fs,
|
||||
note_encryption::{Memo, SaplingNoteEncryption},
|
||||
primitives::{Note, PaymentAddress},
|
||||
transaction::components::Amount,
|
||||
util::generate_random_rseed,
|
||||
zip32::ExtendedFullViewingKey,
|
||||
JUBJUB,
|
||||
};
|
||||
|
@ -120,11 +126,12 @@ mod tests {
|
|||
|
||||
// Create a fake Note for the account
|
||||
let mut rng = OsRng;
|
||||
let rseed = generate_random_rseed::<Network, OsRng>(height as u32, &mut rng);
|
||||
let note = Note {
|
||||
g_d: to.diversifier().g_d::<Bls12>(&JUBJUB).unwrap(),
|
||||
pk_d: to.pk_d().clone(),
|
||||
value: value.into(),
|
||||
r: Fs::random(&mut rng),
|
||||
rseed,
|
||||
};
|
||||
let encryptor = SaplingNoteEncryption::new(
|
||||
extfvk.fvk.ovk,
|
||||
|
@ -168,6 +175,7 @@ mod tests {
|
|||
value: Amount,
|
||||
) -> CompactBlock {
|
||||
let mut rng = OsRng;
|
||||
let rseed = generate_random_rseed::<Network, OsRng>(height as u32, &mut rng);
|
||||
|
||||
// Create a fake CompactBlock containing the note
|
||||
let mut cspend = CompactSpend::new();
|
||||
|
@ -184,7 +192,7 @@ mod tests {
|
|||
g_d: to.diversifier().g_d::<Bls12>(&JUBJUB).unwrap(),
|
||||
pk_d: to.pk_d().clone(),
|
||||
value: value.into(),
|
||||
r: Fs::random(&mut rng),
|
||||
rseed,
|
||||
};
|
||||
let encryptor = SaplingNoteEncryption::new(
|
||||
extfvk.fvk.ovk,
|
||||
|
@ -208,11 +216,12 @@ mod tests {
|
|||
// Create a fake Note for the change
|
||||
ctx.outputs.push({
|
||||
let change_addr = extfvk.default_address().unwrap().1;
|
||||
let rseed = generate_random_rseed::<Network, OsRng>(height as u32, &mut rng);
|
||||
let note = Note {
|
||||
g_d: change_addr.diversifier().g_d::<Bls12>(&JUBJUB).unwrap(),
|
||||
pk_d: change_addr.pk_d().clone(),
|
||||
value: (in_value - value).into(),
|
||||
r: Fs::random(&mut rng),
|
||||
rseed,
|
||||
};
|
||||
let encryptor = SaplingNoteEncryption::new(
|
||||
extfvk.fvk.ovk,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use ff::PrimeField;
|
||||
use protobuf::parse_from_bytes;
|
||||
use rusqlite::{types::ToSql, Connection, NO_PARAMS};
|
||||
use rusqlite::{types::ToSql, Connection, OptionalExtension, NO_PARAMS};
|
||||
use std::path::Path;
|
||||
use zcash_client_backend::{
|
||||
decrypt_transaction, encoding::decode_extended_full_viewing_key,
|
||||
|
@ -18,7 +18,7 @@ use zcash_primitives::{
|
|||
use crate::{
|
||||
address::RecipientAddress,
|
||||
error::{Error, ErrorKind},
|
||||
HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, SAPLING_ACTIVATION_HEIGHT,
|
||||
Network, HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, SAPLING_ACTIVATION_HEIGHT,
|
||||
};
|
||||
|
||||
struct CompactBlockRow {
|
||||
|
@ -187,7 +187,7 @@ pub fn scan_cached_blocks<P: AsRef<Path>, Q: AsRef<Path>>(
|
|||
let txs = {
|
||||
let nf_refs: Vec<_> = nullifiers.iter().map(|(nf, acc)| (&nf[..], *acc)).collect();
|
||||
let mut witness_refs: Vec<_> = witnesses.iter_mut().map(|w| &mut w.witness).collect();
|
||||
scan_block(
|
||||
scan_block::<Network>(
|
||||
block,
|
||||
&extfvks[..],
|
||||
&nf_refs,
|
||||
|
@ -269,7 +269,7 @@ pub fn scan_cached_blocks<P: AsRef<Path>, Q: AsRef<Path>>(
|
|||
.collect();
|
||||
|
||||
for output in tx.shielded_outputs {
|
||||
let rcm = output.note.r.to_repr();
|
||||
let rcm = output.note.rcm().to_repr();
|
||||
let nf = output.note.nf(
|
||||
&extfvks[output.account].fvk.vk,
|
||||
output.witness.position() as u64,
|
||||
|
@ -372,7 +372,23 @@ pub fn decrypt_and_store_transaction<P: AsRef<Path>>(
|
|||
.collect::<Result<Result<Option<_>, _>, _>>()??
|
||||
.ok_or(Error(ErrorKind::IncorrectHRPExtFVK))?;
|
||||
|
||||
let outputs = decrypt_transaction(tx, &extfvks);
|
||||
// Height is block height for mined transactions, and the "mempool height" (chain height + 1) for mempool transactions.
|
||||
let mut stmt_select_block = data.prepare("SELECT block FROM transactions WHERE txid = ?")?;
|
||||
let height = match stmt_select_block
|
||||
.query_row(&[tx.txid().0.to_vec()], |row| row.get(0))
|
||||
.optional()?
|
||||
{
|
||||
Some(height) => height,
|
||||
None => data
|
||||
.query_row("SELECT MAX(height) FROM blocks", NO_PARAMS, |row| {
|
||||
row.get(0)
|
||||
})
|
||||
.optional()?
|
||||
.map(|last_height: u32| last_height + 1)
|
||||
.unwrap_or(SAPLING_ACTIVATION_HEIGHT as u32),
|
||||
};
|
||||
|
||||
let outputs = decrypt_transaction::<Network>(height as u32, tx, &extfvks);
|
||||
|
||||
if outputs.is_empty() {
|
||||
// Nothing to see here
|
||||
|
@ -457,7 +473,7 @@ pub fn decrypt_and_store_transaction<P: AsRef<Path>>(
|
|||
])?;
|
||||
}
|
||||
} else {
|
||||
let rcm = output.note.r.to_repr();
|
||||
let rcm = output.note.rcm().to_repr();
|
||||
|
||||
// Try updating an existing received note.
|
||||
if stmt_update_received_note.execute(&[
|
||||
|
|
|
@ -9,11 +9,12 @@ use std::path::Path;
|
|||
use zcash_client_backend::encoding::encode_extended_full_viewing_key;
|
||||
use zcash_primitives::{
|
||||
consensus,
|
||||
consensus::{NetworkUpgrade, Parameters},
|
||||
jubjub::fs::{Fs, FsRepr},
|
||||
keys::OutgoingViewingKey,
|
||||
merkle_tree::{IncrementalWitness, MerklePath},
|
||||
note_encryption::Memo,
|
||||
primitives::{Diversifier, Note},
|
||||
primitives::{Diversifier, Note, Rseed},
|
||||
prover::TxProver,
|
||||
sapling::Node,
|
||||
transaction::{
|
||||
|
@ -27,7 +28,7 @@ use zcash_primitives::{
|
|||
use crate::{
|
||||
address::RecipientAddress,
|
||||
error::{Error, ErrorKind},
|
||||
get_target_and_anchor_heights, HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
|
||||
get_target_and_anchor_heights, Network, HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
|
||||
};
|
||||
|
||||
/// Describes a policy for which outgoing viewing key should be able to decrypt
|
||||
|
@ -234,14 +235,22 @@ pub fn create_to_address<P: AsRef<Path>>(
|
|||
|
||||
let note_value: i64 = row.get(1)?;
|
||||
|
||||
let rcm = {
|
||||
let rseed = {
|
||||
let d: Vec<_> = row.get(2)?;
|
||||
let tmp = FsRepr(
|
||||
d[..]
|
||||
.try_into()
|
||||
.map_err(|_| Error(ErrorKind::InvalidNote))?,
|
||||
);
|
||||
Fs::from_repr(tmp).ok_or(Error(ErrorKind::InvalidNote))?
|
||||
|
||||
if Network::is_nu_active(NetworkUpgrade::Canopy, height) {
|
||||
let mut r = [0u8; 32];
|
||||
r.copy_from_slice(&d[..]);
|
||||
Rseed::AfterZip212(r)
|
||||
} else {
|
||||
let tmp = FsRepr(
|
||||
d[..]
|
||||
.try_into()
|
||||
.map_err(|_| Error(ErrorKind::InvalidNote))?,
|
||||
);
|
||||
let r = Fs::from_repr(tmp).ok_or(Error(ErrorKind::InvalidNote))?;
|
||||
Rseed::BeforeZip212(r)
|
||||
}
|
||||
};
|
||||
|
||||
let from = extfvk
|
||||
|
@ -249,7 +258,7 @@ pub fn create_to_address<P: AsRef<Path>>(
|
|||
.vk
|
||||
.to_payment_address(diversifier, &JUBJUB)
|
||||
.unwrap();
|
||||
let note = from.create_note(note_value as u64, rcm, &JUBJUB).unwrap();
|
||||
let note = from.create_note(note_value as u64, rseed, &JUBJUB).unwrap();
|
||||
|
||||
let merkle_path = {
|
||||
let d: Vec<_> = row.get(3)?;
|
||||
|
@ -279,7 +288,7 @@ pub fn create_to_address<P: AsRef<Path>>(
|
|||
}
|
||||
|
||||
// Create the transaction
|
||||
let mut builder = Builder::new(height);
|
||||
let mut builder = Builder::<Network, OsRng>::new(height);
|
||||
for selected in notes {
|
||||
builder.add_sapling_spend(
|
||||
extsk.clone(),
|
||||
|
@ -391,7 +400,7 @@ mod tests {
|
|||
query::{get_balance, get_verified_balance},
|
||||
scan::scan_cached_blocks,
|
||||
tests::{fake_compact_block, insert_into_cache},
|
||||
SAPLING_ACTIVATION_HEIGHT,
|
||||
Network, SAPLING_ACTIVATION_HEIGHT,
|
||||
};
|
||||
|
||||
fn test_prover() -> impl TxProver {
|
||||
|
@ -813,7 +822,8 @@ mod tests {
|
|||
.unwrap();
|
||||
let output = &tx.shielded_outputs[output_index as usize];
|
||||
|
||||
try_sapling_output_recovery(
|
||||
try_sapling_output_recovery::<Network>(
|
||||
SAPLING_ACTIVATION_HEIGHT as u32,
|
||||
&extfvk.fvk.ovk,
|
||||
&output.cv,
|
||||
&output.cmu,
|
||||
|
|
|
@ -111,6 +111,8 @@ const UPGRADES_IN_ORDER: &[NetworkUpgrade] = &[
|
|||
NetworkUpgrade::Canopy,
|
||||
];
|
||||
|
||||
pub const ZIP212_GRACE_PERIOD: u32 = 32256;
|
||||
|
||||
/// A globally-unique identifier for a set of consensus rules within the Zcash chain.
|
||||
///
|
||||
/// Each branch ID in this enum corresponds to one of the epochs between a pair of Zcash
|
||||
|
|
|
@ -24,7 +24,7 @@ pub mod redjubjub;
|
|||
pub mod sapling;
|
||||
pub mod serialize;
|
||||
pub mod transaction;
|
||||
mod util;
|
||||
pub mod util;
|
||||
pub mod zip32;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,10 +10,14 @@ use crate::pedersen_hash::{pedersen_hash, Personalization};
|
|||
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
|
||||
use crate::jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams, PrimeOrder};
|
||||
use crate::jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams, PrimeOrder, ToUniform};
|
||||
|
||||
use crate::keys::prf_expand;
|
||||
|
||||
use blake2s_simd::Params as Blake2sParams;
|
||||
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ValueCommitment<E: JubjubEngine> {
|
||||
pub value: u64,
|
||||
|
@ -207,18 +211,29 @@ impl<E: JubjubEngine> PaymentAddress<E> {
|
|||
pub fn create_note(
|
||||
&self,
|
||||
value: u64,
|
||||
randomness: E::Fs,
|
||||
randomness: Rseed<E::Fs>,
|
||||
params: &E::Params,
|
||||
) -> Option<Note<E>> {
|
||||
self.g_d(params).map(|g_d| Note {
|
||||
value,
|
||||
r: randomness,
|
||||
rseed: randomness,
|
||||
g_d,
|
||||
pk_d: self.pk_d.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Enum for note randomness before and after [ZIP 212](https://zips.z.cash/zip-0212).
|
||||
///
|
||||
/// Before ZIP 212, the note commitment trapdoor `rcm` must be a scalar value.
|
||||
/// After ZIP 212, the note randomness `rseed` is a 32-byte sequence, used to derive
|
||||
/// both the note commitment trapdoor `rcm` and the ephemeral private key `esk`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum Rseed<Fs> {
|
||||
BeforeZip212(Fs),
|
||||
AfterZip212([u8; 32]),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Note<E: JubjubEngine> {
|
||||
/// The value of the note
|
||||
|
@ -227,8 +242,8 @@ pub struct Note<E: JubjubEngine> {
|
|||
pub g_d: edwards::Point<E, PrimeOrder>,
|
||||
/// The public key of the address, g_d^ivk
|
||||
pub pk_d: edwards::Point<E, PrimeOrder>,
|
||||
/// The commitment randomness
|
||||
pub r: E::Fs,
|
||||
/// rseed
|
||||
pub rseed: Rseed<E::Fs>,
|
||||
}
|
||||
|
||||
impl<E: JubjubEngine> PartialEq for Note<E> {
|
||||
|
@ -236,7 +251,7 @@ impl<E: JubjubEngine> PartialEq for Note<E> {
|
|||
self.value == other.value
|
||||
&& self.g_d == other.g_d
|
||||
&& self.pk_d == other.pk_d
|
||||
&& self.r == other.r
|
||||
&& self.rcm() == other.rcm()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,7 +295,7 @@ impl<E: JubjubEngine> Note<E> {
|
|||
// Compute final commitment
|
||||
params
|
||||
.generator(FixedGenerators::NoteCommitmentRandomness)
|
||||
.mul(self.r, params)
|
||||
.mul(self.rcm(), params)
|
||||
.add(&hash_of_contents, params)
|
||||
}
|
||||
|
||||
|
@ -313,4 +328,35 @@ impl<E: JubjubEngine> Note<E> {
|
|||
// commitment to the x-coordinate is an injective encoding.
|
||||
self.cm_full_point(params).to_xy().0
|
||||
}
|
||||
|
||||
pub fn rcm(&self) -> E::Fs {
|
||||
match self.rseed {
|
||||
Rseed::BeforeZip212(rcm) => rcm,
|
||||
Rseed::AfterZip212(rseed) => E::Fs::to_uniform(prf_expand(&rseed, &[0x04]).as_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_or_derive_esk<R: RngCore + CryptoRng>(&self, rng: &mut R) -> E::Fs {
|
||||
match self.derive_esk() {
|
||||
None => {
|
||||
// create random 64 byte buffer
|
||||
let mut buffer = [0u8; 64];
|
||||
&rng.fill_bytes(&mut buffer);
|
||||
|
||||
// reduce to uniform value
|
||||
E::Fs::to_uniform(&buffer[..])
|
||||
}
|
||||
Some(esk) => esk,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the derived `esk` if this note was created after ZIP 212 activated.
|
||||
pub fn derive_esk(&self) -> Option<E::Fs> {
|
||||
match self.rseed {
|
||||
Rseed::BeforeZip212(_) => None,
|
||||
Rseed::AfterZip212(rseed) => {
|
||||
Some(E::Fs::to_uniform(prf_expand(&rseed, &[0x05]).as_bytes()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::{
|
||||
jubjub::{edwards, fs::Fs, Unknown},
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey},
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed},
|
||||
};
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
|
||||
|
@ -31,7 +31,7 @@ pub trait TxProver {
|
|||
ctx: &mut Self::SaplingProvingContext,
|
||||
proof_generation_key: ProofGenerationKey<Bls12>,
|
||||
diversifier: Diversifier,
|
||||
rcm: Fs,
|
||||
rseed: Rseed<Fs>,
|
||||
ar: Fs,
|
||||
value: u64,
|
||||
anchor: Fr,
|
||||
|
@ -78,7 +78,7 @@ pub(crate) mod mock {
|
|||
|
||||
use crate::{
|
||||
jubjub::{edwards, fs::Fs, FixedGenerators, Unknown},
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey, ValueCommitment},
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed, ValueCommitment},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -104,7 +104,7 @@ pub(crate) mod mock {
|
|||
_ctx: &mut Self::SaplingProvingContext,
|
||||
proof_generation_key: ProofGenerationKey<Bls12>,
|
||||
_diversifier: Diversifier,
|
||||
_rcm: Fs,
|
||||
_rcm: Rseed<Fs>,
|
||||
ar: Fs,
|
||||
value: u64,
|
||||
_anchor: Fr,
|
||||
|
|
|
@ -10,13 +10,14 @@ use pairing::bls12_381::{Bls12, Fr};
|
|||
use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore};
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::{
|
||||
consensus,
|
||||
keys::OutgoingViewingKey,
|
||||
legacy::TransparentAddress,
|
||||
merkle_tree::MerklePath,
|
||||
note_encryption::{generate_esk, Memo, SaplingNoteEncryption},
|
||||
note_encryption::{Memo, SaplingNoteEncryption},
|
||||
prover::TxProver,
|
||||
redjubjub::PrivateKey,
|
||||
sapling::{spend_sig, Node},
|
||||
|
@ -24,6 +25,7 @@ use crate::{
|
|||
components::{amount::DEFAULT_FEE, Amount, OutputDescription, SpendDescription, TxOut},
|
||||
signature_hash_data, Transaction, TransactionData, SIGHASH_ALL,
|
||||
},
|
||||
util::generate_random_rseed,
|
||||
JUBJUB,
|
||||
};
|
||||
|
||||
|
@ -86,7 +88,8 @@ pub struct SaplingOutput {
|
|||
}
|
||||
|
||||
impl SaplingOutput {
|
||||
pub fn new<R: RngCore + CryptoRng>(
|
||||
pub fn new<R: RngCore + CryptoRng, P: consensus::Parameters>(
|
||||
height: u32,
|
||||
rng: &mut R,
|
||||
ovk: OutgoingViewingKey,
|
||||
to: PaymentAddress<Bls12>,
|
||||
|
@ -101,13 +104,13 @@ impl SaplingOutput {
|
|||
return Err(Error::InvalidAmount);
|
||||
}
|
||||
|
||||
let rcm = Fs::random(rng);
|
||||
let rseed = generate_random_rseed::<P, R>(height, rng);
|
||||
|
||||
let note = Note {
|
||||
g_d,
|
||||
pk_d: to.pk_d().clone(),
|
||||
value: value.into(),
|
||||
r: rcm,
|
||||
rseed,
|
||||
};
|
||||
|
||||
Ok(SaplingOutput {
|
||||
|
@ -136,7 +139,7 @@ impl SaplingOutput {
|
|||
ctx,
|
||||
encryptor.esk().clone(),
|
||||
self.to,
|
||||
self.note.r,
|
||||
self.note.rcm(),
|
||||
self.note.value,
|
||||
);
|
||||
|
||||
|
@ -302,8 +305,9 @@ impl TransactionMetadata {
|
|||
}
|
||||
|
||||
/// Generates a [`Transaction`] from its inputs and outputs.
|
||||
pub struct Builder<R: RngCore + CryptoRng> {
|
||||
pub struct Builder<P: consensus::Parameters, R: RngCore + CryptoRng> {
|
||||
rng: R,
|
||||
height: u32,
|
||||
mtx: TransactionData,
|
||||
fee: Amount,
|
||||
anchor: Option<Fr>,
|
||||
|
@ -311,9 +315,10 @@ pub struct Builder<R: RngCore + CryptoRng> {
|
|||
outputs: Vec<SaplingOutput>,
|
||||
transparent_inputs: TransparentInputs,
|
||||
change_address: Option<(OutgoingViewingKey, PaymentAddress<Bls12>)>,
|
||||
phantom: PhantomData<P>,
|
||||
}
|
||||
|
||||
impl Builder<OsRng> {
|
||||
impl<P: consensus::Parameters> Builder<P, OsRng> {
|
||||
/// Creates a new `Builder` targeted for inclusion in the block with the given height,
|
||||
/// using default values for general transaction fields and the default OS random.
|
||||
///
|
||||
|
@ -328,7 +333,7 @@ impl Builder<OsRng> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<R: RngCore + CryptoRng> Builder<R> {
|
||||
impl<P: consensus::Parameters, R: RngCore + CryptoRng> Builder<P, R> {
|
||||
/// Creates a new `Builder` targeted for inclusion in the block with the given height
|
||||
/// and randomness source, using default values for general transaction fields.
|
||||
///
|
||||
|
@ -338,12 +343,13 @@ impl<R: RngCore + CryptoRng> Builder<R> {
|
|||
/// expiry delta (20 blocks).
|
||||
///
|
||||
/// The fee will be set to the default fee (0.0001 ZEC).
|
||||
pub fn new_with_rng(height: u32, rng: R) -> Builder<R> {
|
||||
pub fn new_with_rng(height: u32, rng: R) -> Builder<P, R> {
|
||||
let mut mtx = TransactionData::new();
|
||||
mtx.expiry_height = height + DEFAULT_TX_EXPIRY_DELTA;
|
||||
|
||||
Builder {
|
||||
rng,
|
||||
height,
|
||||
mtx,
|
||||
fee: DEFAULT_FEE,
|
||||
anchor: None,
|
||||
|
@ -351,6 +357,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
|
|||
outputs: vec![],
|
||||
transparent_inputs: TransparentInputs::default(),
|
||||
change_address: None,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,7 +406,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
|
|||
value: Amount,
|
||||
memo: Option<Memo>,
|
||||
) -> Result<(), Error> {
|
||||
let output = SaplingOutput::new(&mut self.rng, ovk, to, value, memo)?;
|
||||
let output = SaplingOutput::new::<R, P>(self.height, &mut self.rng, ovk, to, value, memo)?;
|
||||
|
||||
self.mtx.value_balance -= value;
|
||||
|
||||
|
@ -555,7 +562,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
|
|||
&mut ctx,
|
||||
proof_generation_key,
|
||||
spend.diversifier,
|
||||
spend.note.r,
|
||||
spend.note.rseed,
|
||||
spend.alpha,
|
||||
spend.note.value,
|
||||
anchor,
|
||||
|
@ -610,22 +617,29 @@ impl<R: RngCore + CryptoRng> Builder<R> {
|
|||
}
|
||||
};
|
||||
|
||||
let rseed = generate_random_rseed::<P, R>(self.height, &mut self.rng);
|
||||
|
||||
(
|
||||
payment_address,
|
||||
Note {
|
||||
g_d,
|
||||
pk_d,
|
||||
r: Fs::random(&mut self.rng),
|
||||
rseed,
|
||||
value: 0,
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
let esk = generate_esk(&mut self.rng);
|
||||
let esk = dummy_note.generate_or_derive_esk(&mut self.rng);
|
||||
let epk = dummy_note.g_d.mul(esk, &JUBJUB);
|
||||
|
||||
let (zkproof, cv) =
|
||||
prover.output_proof(&mut ctx, esk, dummy_to, dummy_note.r, dummy_note.value);
|
||||
let (zkproof, cv) = prover.output_proof(
|
||||
&mut ctx,
|
||||
esk,
|
||||
dummy_to,
|
||||
dummy_note.rcm(),
|
||||
dummy_note.value,
|
||||
);
|
||||
|
||||
let cmu = dummy_note.cm(&JUBJUB);
|
||||
|
||||
|
@ -696,14 +710,17 @@ impl<R: RngCore + CryptoRng> Builder<R> {
|
|||
mod tests {
|
||||
use ff::{Field, PrimeField};
|
||||
use rand_core::OsRng;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::jubjub::fs::Fs;
|
||||
|
||||
use super::{Builder, Error};
|
||||
use crate::{
|
||||
consensus,
|
||||
consensus::TestNetwork,
|
||||
legacy::TransparentAddress,
|
||||
merkle_tree::{CommitmentTree, IncrementalWitness},
|
||||
primitives::Rseed,
|
||||
prover::mock::MockTxProver,
|
||||
sapling::Node,
|
||||
transaction::components::Amount,
|
||||
|
@ -718,7 +735,7 @@ mod tests {
|
|||
let ovk = extfvk.fvk.ovk;
|
||||
let to = extfvk.default_address().unwrap().1;
|
||||
|
||||
let mut builder = Builder::new(0);
|
||||
let mut builder = Builder::<TestNetwork, OsRng>::new(0);
|
||||
assert_eq!(
|
||||
builder.add_sapling_output(ovk, to, Amount::from_i64(-1).unwrap(), None),
|
||||
Err(Error::InvalidAmount)
|
||||
|
@ -727,14 +744,19 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn binding_sig_absent_if_no_shielded_spend_or_output() {
|
||||
use crate::consensus::{NetworkUpgrade, Parameters};
|
||||
use crate::transaction::{
|
||||
builder::{self, TransparentInputs},
|
||||
TransactionData,
|
||||
};
|
||||
|
||||
let sapling_activation_height =
|
||||
TestNetwork::activation_height(NetworkUpgrade::Sapling).unwrap();
|
||||
|
||||
// Create a builder with 0 fee, so we can construct t outputs
|
||||
let mut builder = builder::Builder {
|
||||
let mut builder = builder::Builder::<TestNetwork, OsRng> {
|
||||
rng: OsRng,
|
||||
height: sapling_activation_height,
|
||||
mtx: TransactionData::new(),
|
||||
fee: Amount::zero(),
|
||||
anchor: None,
|
||||
|
@ -742,6 +764,7 @@ mod tests {
|
|||
outputs: vec![],
|
||||
transparent_inputs: TransparentInputs::default(),
|
||||
change_address: None,
|
||||
phantom: PhantomData,
|
||||
};
|
||||
|
||||
// Create a tx with only t output. No binding_sig should be present
|
||||
|
@ -765,14 +788,14 @@ mod tests {
|
|||
let mut rng = OsRng;
|
||||
|
||||
let note1 = to
|
||||
.create_note(50000, Fs::random(&mut rng), &JUBJUB)
|
||||
.create_note(50000, Rseed::BeforeZip212(Fs::random(&mut rng)), &JUBJUB)
|
||||
.unwrap();
|
||||
let cm1 = Node::new(note1.cm(&JUBJUB).to_repr());
|
||||
let mut tree = CommitmentTree::new();
|
||||
tree.append(cm1).unwrap();
|
||||
let witness1 = IncrementalWitness::from_tree(&tree);
|
||||
|
||||
let mut builder = Builder::new(0);
|
||||
let mut builder = Builder::<TestNetwork, OsRng>::new(0);
|
||||
|
||||
// Create a tx with a sapling spend. binding_sig should be present
|
||||
builder
|
||||
|
@ -798,7 +821,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn fails_on_negative_transparent_output() {
|
||||
let mut builder = Builder::new(0);
|
||||
let mut builder = Builder::<TestNetwork, OsRng>::new(0);
|
||||
assert_eq!(
|
||||
builder.add_transparent_output(
|
||||
&TransparentAddress::PublicKey([0; 20]),
|
||||
|
@ -818,7 +841,7 @@ mod tests {
|
|||
// Fails with no inputs or outputs
|
||||
// 0.0001 t-ZEC fee
|
||||
{
|
||||
let builder = Builder::new(0);
|
||||
let builder = Builder::<TestNetwork, OsRng>::new(0);
|
||||
assert_eq!(
|
||||
builder.build(consensus::BranchId::Sapling, &MockTxProver),
|
||||
Err(Error::ChangeIsNegative(Amount::from_i64(-10000).unwrap()))
|
||||
|
@ -832,7 +855,7 @@ mod tests {
|
|||
// Fail if there is only a Sapling output
|
||||
// 0.0005 z-ZEC out, 0.0001 t-ZEC fee
|
||||
{
|
||||
let mut builder = Builder::new(0);
|
||||
let mut builder = Builder::<TestNetwork, OsRng>::new(0);
|
||||
builder
|
||||
.add_sapling_output(
|
||||
ovk.clone(),
|
||||
|
@ -850,7 +873,7 @@ mod tests {
|
|||
// Fail if there is only a transparent output
|
||||
// 0.0005 t-ZEC out, 0.0001 t-ZEC fee
|
||||
{
|
||||
let mut builder = Builder::new(0);
|
||||
let mut builder = Builder::<TestNetwork, OsRng>::new(0);
|
||||
builder
|
||||
.add_transparent_output(
|
||||
&TransparentAddress::PublicKey([0; 20]),
|
||||
|
@ -864,7 +887,7 @@ mod tests {
|
|||
}
|
||||
|
||||
let note1 = to
|
||||
.create_note(59999, Fs::random(&mut rng), &JUBJUB)
|
||||
.create_note(59999, Rseed::BeforeZip212(Fs::random(&mut rng)), &JUBJUB)
|
||||
.unwrap();
|
||||
let cm1 = Node::new(note1.cm(&JUBJUB).to_repr());
|
||||
let mut tree = CommitmentTree::new();
|
||||
|
@ -874,7 +897,7 @@ mod tests {
|
|||
// Fail if there is insufficient input
|
||||
// 0.0003 z-ZEC out, 0.0002 t-ZEC out, 0.0001 t-ZEC fee, 0.00059999 z-ZEC in
|
||||
{
|
||||
let mut builder = Builder::new(0);
|
||||
let mut builder = Builder::<TestNetwork, OsRng>::new(0);
|
||||
builder
|
||||
.add_sapling_spend(
|
||||
extsk.clone(),
|
||||
|
@ -903,7 +926,9 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
let note2 = to.create_note(1, Fs::random(&mut rng), &JUBJUB).unwrap();
|
||||
let note2 = to
|
||||
.create_note(1, Rseed::BeforeZip212(Fs::random(&mut rng)), &JUBJUB)
|
||||
.unwrap();
|
||||
let cm2 = Node::new(note2.cm(&JUBJUB).to_repr());
|
||||
tree.append(cm2).unwrap();
|
||||
witness1.append(cm2).unwrap();
|
||||
|
@ -915,7 +940,7 @@ mod tests {
|
|||
// (Still fails because we are using a MockTxProver which doesn't correctly
|
||||
// compute bindingSig.)
|
||||
{
|
||||
let mut builder = Builder::new(0);
|
||||
let mut builder = Builder::<TestNetwork, OsRng>::new(0);
|
||||
builder
|
||||
.add_sapling_spend(
|
||||
extsk.clone(),
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
use blake2b_simd::Params;
|
||||
|
||||
use crate::jubjub::{JubjubEngine, ToUniform};
|
||||
use crate::{
|
||||
consensus,
|
||||
consensus::NetworkUpgrade,
|
||||
jubjub::{fs::Fs, JubjubEngine, ToUniform},
|
||||
primitives::Rseed,
|
||||
};
|
||||
use ff::Field;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
pub fn hash_to_scalar<E: JubjubEngine>(persona: &[u8], a: &[u8], b: &[u8]) -> E::Fs {
|
||||
let mut hasher = Params::new().hash_length(64).personal(persona).to_state();
|
||||
|
@ -9,3 +16,16 @@ pub fn hash_to_scalar<E: JubjubEngine>(persona: &[u8], a: &[u8], b: &[u8]) -> E:
|
|||
let ret = hasher.finalize();
|
||||
E::Fs::to_uniform(ret.as_ref())
|
||||
}
|
||||
|
||||
pub fn generate_random_rseed<P: consensus::Parameters, R: RngCore + CryptoRng>(
|
||||
height: u32,
|
||||
rng: &mut R,
|
||||
) -> Rseed<Fs> {
|
||||
if P::is_nu_active(NetworkUpgrade::Canopy, height) {
|
||||
let mut buffer = [0u8; 32];
|
||||
&rng.fill_bytes(&mut buffer);
|
||||
Rseed::AfterZip212(buffer)
|
||||
} else {
|
||||
Rseed::BeforeZip212(Fs::random(rng))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -544,7 +544,7 @@ fn test_input_circuit_with_bls12_381() {
|
|||
use zcash_primitives::{
|
||||
jubjub::{edwards, fs, JubjubBls12},
|
||||
pedersen_hash,
|
||||
primitives::{Diversifier, Note, ProofGenerationKey},
|
||||
primitives::{Diversifier, Note, ProofGenerationKey, Rseed},
|
||||
};
|
||||
|
||||
let params = &JubjubBls12::new();
|
||||
|
@ -598,7 +598,7 @@ fn test_input_circuit_with_bls12_381() {
|
|||
value: value_commitment.value,
|
||||
g_d: g_d.clone(),
|
||||
pk_d: payment_address.pk_d().clone(),
|
||||
r: commitment_randomness.clone(),
|
||||
rseed: Rseed::BeforeZip212(commitment_randomness.clone()),
|
||||
};
|
||||
|
||||
let mut position = 0u64;
|
||||
|
@ -694,7 +694,7 @@ fn test_input_circuit_with_bls12_381_external_test_vectors() {
|
|||
use zcash_primitives::{
|
||||
jubjub::{edwards, fs, JubjubBls12},
|
||||
pedersen_hash,
|
||||
primitives::{Diversifier, Note, ProofGenerationKey},
|
||||
primitives::{Diversifier, Note, ProofGenerationKey, Rseed},
|
||||
};
|
||||
|
||||
let params = &JubjubBls12::new();
|
||||
|
@ -782,7 +782,7 @@ fn test_input_circuit_with_bls12_381_external_test_vectors() {
|
|||
value: value_commitment.value,
|
||||
g_d: g_d.clone(),
|
||||
pk_d: payment_address.pk_d().clone(),
|
||||
r: commitment_randomness.clone(),
|
||||
rseed: Rseed::BeforeZip212(commitment_randomness.clone()),
|
||||
};
|
||||
|
||||
let mut position = 0u64;
|
||||
|
@ -877,7 +877,7 @@ fn test_output_circuit_with_bls12_381() {
|
|||
use rand_xorshift::XorShiftRng;
|
||||
use zcash_primitives::{
|
||||
jubjub::{edwards, fs, JubjubBls12},
|
||||
primitives::{Diversifier, ProofGenerationKey},
|
||||
primitives::{Diversifier, ProofGenerationKey, Rseed},
|
||||
};
|
||||
|
||||
let params = &JubjubBls12::new();
|
||||
|
@ -941,7 +941,11 @@ fn test_output_circuit_with_bls12_381() {
|
|||
);
|
||||
|
||||
let expected_cm = payment_address
|
||||
.create_note(value_commitment.value, commitment_randomness, params)
|
||||
.create_note(
|
||||
value_commitment.value,
|
||||
Rseed::BeforeZip212(commitment_randomness),
|
||||
params,
|
||||
)
|
||||
.expect("should be valid")
|
||||
.cm(params);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use bellman::groth16::{Parameters, PreparedVerifyingKey};
|
|||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use zcash_primitives::{
|
||||
jubjub::{edwards, fs::Fs, Unknown},
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey},
|
||||
primitives::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed},
|
||||
};
|
||||
use zcash_primitives::{
|
||||
merkle_tree::MerklePath,
|
||||
|
@ -132,7 +132,7 @@ impl TxProver for LocalTxProver {
|
|||
ctx: &mut Self::SaplingProvingContext,
|
||||
proof_generation_key: ProofGenerationKey<Bls12>,
|
||||
diversifier: Diversifier,
|
||||
rcm: Fs,
|
||||
rseed: Rseed<Fs>,
|
||||
ar: Fs,
|
||||
value: u64,
|
||||
anchor: Fr,
|
||||
|
@ -148,7 +148,7 @@ impl TxProver for LocalTxProver {
|
|||
let (proof, cv, rk) = ctx.spend_proof(
|
||||
proof_generation_key,
|
||||
diversifier,
|
||||
rcm,
|
||||
rseed,
|
||||
ar,
|
||||
value,
|
||||
anchor,
|
||||
|
|
|
@ -8,7 +8,7 @@ use rand_core::OsRng;
|
|||
use std::ops::{AddAssign, Neg};
|
||||
use zcash_primitives::{
|
||||
jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown},
|
||||
primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment},
|
||||
primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, Rseed, ValueCommitment},
|
||||
};
|
||||
use zcash_primitives::{
|
||||
merkle_tree::MerklePath,
|
||||
|
@ -43,7 +43,7 @@ impl SaplingProvingContext {
|
|||
&mut self,
|
||||
proof_generation_key: ProofGenerationKey<Bls12>,
|
||||
diversifier: Diversifier,
|
||||
rcm: Fs,
|
||||
rseed: Rseed<Fs>,
|
||||
ar: Fs,
|
||||
value: u64,
|
||||
anchor: Fr,
|
||||
|
@ -102,7 +102,7 @@ impl SaplingProvingContext {
|
|||
.g_d::<Bls12>(params)
|
||||
.expect("was a valid diversifier before"),
|
||||
pk_d: payment_address.pk_d().clone(),
|
||||
r: rcm,
|
||||
rseed,
|
||||
};
|
||||
|
||||
let nullifier = note.nf(&viewing_key, merkle_path.position, params);
|
||||
|
@ -113,7 +113,7 @@ impl SaplingProvingContext {
|
|||
value_commitment: Some(value_commitment.clone()),
|
||||
proof_generation_key: Some(proof_generation_key),
|
||||
payment_address: Some(payment_address),
|
||||
commitment_randomness: Some(rcm),
|
||||
commitment_randomness: Some(note.rcm()),
|
||||
ar: Some(ar),
|
||||
auth_path: merkle_path
|
||||
.auth_path
|
||||
|
|
Loading…
Reference in New Issue