zcash_client_backend/fees/
sapling.rs

1//! Types related to computation of fees and change related to the Sapling components
2//! of a transaction.
3
4use std::convert::Infallible;
5
6use sapling::builder::{BundleType, OutputInfo, SpendInfo};
7use zcash_protocol::value::Zatoshis;
8
9/// A trait that provides a minimized view of Sapling bundle configuration
10/// suitable for use in fee and change calculation.
11pub trait BundleView<NoteRef> {
12    /// The type of inputs to the bundle.
13    type In: InputView<NoteRef>;
14    /// The type of inputs of the bundle.
15    type Out: OutputView;
16
17    /// Returns the type of the bundle
18    fn bundle_type(&self) -> BundleType;
19    /// Returns the inputs to the bundle.
20    fn inputs(&self) -> &[Self::In];
21    /// Returns the outputs of the bundle.
22    fn outputs(&self) -> &[Self::Out];
23}
24
25impl<'a, NoteRef, In: InputView<NoteRef>, Out: OutputView> BundleView<NoteRef>
26    for (BundleType, &'a [In], &'a [Out])
27{
28    type In = In;
29    type Out = Out;
30
31    fn bundle_type(&self) -> BundleType {
32        self.0
33    }
34
35    fn inputs(&self) -> &[In] {
36        self.1
37    }
38
39    fn outputs(&self) -> &[Out] {
40        self.2
41    }
42}
43
44/// A [`BundleView`] for the empty bundle with [`BundleType::DEFAULT`] bundle type.
45pub struct EmptyBundleView;
46
47impl<NoteRef> BundleView<NoteRef> for EmptyBundleView {
48    type In = Infallible;
49    type Out = Infallible;
50
51    fn bundle_type(&self) -> BundleType {
52        BundleType::DEFAULT
53    }
54
55    fn inputs(&self) -> &[Self::In] {
56        &[]
57    }
58
59    fn outputs(&self) -> &[Self::Out] {
60        &[]
61    }
62}
63
64/// A trait that provides a minimized view of a Sapling input suitable for use in
65/// fee and change calculation.
66pub trait InputView<NoteRef> {
67    /// An identifier for the input being spent.
68    fn note_id(&self) -> &NoteRef;
69    /// The value of the input being spent.
70    fn value(&self) -> Zatoshis;
71}
72
73impl<N> InputView<N> for Infallible {
74    fn note_id(&self) -> &N {
75        unreachable!()
76    }
77    fn value(&self) -> Zatoshis {
78        unreachable!()
79    }
80}
81
82// `SpendDescriptionInfo` does not contain a note identifier, so we can only implement
83// `InputView<()>`
84impl InputView<()> for SpendInfo {
85    fn note_id(&self) -> &() {
86        &()
87    }
88
89    fn value(&self) -> Zatoshis {
90        Zatoshis::try_from(self.value().inner())
91            .expect("An existing note to be spent must have a valid amount value.")
92    }
93}
94
95/// A trait that provides a minimized view of a Sapling output suitable for use in
96/// fee and change calculation.
97pub trait OutputView {
98    /// The value of the output being produced.
99    fn value(&self) -> Zatoshis;
100}
101
102impl OutputView for OutputInfo {
103    fn value(&self) -> Zatoshis {
104        Zatoshis::try_from(self.value().inner())
105            .expect("Output values should be checked at construction.")
106    }
107}
108
109impl OutputView for Infallible {
110    fn value(&self) -> Zatoshis {
111        unreachable!()
112    }
113}