anychain_core/
transaction.rs1use {
2 crate::{
3 address::{Address, AddressError},
4 amount::AmountError,
5 format::Format,
6 no_std::{
7 fmt::{Debug, Display},
8 hash::Hash,
9 String, Vec,
10 },
11 public_key::PublicKey,
12 utilities::crypto::keccak256,
13 },
14 thiserror::Error,
15};
16
17pub fn func_selector(func_signature: &str) -> [u8; 4] {
21 let mut func_id = [0u8; 4];
22 func_id.clone_from_slice(&keccak256(func_signature.as_bytes())[..4]);
23 func_id
24}
25
26pub trait TransactionId:
28 Clone + Debug + Display + Send + Sync + 'static + Eq + Sized + Hash
29{
30}
31
32pub trait Transaction: Clone + Send + Sync + 'static {
34 type Address: Address;
35 type Format: Format;
36 type PublicKey: PublicKey;
37 type TransactionId: TransactionId;
38 type TransactionParameters;
39
40 fn new(parameters: &Self::TransactionParameters) -> Result<Self, TransactionError>;
42
43 fn sign(&mut self, signature: Vec<u8>, recid: u8) -> Result<Vec<u8>, TransactionError>;
45
46 fn from_bytes(transaction: &[u8]) -> Result<Self, TransactionError>;
48
49 fn to_bytes(&self) -> Result<Vec<u8>, TransactionError>;
51
52 fn to_transaction_id(&self) -> Result<Self::TransactionId, TransactionError>;
54}
55
56#[derive(Debug, Error)]
57pub enum TransactionError {
58 #[error("{0}")]
59 AddressError(#[from] AddressError),
60
61 #[error("{0}")]
62 AmountError(#[from] AmountError),
63
64 #[error("witnesses have a conflicting anchor")]
65 ConflictingWitnessAnchors(),
66
67 #[error("{0}: {1}")]
68 Crate(&'static str, String),
69
70 #[error("Failed note decryption for enc_cyphertext: {0}")]
71 FailedNoteDecryption(String),
72
73 #[error("invalid binding signature for the transaction")]
74 InvalidBindingSig(),
75
76 #[error("invalid chain id {0}")]
77 InvalidChainId(u8),
78
79 #[error("invalid ephemeral key {0}")]
80 InvalidEphemeralKey(String),
81
82 #[error("insufficient information to craft transaction. missing: {0}")]
83 InvalidInputs(String),
84
85 #[error("invalid output address: {0}")]
86 InvalidOutputAddress(String),
87
88 #[error("invalid ouptut description for address: {0}")]
89 InvalidOutputDescription(String),
90
91 #[error("invalid transaction RLP length: expected - 9, found - {0}")]
92 InvalidRlpLength(usize),
93
94 #[error("invalid script pub key for format: {0}")]
95 InvalidScriptPubKey(String),
96
97 #[error("invalid segwit flag: {0}")]
98 InvalidSegwitFlag(usize),
99
100 #[error("invalid spend description for address")]
101 InvalidSpendDescription,
102
103 #[error("invalid transaction id {0}")]
104 InvalidTransactionId(usize),
105
106 #[error(
107 "invalid transaction - either both sender and signature should be present, or neither"
108 )]
109 InvalidTransactionState,
110
111 #[error("invalid variable size integer: {0}")]
112 InvalidVariableSizeInteger(usize),
113
114 #[error("{0}")]
115 Message(String),
116
117 #[error("missing diversifier, check that the address is a Sapling address")]
118 MissingDiversifier,
119
120 #[error("missing outpoint address")]
121 MissingOutpointAddress,
122
123 #[error("missing outpoint amount")]
124 MissingOutpointAmount,
125
126 #[error("missing outpoint script public key")]
127 MissingOutpointScriptPublicKey,
128
129 #[error("missing output parameters")]
130 MissingOutputParameters,
131
132 #[error("missing spend description")]
133 MissingSpendDescription,
134
135 #[error("missing spend parameters")]
136 MissingSpendParameters,
137
138 #[error("missing signature")]
139 MissingSignature,
140
141 #[error("Null Error")]
142 NullError(()),
143
144 #[error("Joinsplits are not supported")]
145 UnsupportedJoinsplits,
146
147 #[error("unsupported preimage operation on address format of {0}")]
148 UnsupportedPreimage(String),
149
150 #[error("Reaching end of Ripple SerializedType 'Object'")]
151 EndOfObject,
152
153 #[error("Reaching end of Ripple SerializedType 'Array'")]
154 EndOfArray,
155}
156
157impl From<crate::no_std::io::Error> for TransactionError {
158 fn from(error: crate::no_std::io::Error) -> Self {
159 TransactionError::Crate("crate::no_std::io", format!("{:?}", error))
160 }
161}
162
163impl From<&'static str> for TransactionError {
164 fn from(msg: &'static str) -> Self {
165 TransactionError::Message(msg.into())
166 }
167}
168
169impl From<()> for TransactionError {
170 fn from(error: ()) -> Self {
171 TransactionError::NullError(error)
172 }
173}
174
175impl From<base58::FromBase58Error> for TransactionError {
176 fn from(error: base58::FromBase58Error) -> Self {
177 TransactionError::Crate("base58", format!("{:?}", error))
178 }
179}
180
181impl From<bech32::Error> for TransactionError {
182 fn from(error: bech32::Error) -> Self {
183 TransactionError::Crate("bech32", format!("{:?}", error))
184 }
185}
186
187impl From<core::num::ParseIntError> for TransactionError {
188 fn from(error: core::num::ParseIntError) -> Self {
189 TransactionError::Crate("core::num", format!("{:?}", error))
190 }
191}
192
193impl From<core::str::ParseBoolError> for TransactionError {
194 fn from(error: core::str::ParseBoolError) -> Self {
195 TransactionError::Crate("core::str", format!("{:?}", error))
196 }
197}
198
199impl From<hex::FromHexError> for TransactionError {
200 fn from(error: hex::FromHexError) -> Self {
201 TransactionError::Crate("hex", format!("{:?}", error))
202 }
203}
204
205impl From<serde_json::error::Error> for TransactionError {
218 fn from(error: serde_json::error::Error) -> Self {
219 TransactionError::Crate("serde_json", format!("{:?}", error))
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use crate::func_selector;
226
227 #[test]
228 fn test_func_selector() {
229 let selector = func_selector("transfer(address,uint256)");
230 assert_eq!("a9059cbb", hex::encode(selector));
231 }
232}