Send builder progress

This commit is contained in:
Aditya Kulkarni 2021-04-26 10:14:01 -07:00
parent 3b02c8b26e
commit f3aded9c84
1 changed files with 64 additions and 0 deletions

View File

@ -6,6 +6,7 @@ use std::boxed::Box;
use std::error;
use std::fmt;
use std::marker::PhantomData;
use std::sync::mpsc::Sender;
use ff::Field;
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.
pub struct Builder<'a, P: consensus::Parameters, R: RngCore> {
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
/// the network.
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,
consensus_branch_id: consensus::BranchId,
prover: &impl TxProver,
progress_notifier: Option<Sender<Progress>>,
) -> Result<(Transaction, TransactionMetadata), Error> {
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
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
if !spends.is_empty() {
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,
});
// 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
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);
}