1use std::{
20 fmt::{self, Debug},
21 str::FromStr,
22};
23
24#[cfg(feature = "async")]
25use darkfi_serial::async_trait;
26use darkfi_serial::{SerialDecodable, SerialEncodable};
27
28use super::{
29 crypto::{ContractId, SecretKey},
30 ContractError, GenericResult,
31};
32use crate::crypto::{DAO_CONTRACT_ID, DEPLOYOOOR_CONTRACT_ID, MONEY_CONTRACT_ID};
33
34#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, SerialEncodable, SerialDecodable)]
35pub struct TransactionHash(pub [u8; 32]);
37
38impl TransactionHash {
39 pub fn new(data: [u8; 32]) -> Self {
40 Self(data)
41 }
42
43 pub fn none() -> Self {
44 Self([0; 32])
45 }
46
47 #[inline]
48 pub fn inner(&self) -> &[u8; 32] {
49 &self.0
50 }
51
52 pub fn as_string(&self) -> String {
53 blake3::Hash::from_bytes(self.0).to_string()
54 }
55}
56
57impl FromStr for TransactionHash {
58 type Err = ContractError;
59
60 fn from_str(tx_hash_str: &str) -> GenericResult<Self> {
61 let Ok(hash) = blake3::Hash::from_str(tx_hash_str) else {
62 return Err(ContractError::HexFmtErr);
63 };
64 Ok(Self(*hash.as_bytes()))
65 }
66}
67
68impl fmt::Display for TransactionHash {
69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70 write!(f, "{}", self.as_string())
71 }
72}
73
74#[derive(Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
78pub struct ContractCall {
79 pub contract_id: ContractId,
81 pub data: Vec<u8>,
83}
84impl ContractCall {
87 pub fn is_money_fee(&self) -> bool {
89 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x00)
90 }
91
92 pub fn is_money_genesis_mint(&self) -> bool {
94 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x01)
95 }
96
97 pub fn is_money_pow_reward(&self) -> bool {
99 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x02)
100 }
101
102 pub fn is_money_transfer(&self) -> bool {
104 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x03)
105 }
106
107 pub fn is_money_otc_swap(&self) -> bool {
109 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x04)
110 }
111
112 pub fn is_money_auth_token_mint(&self) -> bool {
114 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x05)
115 }
116
117 pub fn is_money_auth_token_freeze(&self) -> bool {
119 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x06)
120 }
121
122 pub fn is_money_token_mint(&self) -> bool {
124 self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x07)
125 }
126
127 pub fn is_dao_mint(&self) -> bool {
129 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x00)
130 }
131
132 pub fn is_dao_propose(&self) -> bool {
134 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x01)
135 }
136
137 pub fn is_dao_vote(&self) -> bool {
139 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x02)
140 }
141
142 pub fn is_dao_exec(&self) -> bool {
144 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x03)
145 }
146
147 pub fn is_dao_auth_money_transfer(&self) -> bool {
149 self.matches_contract_call_type(*DAO_CONTRACT_ID, 0x04)
150 }
151
152 pub fn is_deployment(&self) -> bool {
154 self.matches_contract_call_type(*DEPLOYOOOR_CONTRACT_ID, 0x00)
155 }
156
157 pub fn matches_contract_call_type(&self, contract_id: ContractId, func_code: u8) -> bool {
159 !self.data.is_empty() && self.contract_id == contract_id && self.data[0] == func_code
160 }
161}
162
163impl Debug for ContractCall {
165 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166 write!(f, "ContractCall(id={:?}", self.contract_id.inner())?;
167 let calldata = &self.data;
168 if !calldata.is_empty() {
169 write!(f, ", function_code={}", calldata[0])?;
170 }
171 write!(f, ")")
172 }
173}
174
175#[derive(Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
180pub struct ContractCallImport {
181 call: ContractCall,
183 proofs: Vec<Vec<u8>>,
185 secrets: Vec<SecretKey>,
187}
188
189impl ContractCallImport {
190 pub fn new(call: ContractCall, proofs: Vec<Vec<u8>>, secrets: Vec<SecretKey>) -> Self {
192 Self { call, proofs, secrets }
193 }
194
195 pub fn call(&self) -> &ContractCall {
197 &self.call
198 }
199
200 pub fn proofs(&self) -> &[Vec<u8>] {
202 &self.proofs
203 }
204
205 pub fn secrets(&self) -> &[SecretKey] {
207 &self.secrets
208 }
209}