zcash_primitives: Remove `consensus::Parameters` from `sapling` module
Part of zcash/librustzcash#1044.
This commit is contained in:
parent
2c7c7b85e3
commit
eb0b5a1b24
|
@ -741,10 +741,12 @@ where
|
|||
{
|
||||
tx.sapling_bundle().and_then(|bundle| {
|
||||
try_sapling_note_decryption(
|
||||
params,
|
||||
proposal.min_target_height(),
|
||||
&internal_ivk,
|
||||
&bundle.shielded_outputs()[output_index],
|
||||
consensus::sapling_zip212_enforcement(
|
||||
params,
|
||||
proposal.min_target_height(),
|
||||
),
|
||||
)
|
||||
.map(|(note, _, _)| (account, note))
|
||||
})
|
||||
|
|
|
@ -56,6 +56,7 @@ pub fn decrypt_transaction<P: consensus::Parameters>(
|
|||
tx: &Transaction,
|
||||
ufvks: &HashMap<AccountId, UnifiedFullViewingKey>,
|
||||
) -> Vec<DecryptedOutput<sapling::Note>> {
|
||||
let zip212_enforcement = consensus::sapling_zip212_enforcement(params, height);
|
||||
tx.sapling_bundle()
|
||||
.iter()
|
||||
.flat_map(|bundle| {
|
||||
|
@ -76,19 +77,18 @@ pub fn decrypt_transaction<P: consensus::Parameters>(
|
|||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(move |(index, output)| {
|
||||
try_sapling_note_decryption(params, height, &ivk_external, output)
|
||||
try_sapling_note_decryption(&ivk_external, output, zip212_enforcement)
|
||||
.map(|ret| (ret, TransferType::Incoming))
|
||||
.or_else(|| {
|
||||
try_sapling_note_decryption(
|
||||
params,
|
||||
height,
|
||||
&ivk_internal,
|
||||
output,
|
||||
zip212_enforcement,
|
||||
)
|
||||
.map(|ret| (ret, TransferType::WalletInternal))
|
||||
})
|
||||
.or_else(|| {
|
||||
try_sapling_output_recovery(params, height, &ovk, output)
|
||||
try_sapling_output_recovery(&ovk, output, zip212_enforcement)
|
||||
.map(|ret| (ret, TransferType::Outgoing))
|
||||
})
|
||||
.into_iter()
|
||||
|
|
|
@ -267,22 +267,23 @@ pub fn scan_block<P: consensus::Parameters + Send + 'static, K: ScanningKey>(
|
|||
)
|
||||
}
|
||||
|
||||
type TaggedBatch<P, S> = Batch<(AccountId, S), SaplingDomain<P>, CompactOutputDescription>;
|
||||
type TaggedBatchRunner<P, S, T> =
|
||||
BatchRunner<(AccountId, S), SaplingDomain<P>, CompactOutputDescription, T>;
|
||||
type TaggedBatch<S> = Batch<(AccountId, S), SaplingDomain, CompactOutputDescription>;
|
||||
type TaggedBatchRunner<S, T> =
|
||||
BatchRunner<(AccountId, S), SaplingDomain, CompactOutputDescription, T>;
|
||||
|
||||
#[tracing::instrument(skip_all, fields(height = block.height))]
|
||||
pub(crate) fn add_block_to_runner<P, S, T>(
|
||||
params: &P,
|
||||
block: CompactBlock,
|
||||
batch_runner: &mut TaggedBatchRunner<P, S, T>,
|
||||
batch_runner: &mut TaggedBatchRunner<S, T>,
|
||||
) where
|
||||
P: consensus::Parameters + Send + 'static,
|
||||
S: Clone + Send + 'static,
|
||||
T: Tasks<TaggedBatch<P, S>>,
|
||||
T: Tasks<TaggedBatch<S>>,
|
||||
{
|
||||
let block_hash = block.hash();
|
||||
let block_height = block.height();
|
||||
let zip212_enforcement = consensus::sapling_zip212_enforcement(params, block_height);
|
||||
|
||||
for tx in block.vtx.into_iter() {
|
||||
let txid = tx.txid();
|
||||
|
@ -298,7 +299,7 @@ pub(crate) fn add_block_to_runner<P, S, T>(
|
|||
batch_runner.add_outputs(
|
||||
block_hash,
|
||||
txid,
|
||||
|| SaplingDomain::for_height(params.clone(), block_height),
|
||||
|| SaplingDomain::new(zip212_enforcement),
|
||||
&outputs,
|
||||
)
|
||||
}
|
||||
|
@ -330,14 +331,14 @@ fn check_hash_continuity(
|
|||
pub(crate) fn scan_block_with_runner<
|
||||
P: consensus::Parameters + Send + 'static,
|
||||
K: ScanningKey,
|
||||
T: Tasks<TaggedBatch<P, K::Scope>> + Sync,
|
||||
T: Tasks<TaggedBatch<K::Scope>> + Sync,
|
||||
>(
|
||||
params: &P,
|
||||
block: CompactBlock,
|
||||
vks: &[(&AccountId, K)],
|
||||
nullifiers: &[(AccountId, sapling::Nullifier)],
|
||||
prior_block_metadata: Option<&BlockMetadata>,
|
||||
mut batch_runner: Option<&mut TaggedBatchRunner<P, K::Scope, T>>,
|
||||
mut batch_runner: Option<&mut TaggedBatchRunner<K::Scope, T>>,
|
||||
) -> Result<ScannedBlock<K::Nf>, ScanError> {
|
||||
if let Some(scan_error) = check_hash_continuity(&block, prior_block_metadata) {
|
||||
return Err(scan_error);
|
||||
|
@ -345,6 +346,7 @@ pub(crate) fn scan_block_with_runner<
|
|||
|
||||
let cur_height = block.height();
|
||||
let cur_hash = block.hash();
|
||||
let zip212_enforcement = consensus::sapling_zip212_enforcement(params, cur_height);
|
||||
|
||||
let initial_sapling_tree_size = prior_block_metadata.and_then(|m| m.sapling_tree_size());
|
||||
let mut sapling_commitment_tree_size = initial_sapling_tree_size.map_or_else(
|
||||
|
@ -498,7 +500,7 @@ pub(crate) fn scan_block_with_runner<
|
|||
.into_iter()
|
||||
.map(|output| {
|
||||
(
|
||||
SaplingDomain::for_height(params.clone(), cur_height),
|
||||
SaplingDomain::new(zip212_enforcement),
|
||||
CompactOutputDescription::try_from(output)
|
||||
.expect("Invalid output found in compact block decoding."),
|
||||
)
|
||||
|
@ -655,7 +657,7 @@ mod tests {
|
|||
use zcash_note_encryption::Domain;
|
||||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
consensus::{BlockHeight, Network},
|
||||
consensus::{sapling_zip212_enforcement, BlockHeight, Network},
|
||||
memo::MemoBytes,
|
||||
sapling::{
|
||||
self,
|
||||
|
@ -726,22 +728,21 @@ mod tests {
|
|||
tx_after: bool,
|
||||
initial_tree_sizes: Option<(u32, u32)>,
|
||||
) -> CompactBlock {
|
||||
let zip212_enforcement = sapling_zip212_enforcement(&Network::TestNetwork, height);
|
||||
let to = dfvk.default_address().1;
|
||||
|
||||
// Create a fake Note for the account
|
||||
let mut rng = OsRng;
|
||||
let rseed = generate_random_rseed(&Network::TestNetwork, height, &mut rng);
|
||||
let rseed = generate_random_rseed(zip212_enforcement, &mut rng);
|
||||
let note = sapling::Note::from_parts(to, NoteValue::from(value), rseed);
|
||||
let encryptor = sapling_note_encryption::<_, Network>(
|
||||
let encryptor = sapling_note_encryption(
|
||||
Some(dfvk.fvk().ovk),
|
||||
note.clone(),
|
||||
MemoBytes::empty(),
|
||||
&mut rng,
|
||||
);
|
||||
let cmu = note.cmu().to_bytes().to_vec();
|
||||
let ephemeral_key = SaplingDomain::<Network>::epk_bytes(encryptor.epk())
|
||||
.0
|
||||
.to_vec();
|
||||
let ephemeral_key = SaplingDomain::epk_bytes(encryptor.epk()).0.to_vec();
|
||||
let enc_ciphertext = encryptor.encrypt_note_plaintext();
|
||||
|
||||
// Create a fake CompactBlock containing the note
|
||||
|
|
|
@ -770,18 +770,19 @@ pub(crate) fn fake_compact_block<P: consensus::Parameters>(
|
|||
|
||||
// Create a fake Note for the account
|
||||
let mut rng = OsRng;
|
||||
let rseed = generate_random_rseed(params, height, &mut rng);
|
||||
let rseed = generate_random_rseed(
|
||||
consensus::sapling_zip212_enforcement(params, height),
|
||||
&mut rng,
|
||||
);
|
||||
let note = Note::from_parts(to, NoteValue::from(value), rseed);
|
||||
let encryptor = sapling_note_encryption::<_, Network>(
|
||||
let encryptor = sapling_note_encryption(
|
||||
Some(dfvk.fvk().ovk),
|
||||
note.clone(),
|
||||
MemoBytes::empty(),
|
||||
&mut rng,
|
||||
);
|
||||
let cmu = note.cmu().to_bytes().to_vec();
|
||||
let ephemeral_key = SaplingDomain::<Network>::epk_bytes(encryptor.epk())
|
||||
.0
|
||||
.to_vec();
|
||||
let ephemeral_key = SaplingDomain::epk_bytes(encryptor.epk()).0.to_vec();
|
||||
let enc_ciphertext = encryptor.encrypt_note_plaintext();
|
||||
|
||||
// Create a fake CompactBlock containing the note
|
||||
|
@ -866,8 +867,9 @@ pub(crate) fn fake_compact_block_spending<P: consensus::Parameters>(
|
|||
value: NonNegativeAmount,
|
||||
initial_sapling_tree_size: u32,
|
||||
) -> CompactBlock {
|
||||
let zip212_enforcement = consensus::sapling_zip212_enforcement(params, height);
|
||||
let mut rng = OsRng;
|
||||
let rseed = generate_random_rseed(params, height, &mut rng);
|
||||
let rseed = generate_random_rseed(zip212_enforcement, &mut rng);
|
||||
|
||||
// Create a fake CompactBlock containing the note
|
||||
let cspend = CompactSaplingSpend { nf: nf.to_vec() };
|
||||
|
@ -880,16 +882,14 @@ pub(crate) fn fake_compact_block_spending<P: consensus::Parameters>(
|
|||
// Create a fake Note for the payment
|
||||
ctx.outputs.push({
|
||||
let note = Note::from_parts(to, NoteValue::from(value), rseed);
|
||||
let encryptor = sapling_note_encryption::<_, Network>(
|
||||
let encryptor = sapling_note_encryption(
|
||||
Some(dfvk.fvk().ovk),
|
||||
note.clone(),
|
||||
MemoBytes::empty(),
|
||||
&mut rng,
|
||||
);
|
||||
let cmu = note.cmu().to_bytes().to_vec();
|
||||
let ephemeral_key = SaplingDomain::<Network>::epk_bytes(encryptor.epk())
|
||||
.0
|
||||
.to_vec();
|
||||
let ephemeral_key = SaplingDomain::epk_bytes(encryptor.epk()).0.to_vec();
|
||||
let enc_ciphertext = encryptor.encrypt_note_plaintext();
|
||||
|
||||
CompactSaplingOutput {
|
||||
|
@ -902,22 +902,20 @@ pub(crate) fn fake_compact_block_spending<P: consensus::Parameters>(
|
|||
// Create a fake Note for the change
|
||||
ctx.outputs.push({
|
||||
let change_addr = dfvk.default_address().1;
|
||||
let rseed = generate_random_rseed(params, height, &mut rng);
|
||||
let rseed = generate_random_rseed(zip212_enforcement, &mut rng);
|
||||
let note = Note::from_parts(
|
||||
change_addr,
|
||||
NoteValue::from((in_value - value).unwrap()),
|
||||
rseed,
|
||||
);
|
||||
let encryptor = sapling_note_encryption::<_, Network>(
|
||||
let encryptor = sapling_note_encryption(
|
||||
Some(dfvk.fvk().ovk),
|
||||
note.clone(),
|
||||
MemoBytes::empty(),
|
||||
&mut rng,
|
||||
);
|
||||
let cmu = note.cmu().to_bytes().to_vec();
|
||||
let ephemeral_key = SaplingDomain::<Network>::epk_bytes(encryptor.epk())
|
||||
.0
|
||||
.to_vec();
|
||||
let ephemeral_key = SaplingDomain::epk_bytes(encryptor.epk()).0.to_vec();
|
||||
let enc_ciphertext = encryptor.encrypt_note_plaintext();
|
||||
|
||||
CompactSaplingOutput {
|
||||
|
|
|
@ -423,7 +423,7 @@ pub(crate) mod tests {
|
|||
|
||||
use zcash_primitives::{
|
||||
block::BlockHash,
|
||||
consensus::BranchId,
|
||||
consensus::{sapling_zip212_enforcement, BranchId},
|
||||
legacy::TransparentAddress,
|
||||
memo::{Memo, MemoBytes},
|
||||
sapling::{
|
||||
|
@ -1033,10 +1033,9 @@ pub(crate) mod tests {
|
|||
for output in tx.sapling_bundle().unwrap().shielded_outputs() {
|
||||
// Find the output that decrypts with the external OVK
|
||||
let result = try_sapling_output_recovery(
|
||||
&st.network(),
|
||||
h1,
|
||||
&dfvk.to_ovk(Scope::External),
|
||||
output,
|
||||
sapling_zip212_enforcement(&st.network(), h1),
|
||||
);
|
||||
|
||||
if result.is_some() {
|
||||
|
|
|
@ -8,6 +8,7 @@ and this library adheres to Rust's notion of
|
|||
## [Unreleased]
|
||||
### Added
|
||||
- Dependency on `bellman 0.14`.
|
||||
- `zcash_primitives::consensus::sapling_zip212_enforcement`
|
||||
- `zcash_primitives::sapling`:
|
||||
- `BatchValidator` (moved from `zcash_proofs::sapling`).
|
||||
- `SaplingVerificationContext` (moved from `zcash_proofs::sapling`).
|
||||
|
@ -46,6 +47,8 @@ and this library adheres to Rust's notion of
|
|||
- `constants` module.
|
||||
- `note_encryption::CompactOutputDescription` (moved from
|
||||
`zcash_primitives::transaction::components::sapling`).
|
||||
- `note_encryption::SaplingDomain::new`
|
||||
- `note_encryption::Zip212Enforcement`
|
||||
- `prover::{SpendProver, OutputProver}`
|
||||
- `value`:
|
||||
- `ValueCommitTrapdoor::from_bytes`
|
||||
|
@ -95,12 +98,16 @@ and this library adheres to Rust's notion of
|
|||
newtypes.
|
||||
- `address::PaymentAddress::create_note` now takes its `value` argument as a
|
||||
`NoteValue` instead of as a bare `u64`.
|
||||
- `builder::SaplingBuilder` no longer has a `P: consensus::Parameters` type
|
||||
parameter.
|
||||
- `builder::SaplingBuilder::new` now takes a `Zip212Enforcement` argument
|
||||
instead of a `P: consensus::Parameters` argument and a target height.
|
||||
- `builder::SaplingBuilder::add_spend` now takes `extsk` by reference.
|
||||
- `builder::SaplingBuilder::build` no longer takes a prover, proving context,
|
||||
or progress notifier. Instead, it has `SpendProver, OutputProver` generic
|
||||
parameters and returns `(UnauthorizedBundle, SaplingMetadata)`. The caller
|
||||
can then use `Bundle::<InProgress<Unproven, _>>::create_proofs` to create
|
||||
spend and output proofs for the bundle.
|
||||
progress notifier, or target height. Instead, it has `SpendProver, OutputProver`
|
||||
generic parameters and returns `(UnauthorizedBundle, SaplingMetadata)`. The
|
||||
caller can then use `Bundle::<InProgress<Unproven, _>>::create_proofs` to
|
||||
create spend and output proofs for the bundle.
|
||||
- `builder::Error` has new error variants:
|
||||
- `Error::DuplicateSignature`
|
||||
- `Error::InvalidExternalSignature`
|
||||
|
@ -108,6 +115,17 @@ and this library adheres to Rust's notion of
|
|||
- `bundle::MapAuth` trait methods now take `&mut self` instead of `&self`.
|
||||
- `circuit::ValueCommitmentOpening::value` is now represented as a `NoteValue`
|
||||
instead of as a bare `u64`.
|
||||
- `note_encryption`:
|
||||
- `SaplingDomain` no longer has a `P: consensus::Parameters` type parameter.
|
||||
- The following methods now take a `Zip212Enforcement` argument instead of a
|
||||
`P: consensus::Parameters` argument:
|
||||
- `plaintext_version_is_valid`
|
||||
- `try_sapling_note_decryption`
|
||||
- `try_sapling_compact_note_decryption`
|
||||
- `try_sapling_output_recovery_with_ock`
|
||||
- `try_sapling_output_recovery`
|
||||
- `util::generate_random_rseed` now takes a `Zip212Enforcement` argument
|
||||
instead of a `P: consensus::Parameters` argument and a height.
|
||||
- `zcash_primitives::transaction`:
|
||||
- `builder::Builder::{build, build_zfuture}` now take
|
||||
`&impl SpendProver, &impl OutputProver` instead of `&impl TxProver`.
|
||||
|
@ -135,13 +153,16 @@ and this library adheres to Rust's notion of
|
|||
### Removed
|
||||
- `zcash_primitives::constants`:
|
||||
- All `const` values (moved to `zcash_primitives::sapling::constants`).
|
||||
- `zcash_primitives::sapling::bundle`:
|
||||
- `SpendDescription::{read, read_nullifier, read_rk, read_spend_auth_sig}`
|
||||
- `SpendDescription::{write_v4, write_v5_without_witness_data}`
|
||||
- `SpendDescriptionV5::read`
|
||||
- `OutputDescription::read`
|
||||
- `OutputDescription::{write_v4, write_v5_without_proof}`
|
||||
- `OutputDescriptionV5::read`
|
||||
- `zcash_primitives::sapling`:
|
||||
- `bundle`:
|
||||
- `SpendDescription::{read, read_nullifier, read_rk, read_spend_auth_sig}`
|
||||
- `SpendDescription::{write_v4, write_v5_without_witness_data}`
|
||||
- `SpendDescriptionV5::read`
|
||||
- `OutputDescription::read`
|
||||
- `OutputDescription::{write_v4, write_v5_without_proof}`
|
||||
- `OutputDescriptionV5::read`
|
||||
- `note_encryption::SaplingDomain::for_height` (use `SaplingDomain::new`
|
||||
instead).
|
||||
- `zcash_primitives::transaction::components::sapling`:
|
||||
- The following types were removed from this module (moved into
|
||||
`zcash_primitives::sapling::bundle`):
|
||||
|
|
|
@ -5,7 +5,7 @@ use ff::Field;
|
|||
use rand_core::OsRng;
|
||||
use zcash_note_encryption::batch;
|
||||
use zcash_primitives::{
|
||||
consensus::{NetworkUpgrade::Canopy, Parameters, TEST_NETWORK},
|
||||
consensus::{sapling_zip212_enforcement, NetworkUpgrade::Canopy, Parameters, TEST_NETWORK},
|
||||
memo::MemoBytes,
|
||||
sapling::{
|
||||
builder::SaplingBuilder,
|
||||
|
@ -25,6 +25,7 @@ use pprof::criterion::{Output, PProfProfiler};
|
|||
fn bench_note_decryption(c: &mut Criterion) {
|
||||
let mut rng = OsRng;
|
||||
let height = TEST_NETWORK.activation_height(Canopy).unwrap();
|
||||
let zip212_enforcement = sapling_zip212_enforcement(&TEST_NETWORK, height);
|
||||
|
||||
let valid_ivk = SaplingIvk(jubjub::Fr::random(&mut rng));
|
||||
let invalid_ivk = SaplingIvk(jubjub::Fr::random(&mut rng));
|
||||
|
@ -34,7 +35,7 @@ fn bench_note_decryption(c: &mut Criterion) {
|
|||
let diversifier = Diversifier([0; 11]);
|
||||
let pa = valid_ivk.to_payment_address(diversifier).unwrap();
|
||||
|
||||
let mut builder = SaplingBuilder::new(TEST_NETWORK, height);
|
||||
let mut builder = SaplingBuilder::new(zip212_enforcement);
|
||||
builder
|
||||
.add_output(
|
||||
&mut rng,
|
||||
|
@ -45,7 +46,7 @@ fn bench_note_decryption(c: &mut Criterion) {
|
|||
)
|
||||
.unwrap();
|
||||
let (bundle, _) = builder
|
||||
.build::<MockSpendProver, MockOutputProver, _>(&mut rng, height)
|
||||
.build::<MockSpendProver, MockOutputProver, _>(&mut rng)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
bundle.shielded_outputs()[0].clone()
|
||||
|
@ -59,27 +60,25 @@ fn bench_note_decryption(c: &mut Criterion) {
|
|||
group.throughput(Throughput::Elements(1));
|
||||
|
||||
group.bench_function("valid", |b| {
|
||||
b.iter(|| {
|
||||
try_sapling_note_decryption(&TEST_NETWORK, height, &valid_ivk, &output).unwrap()
|
||||
})
|
||||
b.iter(|| try_sapling_note_decryption(&valid_ivk, &output, zip212_enforcement).unwrap())
|
||||
});
|
||||
|
||||
group.bench_function("invalid", |b| {
|
||||
b.iter(|| try_sapling_note_decryption(&TEST_NETWORK, height, &invalid_ivk, &output))
|
||||
b.iter(|| try_sapling_note_decryption(&invalid_ivk, &output, zip212_enforcement))
|
||||
});
|
||||
|
||||
let compact = CompactOutputDescription::from(output.clone());
|
||||
|
||||
group.bench_function("compact-valid", |b| {
|
||||
b.iter(|| {
|
||||
try_sapling_compact_note_decryption(&TEST_NETWORK, height, &valid_ivk, &compact)
|
||||
try_sapling_compact_note_decryption(&valid_ivk, &compact, zip212_enforcement)
|
||||
.unwrap()
|
||||
})
|
||||
});
|
||||
|
||||
group.bench_function("compact-invalid", |b| {
|
||||
b.iter(|| {
|
||||
try_sapling_compact_note_decryption(&TEST_NETWORK, height, &invalid_ivk, &compact)
|
||||
try_sapling_compact_note_decryption(&invalid_ivk, &compact, zip212_enforcement)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -93,7 +92,7 @@ fn bench_note_decryption(c: &mut Criterion) {
|
|||
|
||||
let outputs: Vec<_> = iter::repeat(output.clone())
|
||||
.take(noutputs)
|
||||
.map(|output| (SaplingDomain::for_height(TEST_NETWORK, height), output))
|
||||
.map(|output| (SaplingDomain::new(zip212_enforcement), output))
|
||||
.collect();
|
||||
|
||||
group.bench_function(
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::fmt;
|
|||
use std::ops::{Add, Bound, RangeBounds, Sub};
|
||||
use zcash_address;
|
||||
|
||||
use crate::constants;
|
||||
use crate::{constants, sapling::note_encryption::Zip212Enforcement};
|
||||
|
||||
/// A wrapper type representing blockchain heights. Safe conversion from
|
||||
/// various integer types, as well as addition and subtraction, are provided.
|
||||
|
@ -599,6 +599,25 @@ impl BranchId {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the enforcement policy for ZIP 212 at the given height.
|
||||
pub fn sapling_zip212_enforcement(
|
||||
params: &impl Parameters,
|
||||
height: BlockHeight,
|
||||
) -> Zip212Enforcement {
|
||||
if params.is_nu_active(NetworkUpgrade::Canopy, height) {
|
||||
let grace_period_end_height =
|
||||
params.activation_height(NetworkUpgrade::Canopy).unwrap() + ZIP212_GRACE_PERIOD;
|
||||
|
||||
if height < grace_period_end_height {
|
||||
Zip212Enforcement::GracePeriod
|
||||
} else {
|
||||
Zip212Enforcement::On
|
||||
}
|
||||
} else {
|
||||
Zip212Enforcement::Off
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-dependencies"))]
|
||||
pub mod testing {
|
||||
use proptest::sample::select;
|
||||
|
|
|
@ -8,7 +8,6 @@ use rand::{seq::SliceRandom, RngCore};
|
|||
use rand_core::CryptoRng;
|
||||
|
||||
use crate::{
|
||||
consensus::{self, BlockHeight},
|
||||
keys::OutgoingViewingKey,
|
||||
memo::MemoBytes,
|
||||
sapling::{
|
||||
|
@ -18,7 +17,7 @@ use crate::{
|
|||
SpendDescription,
|
||||
},
|
||||
constants::{SPENDING_KEY_GENERATOR, VALUE_COMMITMENT_RANDOMNESS_GENERATOR},
|
||||
note_encryption::sapling_note_encryption,
|
||||
note_encryption::{sapling_note_encryption, Zip212Enforcement},
|
||||
prover::{OutputProver, SpendProver},
|
||||
redjubjub::{PrivateKey, PublicKey, Signature},
|
||||
spend_sig_internal,
|
||||
|
@ -174,11 +173,7 @@ struct SaplingOutputInfo {
|
|||
}
|
||||
|
||||
impl SaplingOutputInfo {
|
||||
fn dummy<P: consensus::Parameters, R: RngCore>(
|
||||
params: &P,
|
||||
mut rng: &mut R,
|
||||
target_height: BlockHeight,
|
||||
) -> Self {
|
||||
fn dummy<R: RngCore>(mut rng: &mut R, zip212_enforcement: Zip212Enforcement) -> Self {
|
||||
// This is a dummy output
|
||||
let dummy_to = {
|
||||
let mut diversifier = Diversifier([0; 11]);
|
||||
|
@ -192,26 +187,24 @@ impl SaplingOutputInfo {
|
|||
};
|
||||
|
||||
Self::new_internal(
|
||||
params,
|
||||
rng,
|
||||
target_height,
|
||||
None,
|
||||
dummy_to,
|
||||
NoteValue::from_raw(0),
|
||||
MemoBytes::empty(),
|
||||
zip212_enforcement,
|
||||
)
|
||||
}
|
||||
|
||||
fn new_internal<P: consensus::Parameters, R: RngCore>(
|
||||
params: &P,
|
||||
fn new_internal<R: RngCore>(
|
||||
rng: &mut R,
|
||||
target_height: BlockHeight,
|
||||
ovk: Option<OutgoingViewingKey>,
|
||||
to: PaymentAddress,
|
||||
value: NoteValue,
|
||||
memo: MemoBytes,
|
||||
zip212_enforcement: Zip212Enforcement,
|
||||
) -> Self {
|
||||
let rseed = generate_random_rseed_internal(params, target_height, rng);
|
||||
let rseed = generate_random_rseed_internal(zip212_enforcement, rng);
|
||||
|
||||
let note = Note::from_parts(to, value, rseed);
|
||||
|
||||
|
@ -223,12 +216,11 @@ impl SaplingOutputInfo {
|
|||
}
|
||||
}
|
||||
|
||||
fn build<P: consensus::Parameters, Pr: OutputProver, R: RngCore>(
|
||||
fn build<Pr: OutputProver, R: RngCore>(
|
||||
self,
|
||||
rng: &mut R,
|
||||
) -> OutputDescription<sapling::circuit::Output> {
|
||||
let encryptor =
|
||||
sapling_note_encryption::<R, P>(self.ovk, self.note.clone(), self.memo, rng);
|
||||
let encryptor = sapling_note_encryption::<R>(self.ovk, self.note.clone(), self.memo, rng);
|
||||
|
||||
// Construct the value commitment.
|
||||
let cv = ValueCommitment::derive(self.note.value(), self.rcv.clone());
|
||||
|
@ -305,24 +297,22 @@ impl SaplingMetadata {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SaplingBuilder<P> {
|
||||
params: P,
|
||||
pub struct SaplingBuilder {
|
||||
anchor: Option<bls12_381::Scalar>,
|
||||
target_height: BlockHeight,
|
||||
value_balance: ValueSum,
|
||||
spends: Vec<SpendDescriptionInfo>,
|
||||
outputs: Vec<SaplingOutputInfo>,
|
||||
zip212_enforcement: Zip212Enforcement,
|
||||
}
|
||||
|
||||
impl<P> SaplingBuilder<P> {
|
||||
pub fn new(params: P, target_height: BlockHeight) -> Self {
|
||||
impl SaplingBuilder {
|
||||
pub fn new(zip212_enforcement: Zip212Enforcement) -> Self {
|
||||
SaplingBuilder {
|
||||
params,
|
||||
anchor: None,
|
||||
target_height,
|
||||
value_balance: ValueSum::zero(),
|
||||
spends: vec![],
|
||||
outputs: vec![],
|
||||
zip212_enforcement,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,9 +356,7 @@ impl<P> SaplingBuilder<P> {
|
|||
self.try_value_balance()
|
||||
.expect("we check this when mutating self.value_balance")
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: consensus::Parameters> SaplingBuilder<P> {
|
||||
/// Adds a Sapling note to be spent in this transaction.
|
||||
///
|
||||
/// Returns an error if the given Merkle path does not have the same anchor as the
|
||||
|
@ -414,13 +402,12 @@ impl<P: consensus::Parameters> SaplingBuilder<P> {
|
|||
memo: MemoBytes,
|
||||
) -> Result<(), Error> {
|
||||
let output = SaplingOutputInfo::new_internal(
|
||||
&self.params,
|
||||
&mut rng,
|
||||
self.target_height,
|
||||
ovk,
|
||||
to,
|
||||
value,
|
||||
memo,
|
||||
self.zip212_enforcement,
|
||||
);
|
||||
|
||||
self.value_balance = (self.value_balance - value).ok_or(Error::InvalidAddress)?;
|
||||
|
@ -434,7 +421,6 @@ impl<P: consensus::Parameters> SaplingBuilder<P> {
|
|||
pub fn build<SP: SpendProver, OP: OutputProver, R: RngCore>(
|
||||
self,
|
||||
mut rng: R,
|
||||
target_height: BlockHeight,
|
||||
) -> Result<Option<(UnauthorizedBundle, SaplingMetadata)>, Error> {
|
||||
let value_balance = self.try_value_balance()?;
|
||||
|
||||
|
@ -486,7 +472,7 @@ impl<P: consensus::Parameters> SaplingBuilder<P> {
|
|||
output
|
||||
} else {
|
||||
// This is a dummy output
|
||||
SaplingOutputInfo::dummy(&self.params, &mut rng, target_height)
|
||||
SaplingOutputInfo::dummy(&mut rng, self.zip212_enforcement)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -505,7 +491,7 @@ impl<P: consensus::Parameters> SaplingBuilder<P> {
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let shielded_outputs = output_infos
|
||||
.into_iter()
|
||||
.map(|a| a.build::<P, OP, _>(&mut rng))
|
||||
.map(|a| a.build::<OP, _>(&mut rng))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Verify that bsk and bvk are consistent.
|
||||
|
@ -881,12 +867,9 @@ pub mod testing {
|
|||
use rand::{rngs::StdRng, SeedableRng};
|
||||
|
||||
use crate::{
|
||||
consensus::{
|
||||
testing::{arb_branch_id, arb_height},
|
||||
TEST_NETWORK,
|
||||
},
|
||||
sapling::{
|
||||
bundle::{Authorized, Bundle},
|
||||
note_encryption::Zip212Enforcement,
|
||||
prover::mock::{MockOutputProver, MockSpendProver},
|
||||
redjubjub::PrivateKey,
|
||||
testing::{arb_node, arb_note},
|
||||
|
@ -903,7 +886,7 @@ pub mod testing {
|
|||
use super::SaplingBuilder;
|
||||
|
||||
prop_compose! {
|
||||
fn arb_bundle()(n_notes in 1..30usize)(
|
||||
fn arb_bundle(zip212_enforcement: Zip212Enforcement)(n_notes in 1..30usize)(
|
||||
extsk in arb_extended_spending_key(),
|
||||
spendable_notes in vec(
|
||||
arb_positive_note_value(MAX_MONEY as u64 / 10000).prop_flat_map(arb_note),
|
||||
|
@ -916,11 +899,10 @@ pub mod testing {
|
|||
n_notes
|
||||
),
|
||||
diversifiers in vec(prop::array::uniform11(any::<u8>()).prop_map(Diversifier), n_notes),
|
||||
target_height in arb_branch_id().prop_flat_map(|b| arb_height(b, &TEST_NETWORK)),
|
||||
rng_seed in prop::array::uniform32(any::<u8>()),
|
||||
fake_sighash_bytes in prop::array::uniform32(any::<u8>()),
|
||||
) -> Bundle<Authorized> {
|
||||
let mut builder = SaplingBuilder::new(TEST_NETWORK, target_height.unwrap());
|
||||
let mut builder = SaplingBuilder::new(zip212_enforcement);
|
||||
let mut rng = StdRng::from_seed(rng_seed);
|
||||
|
||||
for ((note, path), diversifier) in spendable_notes.into_iter().zip(commitment_trees.into_iter()).zip(diversifiers.into_iter()) {
|
||||
|
@ -933,10 +915,10 @@ pub mod testing {
|
|||
).unwrap();
|
||||
}
|
||||
|
||||
let (bundle, _) = builder.build::<MockSpendProver, MockOutputProver, _>(
|
||||
&mut rng,
|
||||
target_height.unwrap(),
|
||||
).unwrap().unwrap();
|
||||
let (bundle, _) = builder
|
||||
.build::<MockSpendProver, MockOutputProver, _>(&mut rng)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
let bundle = bundle.create_proofs(
|
||||
&MockSpendProver,
|
||||
|
|
|
@ -7,7 +7,6 @@ use zcash_note_encryption::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
consensus,
|
||||
sapling::{
|
||||
note::ExtractedNoteCommitment,
|
||||
note_encryption::{CompactOutputDescription, SaplingDomain},
|
||||
|
@ -533,9 +532,7 @@ impl<Proof: DynamicUsage> DynamicUsage for OutputDescription<Proof> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<P: consensus::Parameters, A> ShieldedOutput<SaplingDomain<P>, ENC_CIPHERTEXT_SIZE>
|
||||
for OutputDescription<A>
|
||||
{
|
||||
impl<A> ShieldedOutput<SaplingDomain, ENC_CIPHERTEXT_SIZE> for OutputDescription<A> {
|
||||
fn ephemeral_key(&self) -> EphemeralKeyBytes {
|
||||
self.ephemeral_key.clone()
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,9 +2,7 @@ use blake2b_simd::Params;
|
|||
use ff::Field;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
use crate::consensus::{self, BlockHeight, NetworkUpgrade};
|
||||
|
||||
use super::Rseed;
|
||||
use super::{note_encryption::Zip212Enforcement, Rseed};
|
||||
|
||||
pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> jubjub::Fr {
|
||||
let mut hasher = Params::new().hash_length(64).personal(persona).to_state();
|
||||
|
@ -14,24 +12,23 @@ pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> jubjub::Fr {
|
|||
jubjub::Fr::from_bytes_wide(ret.as_array())
|
||||
}
|
||||
|
||||
pub fn generate_random_rseed<P: consensus::Parameters, R: RngCore + CryptoRng>(
|
||||
params: &P,
|
||||
height: BlockHeight,
|
||||
pub fn generate_random_rseed<R: RngCore + CryptoRng>(
|
||||
zip212_enforcement: Zip212Enforcement,
|
||||
rng: &mut R,
|
||||
) -> Rseed {
|
||||
generate_random_rseed_internal(params, height, rng)
|
||||
generate_random_rseed_internal(zip212_enforcement, rng)
|
||||
}
|
||||
|
||||
pub(crate) fn generate_random_rseed_internal<P: consensus::Parameters, R: RngCore>(
|
||||
params: &P,
|
||||
height: BlockHeight,
|
||||
pub(crate) fn generate_random_rseed_internal<R: RngCore>(
|
||||
zip212_enforcement: Zip212Enforcement,
|
||||
rng: &mut R,
|
||||
) -> Rseed {
|
||||
if params.is_nu_active(NetworkUpgrade::Canopy, height) {
|
||||
let mut buffer = [0u8; 32];
|
||||
rng.fill_bytes(&mut buffer);
|
||||
Rseed::AfterZip212(buffer)
|
||||
} else {
|
||||
Rseed::BeforeZip212(jubjub::Fr::random(rng))
|
||||
match zip212_enforcement {
|
||||
Zip212Enforcement::Off => Rseed::BeforeZip212(jubjub::Fr::random(rng)),
|
||||
Zip212Enforcement::GracePeriod | Zip212Enforcement::On => {
|
||||
let mut buffer = [0u8; 32];
|
||||
rng.fill_bytes(&mut buffer);
|
||||
Rseed::AfterZip212(buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ pub struct Builder<'a, P, R> {
|
|||
target_height: BlockHeight,
|
||||
expiry_height: BlockHeight,
|
||||
transparent_builder: TransparentBuilder,
|
||||
sapling_builder: SaplingBuilder<P>,
|
||||
sapling_builder: SaplingBuilder,
|
||||
orchard_builder: Option<orchard::builder::Builder>,
|
||||
// TODO: In the future, instead of taking the spending keys as arguments when calling
|
||||
// `add_sapling_spend` or `add_orchard_spend`, we will build an unauthorized, unproven
|
||||
|
@ -261,13 +261,15 @@ impl<'a, P: consensus::Parameters, R: RngCore + CryptoRng> Builder<'a, P, R> {
|
|||
target_height: BlockHeight,
|
||||
orchard_builder: Option<orchard::builder::Builder>,
|
||||
) -> Self {
|
||||
let zip212_enforcement = consensus::sapling_zip212_enforcement(¶ms, target_height);
|
||||
|
||||
Builder {
|
||||
params: params.clone(),
|
||||
params,
|
||||
rng,
|
||||
target_height,
|
||||
expiry_height: target_height + DEFAULT_TX_EXPIRY_DELTA,
|
||||
transparent_builder: TransparentBuilder::empty(),
|
||||
sapling_builder: SaplingBuilder::new(params, target_height),
|
||||
sapling_builder: SaplingBuilder::new(zip212_enforcement),
|
||||
orchard_builder,
|
||||
sapling_asks: vec![],
|
||||
orchard_saks: Vec::new(),
|
||||
|
@ -511,7 +513,7 @@ impl<'a, P: consensus::Parameters, R: RngCore + CryptoRng> Builder<'a, P, R> {
|
|||
let mut rng = self.rng;
|
||||
let (sapling_bundle, tx_metadata) = match self
|
||||
.sapling_builder
|
||||
.build::<SP, OP, _>(&mut rng, self.target_height)
|
||||
.build::<SP, OP, _>(&mut rng)
|
||||
.map_err(Error::SaplingBuild)?
|
||||
.map(|(bundle, tx_metadata)| {
|
||||
// We need to create proofs before signatures, because we still support
|
||||
|
@ -749,6 +751,7 @@ mod tests {
|
|||
#[cfg(feature = "transparent-inputs")]
|
||||
use crate::{
|
||||
legacy::keys::{AccountPrivKey, IncomingViewingKey},
|
||||
sapling::note_encryption::Zip212Enforcement,
|
||||
transaction::{
|
||||
builder::{SaplingBuilder, DEFAULT_TX_EXPIRY_DELTA},
|
||||
OutPoint, TxOut,
|
||||
|
@ -775,7 +778,7 @@ mod tests {
|
|||
target_height: sapling_activation_height,
|
||||
expiry_height: sapling_activation_height + DEFAULT_TX_EXPIRY_DELTA,
|
||||
transparent_builder: TransparentBuilder::empty(),
|
||||
sapling_builder: SaplingBuilder::new(TEST_NETWORK, sapling_activation_height),
|
||||
sapling_builder: SaplingBuilder::new(Zip212Enforcement::Off),
|
||||
#[cfg(feature = "zfuture")]
|
||||
tze_builder: TzeBuilder::empty(),
|
||||
#[cfg(not(feature = "zfuture"))]
|
||||
|
|
Loading…
Reference in New Issue