Add <P: consensus::Parameters> type parameter to Builder struct

This commit is contained in:
therealyingtong 2020-08-06 11:36:02 +08:00
parent 88072d64ec
commit 44f46e50ce
No known key found for this signature in database
GPG Key ID: 179F32A1503D607E
2 changed files with 52 additions and 33 deletions

View File

@ -286,7 +286,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(),
@ -297,7 +297,7 @@ pub fn create_to_address<P: AsRef<Path>>(
}
match to {
RecipientAddress::Shielded(to) => {
builder.add_sapling_output::<Network>(ovk, to.clone(), value, memo.clone())
builder.add_sapling_output(ovk, to.clone(), value, memo.clone())
}
RecipientAddress::Transparent(to) => builder.add_transparent_output(&to, value),
}?;

View File

@ -3,17 +3,18 @@
use crate::zip32::ExtendedSpendingKey;
use crate::{
jubjub::fs::Fs,
primitives::{Diversifier, Note, PaymentAddress, Rseed},
primitives::{Diversifier, Note, PaymentAddress},
};
use ff::Field;
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,
consensus::{NetworkUpgrade, Parameters},
consensus::{MainNetwork, NetworkUpgrade, TestNetwork},
keys::OutgoingViewingKey,
legacy::TransparentAddress,
merkle_tree::MerklePath,
@ -26,7 +27,7 @@ use crate::{
signature_hash_data, Transaction, TransactionData, SIGHASH_ALL,
},
util::generate_random_rseed,
Network, JUBJUB,
JUBJUB,
};
#[cfg(feature = "transparent-inputs")]
@ -305,7 +306,7 @@ 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,
@ -315,9 +316,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 Builder<MainNetwork, 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.
///
@ -332,7 +334,22 @@ impl Builder<OsRng> {
}
}
impl<R: RngCore + CryptoRng> Builder<R> {
impl Builder<TestNetwork, 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.
///
/// # Default values
///
/// The expiry height will be set to the given height plus the default transaction
/// expiry delta (20 blocks).
///
/// The fee will be set to the default fee (0.0001 ZEC).
pub fn new(height: u32) -> Self {
Builder::new_with_rng(height, OsRng)
}
}
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.
///
@ -342,7 +359,7 @@ 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;
@ -356,6 +373,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
outputs: vec![],
transparent_inputs: TransparentInputs::default(),
change_address: None,
phantom: PhantomData,
}
}
@ -397,7 +415,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
}
/// Adds a Sapling address to send funds to.
pub fn add_sapling_output<P: consensus::Parameters>(
pub fn add_sapling_output(
&mut self,
ovk: OutgoingViewingKey,
to: PaymentAddress<Bls12>,
@ -504,7 +522,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
return Err(Error::NoChangeAddress);
};
self.add_sapling_output::<Network>(change_address.0, change_address.1, change, None)?;
self.add_sapling_output(change_address.0, change_address.1, change, None)?;
}
//
@ -615,13 +633,11 @@ impl<R: RngCore + CryptoRng> Builder<R> {
}
};
let rseed = if self.height >= Network::CANOPY_ACTIVATION_HEIGHT {
let mut buffer = [0u8; 32];
&mut self.rng.fill_bytes(&mut buffer);
Rseed::AfterZip212(buffer)
} else {
Rseed::BeforeZip212(Fs::random(&mut self.rng))
};
let rseed = generate_random_rseed::<P, R>(
NetworkUpgrade::Canopy,
self.height,
&mut self.rng,
);
(
payment_address,
@ -714,12 +730,14 @@ 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,
@ -727,7 +745,7 @@ mod tests {
sapling::Node,
transaction::components::Amount,
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
Network, JUBJUB,
JUBJUB,
};
#[test]
@ -737,9 +755,9 @@ 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::<Network>(ovk, to, Amount::from_i64(-1).unwrap(), None),
builder.add_sapling_output(ovk, to, Amount::from_i64(-1).unwrap(), None),
Err(Error::InvalidAmount)
);
}
@ -753,10 +771,10 @@ mod tests {
};
let sapling_activation_height =
Network::activation_height(NetworkUpgrade::Sapling).unwrap();
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(),
@ -766,6 +784,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
@ -796,7 +815,7 @@ mod tests {
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
@ -822,7 +841,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]),
@ -842,7 +861,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()))
@ -856,9 +875,9 @@ 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::<Network>(
.add_sapling_output(
ovk.clone(),
to.clone(),
Amount::from_u64(50000).unwrap(),
@ -874,7 +893,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]),
@ -898,7 +917,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(),
@ -908,7 +927,7 @@ mod tests {
)
.unwrap();
builder
.add_sapling_output::<Network>(
.add_sapling_output(
ovk.clone(),
to.clone(),
Amount::from_u64(30000).unwrap(),
@ -941,7 +960,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(),
@ -954,7 +973,7 @@ mod tests {
.add_sapling_spend(extsk, *to.diversifier(), note2, witness2.path().unwrap())
.unwrap();
builder
.add_sapling_output::<Network>(ovk, to, Amount::from_u64(30000).unwrap(), None)
.add_sapling_output(ovk, to, Amount::from_u64(30000).unwrap(), None)
.unwrap();
builder
.add_transparent_output(