Skip to main content

wagyu_model/
transaction.rs

1use crate::address::{Address, AddressError};
2use crate::amount::AmountError;
3use crate::extended_private_key::ExtendedPrivateKeyError;
4use crate::format::Format;
5use crate::private_key::{PrivateKey, PrivateKeyError};
6use crate::public_key::PublicKey;
7
8use rlp;
9use std::{
10    fmt::{Debug, Display},
11    hash::Hash,
12};
13
14/// The interface for a generic transaction id.
15pub trait TransactionId: Clone + Debug + Display + Send + Sync + 'static + Eq + Ord + Sized + Hash {}
16
17/// The interface for a generic transactions.
18pub trait Transaction: Clone + Send + Sync + 'static {
19    type Address: Address;
20    type Format: Format;
21    type PrivateKey: PrivateKey;
22    type PublicKey: PublicKey;
23    type TransactionId: TransactionId;
24    type TransactionParameters;
25
26    /// Returns an unsigned transaction given the transaction parameters.
27    fn new(parameters: &Self::TransactionParameters) -> Result<Self, TransactionError>;
28
29    /// Returns a signed transaction given the private key of the sender.
30    fn sign(&self, private_key: &Self::PrivateKey) -> Result<Self, TransactionError>;
31
32    /// Returns a transaction given the transaction bytes.
33    fn from_transaction_bytes(transaction: &Vec<u8>) -> Result<Self, TransactionError>;
34
35    /// Returns the transaction in bytes.
36    fn to_transaction_bytes(&self) -> Result<Vec<u8>, TransactionError>;
37
38    /// Returns the transaction id.
39    fn to_transaction_id(&self) -> Result<Self::TransactionId, TransactionError>;
40}
41
42#[derive(Debug, Fail)]
43pub enum TransactionError {
44    #[fail(display = "{}", _0)]
45    AddressError(AddressError),
46
47    #[fail(display = "{}", _0)]
48    AmountError(AmountError),
49
50    #[fail(display = "witnesses have a conflicting anchor")]
51    ConflictingWitnessAnchors(),
52
53    #[fail(display = "{}: {}", _0, _1)]
54    Crate(&'static str, String),
55
56    #[fail(display = "{}", _0)]
57    ExtendedPrivateKeyError(ExtendedPrivateKeyError),
58
59    #[fail(display = "Failed note decryption for enc_cyphertext: {}", _0)]
60    FailedNoteDecryption(String),
61
62    #[fail(display = "invalid binding signature for the transaction")]
63    InvalidBindingSig(),
64
65    #[fail(display = "invalid chain id {:?}", _0)]
66    InvalidChainId(u8),
67
68    #[fail(display = "invalid ephemeral key {}", _0)]
69    InvalidEphemeralKey(String),
70
71    #[fail(display = "insufficient information to craft transaction. missing: {}", _0)]
72    InvalidInputs(String),
73
74    #[fail(display = "invalid output address: {}", _0)]
75    InvalidOutputAddress(String),
76
77    #[fail(display = "invalid ouptut description for address: {}", _0)]
78    InvalidOutputDescription(String),
79
80    #[fail(display = "invalid transaction RLP length: expected - 9, found - {:?}", _0)]
81    InvalidRlpLength(usize),
82
83    #[fail(display = "invalid script pub key for format: {}", _0)]
84    InvalidScriptPubKey(String),
85
86    #[fail(display = "invalid segwit flag: {:?}", _0)]
87    InvalidSegwitFlag(usize),
88
89    #[fail(display = "invalid spend description for address")]
90    InvalidSpendDescription,
91
92    #[fail(display = "invalid transaction id {:?}", _0)]
93    InvalidTransactionId(usize),
94
95    #[fail(display = "invalid transaction - either both sender and signature should be present, or neither")]
96    InvalidTransactionState,
97
98    #[fail(display = "invalid variable size integer: {:?}", _0)]
99    InvalidVariableSizeInteger(usize),
100
101    #[fail(display = "{}", _0)]
102    Message(String),
103
104    #[fail(display = "missing diversifier, check that the address is a Sapling address")]
105    MissingDiversifier,
106
107    #[fail(display = "missing outpoint address")]
108    MissingOutpointAddress,
109
110    #[fail(display = "missing outpoint amount")]
111    MissingOutpointAmount,
112
113    #[fail(display = "missing outpoint script public key")]
114    MissingOutpointScriptPublicKey,
115
116    #[fail(display = "missing output parameters")]
117    MissingOutputParameters,
118
119    #[fail(display = "missing spend description")]
120    MissingSpendDescription,
121
122    #[fail(display = "missing spend parameters")]
123    MissingSpendParameters,
124
125    #[fail(display = "Null Error {:?}", _0)]
126    NullError(()),
127
128    #[fail(display = "{}", _0)]
129    PrivateKeyError(PrivateKeyError),
130
131    #[fail(display = "Joinsplits are not supported")]
132    UnsupportedJoinsplits,
133
134    #[fail(display = "unsupported preimage operation on address format of {}", _0)]
135    UnsupportedPreimage(String),
136}
137
138impl From<&'static str> for TransactionError {
139    fn from(msg: &'static str) -> Self {
140        TransactionError::Message(msg.into())
141    }
142}
143
144impl From<()> for TransactionError {
145    fn from(error: ()) -> Self {
146        TransactionError::NullError(error)
147    }
148}
149
150impl From<AddressError> for TransactionError {
151    fn from(error: AddressError) -> Self {
152        TransactionError::AddressError(error)
153    }
154}
155
156impl From<AmountError> for TransactionError {
157    fn from(error: AmountError) -> Self {
158        TransactionError::AmountError(error)
159    }
160}
161
162impl From<base58::FromBase58Error> for TransactionError {
163    fn from(error: base58::FromBase58Error) -> Self {
164        TransactionError::Crate("base58", format!("{:?}", error))
165    }
166}
167
168impl From<base58_monero::base58::Error> for TransactionError {
169    fn from(error: base58_monero::base58::Error) -> Self {
170        TransactionError::Crate("base58_monero", format!("{:?}", error))
171    }
172}
173
174impl From<bech32::Error> for TransactionError {
175    fn from(error: bech32::Error) -> Self {
176        TransactionError::Crate("bech32", format!("{:?}", error))
177    }
178}
179
180impl From<ExtendedPrivateKeyError> for TransactionError {
181    fn from(error: ExtendedPrivateKeyError) -> Self {
182        TransactionError::ExtendedPrivateKeyError(error)
183    }
184}
185
186impl From<ff::PrimeFieldDecodingError> for TransactionError {
187    fn from(error: ff::PrimeFieldDecodingError) -> Self {
188        TransactionError::Crate("ff", format!("{:?}", error))
189    }
190}
191
192impl From<hex::FromHexError> for TransactionError {
193    fn from(error: hex::FromHexError) -> Self {
194        TransactionError::Crate("hex", format!("{:?}", error))
195    }
196}
197
198impl From<PrivateKeyError> for TransactionError {
199    fn from(error: PrivateKeyError) -> Self {
200        TransactionError::PrivateKeyError(error)
201    }
202}
203
204impl From<rlp::DecoderError> for TransactionError {
205    fn from(error: rlp::DecoderError) -> Self {
206        TransactionError::Crate("rlp", format!("{:?}", error))
207    }
208}
209
210impl From<secp256k1::Error> for TransactionError {
211    fn from(error: secp256k1::Error) -> Self {
212        TransactionError::Crate("secp256k1", format!("{:?}", error))
213    }
214}
215
216impl From<serde_json::error::Error> for TransactionError {
217    fn from(error: serde_json::error::Error) -> Self {
218        TransactionError::Crate("serde_json", format!("{:?}", error))
219    }
220}
221
222impl From<std::io::Error> for TransactionError {
223    fn from(error: std::io::Error) -> Self {
224        TransactionError::Crate("std::io", format!("{:?}", error))
225    }
226}
227
228impl From<std::str::ParseBoolError> for TransactionError {
229    fn from(error: std::str::ParseBoolError) -> Self {
230        TransactionError::Crate("std::str", format!("{:?}", error))
231    }
232}
233
234impl From<std::num::ParseIntError> for TransactionError {
235    fn from(error: std::num::ParseIntError) -> Self {
236        TransactionError::Crate("std::num", format!("{:?}", error))
237    }
238}
239
240impl From<uint::FromDecStrErr> for TransactionError {
241    fn from(error: uint::FromDecStrErr) -> Self {
242        TransactionError::Crate("uint", format!("{:?}", error))
243    }
244}