zakura-client-backend 0.1.0-rc2

APIs for creating shielded Zcash light clients
Documentation
//! Types related to computation of fees and change related to the Orchard components
//! of a transaction.

use std::convert::Infallible;

use orchard::{builder::BundleType, bundle::BundleVersion};
use zcash_protocol::value::Zatoshis;

/// Returns the number of actions the transaction builder will produce for a
/// transactional (non-coinbase) Orchard-pool bundle of the given bundle type and
/// version, carrying the given numbers of requested spends and outputs.
///
/// The caller must pass the same [`BundleType`](orchard::builder::BundleType) the
/// transaction builder will be configured with: the builder enforces an exact
/// balance against the fee computed from these counts.
pub(crate) fn transactional_action_count(
    bundle_type: BundleType,
    bundle_version: BundleVersion,
    num_spends: usize,
    num_outputs: usize,
) -> Result<usize, &'static str> {
    bundle_type.num_actions(bundle_version.default_flags(), num_spends, num_outputs)
}

/// A trait that provides a minimized view of Orchard-style bundle configuration
/// suitable for use in fee and change calculation.
pub trait BundleView<NoteRef> {
    /// The type of inputs to the bundle.
    type In: InputView<NoteRef>;
    /// The type of inputs of the bundle.
    type Out: OutputView;

    /// Returns the bundle version for the bundle.
    fn bundle_version(&self) -> BundleVersion;
    /// Returns the inputs to the bundle.
    fn inputs(&self) -> &[Self::In];
    /// Returns the outputs of the bundle.
    fn outputs(&self) -> &[Self::Out];
}

impl<'a, NoteRef, In: InputView<NoteRef>, Out: OutputView> BundleView<NoteRef>
    for (BundleVersion, &'a [In], &'a [Out])
{
    type In = In;
    type Out = Out;

    fn bundle_version(&self) -> BundleVersion {
        self.0
    }

    fn inputs(&self) -> &[In] {
        self.1
    }

    fn outputs(&self) -> &[Out] {
        self.2
    }
}

/// A [`BundleView`] for the empty legacy Orchard bundle.
pub struct EmptyBundleView;

impl<NoteRef> BundleView<NoteRef> for EmptyBundleView {
    type In = Infallible;
    type Out = Infallible;

    fn bundle_version(&self) -> BundleVersion {
        // An empty bundle contains no spends or outputs, and therefore produces
        // zero actions under every bundle version's action-count policy, so the
        // version returned here cannot affect fee calculation.
        BundleVersion::orchard_v2()
    }

    fn inputs(&self) -> &[Self::In] {
        &[]
    }

    fn outputs(&self) -> &[Self::Out] {
        &[]
    }
}

/// A trait that provides a minimized view of an Orchard input suitable for use in fee and change
/// calculation.
pub trait InputView<NoteRef> {
    /// An identifier for the input being spent.
    fn note_id(&self) -> &NoteRef;
    /// The value of the input being spent.
    fn value(&self) -> Zatoshis;
}

impl<N> InputView<N> for Infallible {
    fn note_id(&self) -> &N {
        unreachable!()
    }
    fn value(&self) -> Zatoshis {
        unreachable!()
    }
}

/// A trait that provides a minimized view of a Orchard output suitable for use in fee and change
/// calculation.
pub trait OutputView {
    /// The value of the output being produced.
    fn value(&self) -> Zatoshis;
}

impl OutputView for Infallible {
    fn value(&self) -> Zatoshis {
        unreachable!()
    }
}

impl OutputView for Zatoshis {
    fn value(&self) -> Zatoshis {
        *self
    }
}