Send builder progress
This commit is contained in:
parent
3b02c8b26e
commit
f3aded9c84
|
@ -6,6 +6,7 @@ use std::boxed::Box;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore};
|
use rand::{rngs::OsRng, seq::SliceRandom, CryptoRng, RngCore};
|
||||||
|
@ -363,6 +364,30 @@ impl TransactionMetadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reports on the progress made by the builder towards building the transaction.
|
||||||
|
/// `cur` is the number of steps completed, and `end` is the total number of steps
|
||||||
|
/// expected. Note that each step may not be of the same complexity/duration
|
||||||
|
pub struct Progress {
|
||||||
|
cur: u32,
|
||||||
|
end: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Progress {
|
||||||
|
fn new(cur: u32, end: Option<u32>) -> Self {
|
||||||
|
Self { cur, end }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the amount of progress made so far building the Tx
|
||||||
|
pub fn cur(&self) -> u32 {
|
||||||
|
self.cur
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the total expected number of steps before this Tx is ready
|
||||||
|
pub fn end(&self) -> Option<u32> {
|
||||||
|
self.end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generates a [`Transaction`] from its inputs and outputs.
|
/// Generates a [`Transaction`] from its inputs and outputs.
|
||||||
pub struct Builder<'a, P: consensus::Parameters, R: RngCore> {
|
pub struct Builder<'a, P: consensus::Parameters, R: RngCore> {
|
||||||
params: P,
|
params: P,
|
||||||
|
@ -590,9 +615,32 @@ impl<'a, P: consensus::Parameters, R: RngCore> Builder<'a, P, R> {
|
||||||
/// this function, and instead will generate a transaction that will be rejected by
|
/// this function, and instead will generate a transaction that will be rejected by
|
||||||
/// the network.
|
/// the network.
|
||||||
pub fn build(
|
pub fn build(
|
||||||
|
self,
|
||||||
|
consensus_branch_id: consensus::BranchId,
|
||||||
|
prover: &impl TxProver,
|
||||||
|
) -> Result<(Transaction, TransactionMetadata), Error> {
|
||||||
|
self.build_with_progress_notifier(consensus_branch_id, prover, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds a transaction from the configured spends and outputs.
|
||||||
|
///
|
||||||
|
/// Upon success, returns a tuple containing the final transaction, and the
|
||||||
|
/// [`TransactionMetadata`] generated during the build process.
|
||||||
|
///
|
||||||
|
/// `consensus_branch_id` must be valid for the block height that this transaction is
|
||||||
|
/// targeting. An invalid `consensus_branch_id` will *not* result in an error from
|
||||||
|
/// this function, and instead will generate a transaction that will be rejected by
|
||||||
|
/// the network.
|
||||||
|
///
|
||||||
|
/// `progress_notifier` sets the notifier channel, where progress of building the transaction is sent.
|
||||||
|
/// It sends an update after every Spend or Output is computed, and the `u32` sent represents
|
||||||
|
/// the total steps completed so far. It will eventually send number of spends + outputs.
|
||||||
|
/// If there's an error building the transaction, the channel is closed.
|
||||||
|
pub fn build_with_progress_notifier(
|
||||||
mut self,
|
mut self,
|
||||||
consensus_branch_id: consensus::BranchId,
|
consensus_branch_id: consensus::BranchId,
|
||||||
prover: &impl TxProver,
|
prover: &impl TxProver,
|
||||||
|
progress_notifier: Option<Sender<Progress>>,
|
||||||
) -> Result<(Transaction, TransactionMetadata), Error> {
|
) -> Result<(Transaction, TransactionMetadata), Error> {
|
||||||
let mut tx_metadata = TransactionMetadata::new();
|
let mut tx_metadata = TransactionMetadata::new();
|
||||||
|
|
||||||
|
@ -682,6 +730,10 @@ impl<'a, P: consensus::Parameters, R: RngCore> Builder<'a, P, R> {
|
||||||
// Record if we'll need a binding signature
|
// Record if we'll need a binding signature
|
||||||
let binding_sig_needed = !spends.is_empty() || !outputs.is_empty();
|
let binding_sig_needed = !spends.is_empty() || !outputs.is_empty();
|
||||||
|
|
||||||
|
// Keep track of the total number of steps computed
|
||||||
|
let total_progress = spends.len() as u32 + outputs.len() as u32;
|
||||||
|
let mut progress = 0u32;
|
||||||
|
|
||||||
// Create Sapling SpendDescriptions
|
// Create Sapling SpendDescriptions
|
||||||
if !spends.is_empty() {
|
if !spends.is_empty() {
|
||||||
let anchor = self.anchor.expect("anchor was set if spends were added");
|
let anchor = self.anchor.expect("anchor was set if spends were added");
|
||||||
|
@ -716,6 +768,12 @@ impl<'a, P: consensus::Parameters, R: RngCore> Builder<'a, P, R> {
|
||||||
spend_auth_sig: None,
|
spend_auth_sig: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update progress and send a notification on the channel
|
||||||
|
progress += 1;
|
||||||
|
progress_notifier
|
||||||
|
.as_ref()
|
||||||
|
.map(|tx| tx.send(Progress::new(progress, Some(total_progress))));
|
||||||
|
|
||||||
// Record the post-randomized spend location
|
// Record the post-randomized spend location
|
||||||
tx_metadata.spend_indices[*pos] = i;
|
tx_metadata.spend_indices[*pos] = i;
|
||||||
}
|
}
|
||||||
|
@ -796,6 +854,12 @@ impl<'a, P: consensus::Parameters, R: RngCore> Builder<'a, P, R> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update progress and send a notification on the channel
|
||||||
|
progress += 1;
|
||||||
|
progress_notifier
|
||||||
|
.as_ref()
|
||||||
|
.map(|tx| tx.send(Progress::new(progress, Some(total_progress))));
|
||||||
|
|
||||||
self.mtx.shielded_outputs.push(output_desc);
|
self.mtx.shielded_outputs.push(output_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue