Skip to main content

zcash_client_backend/fees/
orchard.rs

1//! Types related to computation of fees and change related to the Orchard components
2//! of a transaction.
3
4use std::convert::Infallible;
5
6use orchard::{builder::BundleType, bundle::BundleVersion};
7use zcash_protocol::value::Zatoshis;
8
9/// Returns the number of actions the transaction builder will produce for a
10/// transactional (non-coinbase) Orchard-pool bundle of the given bundle type and
11/// version, carrying the given numbers of requested spends and outputs.
12///
13/// The caller must pass the same [`BundleType`](orchard::builder::BundleType) the
14/// transaction builder will be configured with: the builder enforces an exact
15/// balance against the fee computed from these counts.
16pub(crate) fn transactional_action_count(
17    bundle_type: BundleType,
18    bundle_version: BundleVersion,
19    num_spends: usize,
20    num_outputs: usize,
21) -> Result<usize, &'static str> {
22    bundle_type.num_actions(bundle_version.default_flags(), num_spends, num_outputs)
23}
24
25/// A trait that provides a minimized view of Orchard-style bundle configuration
26/// suitable for use in fee and change calculation.
27pub trait BundleView<NoteRef> {
28    /// The type of inputs to the bundle.
29    type In: InputView<NoteRef>;
30    /// The type of inputs of the bundle.
31    type Out: OutputView;
32
33    /// Returns the bundle version for the bundle.
34    fn bundle_version(&self) -> BundleVersion;
35    /// Returns the inputs to the bundle.
36    fn inputs(&self) -> &[Self::In];
37    /// Returns the outputs of the bundle.
38    fn outputs(&self) -> &[Self::Out];
39}
40
41impl<'a, NoteRef, In: InputView<NoteRef>, Out: OutputView> BundleView<NoteRef>
42    for (BundleVersion, &'a [In], &'a [Out])
43{
44    type In = In;
45    type Out = Out;
46
47    fn bundle_version(&self) -> BundleVersion {
48        self.0
49    }
50
51    fn inputs(&self) -> &[In] {
52        self.1
53    }
54
55    fn outputs(&self) -> &[Out] {
56        self.2
57    }
58}
59
60/// A [`BundleView`] for the empty legacy Orchard bundle.
61pub struct EmptyBundleView;
62
63impl<NoteRef> BundleView<NoteRef> for EmptyBundleView {
64    type In = Infallible;
65    type Out = Infallible;
66
67    fn bundle_version(&self) -> BundleVersion {
68        // An empty bundle contains no spends or outputs, and therefore produces
69        // zero actions under every bundle version's action-count policy, so the
70        // version returned here cannot affect fee calculation.
71        BundleVersion::orchard_v2()
72    }
73
74    fn inputs(&self) -> &[Self::In] {
75        &[]
76    }
77
78    fn outputs(&self) -> &[Self::Out] {
79        &[]
80    }
81}
82
83/// A trait that provides a minimized view of an Orchard input suitable for use in fee and change
84/// calculation.
85pub trait InputView<NoteRef> {
86    /// An identifier for the input being spent.
87    fn note_id(&self) -> &NoteRef;
88    /// The value of the input being spent.
89    fn value(&self) -> Zatoshis;
90}
91
92impl<N> InputView<N> for Infallible {
93    fn note_id(&self) -> &N {
94        unreachable!()
95    }
96    fn value(&self) -> Zatoshis {
97        unreachable!()
98    }
99}
100
101/// A trait that provides a minimized view of a Orchard output suitable for use in fee and change
102/// calculation.
103pub trait OutputView {
104    /// The value of the output being produced.
105    fn value(&self) -> Zatoshis;
106}
107
108impl OutputView for Infallible {
109    fn value(&self) -> Zatoshis {
110        unreachable!()
111    }
112}
113
114impl OutputView for Zatoshis {
115    fn value(&self) -> Zatoshis {
116        *self
117    }
118}