radix_transactions/model/
concepts.rs

1use crate::internal_prelude::*;
2
3// This file is for concepts which are version-independent
4
5define_raw_transaction_payload!(RawTransactionIntent, TransactionPayloadKind::Other);
6define_wrapped_hash!(
7    /// A hash of the primary intent of a transaction, used as the transaction id.
8    /// The engine guarantees each intent hash can only be committed once.
9    TransactionIntentHash
10);
11
12pub trait HasTransactionIntentHash {
13    fn transaction_intent_hash(&self) -> TransactionIntentHash;
14}
15
16define_raw_transaction_payload!(RawSignedTransactionIntent, TransactionPayloadKind::Other);
17define_wrapped_hash!(SignedTransactionIntentHash);
18
19pub trait HasSignedTransactionIntentHash {
20    fn signed_transaction_intent_hash(&self) -> SignedTransactionIntentHash;
21}
22
23define_raw_transaction_payload!(
24    RawNotarizedTransaction,
25    TransactionPayloadKind::CompleteUserTransaction
26);
27define_wrapped_hash!(NotarizedTransactionHash);
28
29impl RawNotarizedTransaction {
30    pub fn into_typed(&self) -> Result<UserTransaction, DecodeError> {
31        manifest_decode(self.as_slice())
32    }
33
34    pub fn prepare(
35        &self,
36        settings: &PreparationSettings,
37    ) -> Result<PreparedUserTransaction, PrepareError> {
38        PreparedUserTransaction::prepare(self, settings)
39    }
40
41    pub fn validate(
42        &self,
43        validator: &TransactionValidator,
44    ) -> Result<ValidatedUserTransaction, TransactionValidationError> {
45        self.prepare(validator.preparation_settings())?
46            .validate(validator)
47    }
48
49    pub fn prepare_as_known_v2(
50        &self,
51        settings: &PreparationSettings,
52    ) -> Result<PreparedNotarizedTransactionV2, PrepareError> {
53        PreparedNotarizedTransactionV2::prepare(self, settings)
54    }
55
56    pub fn validate_as_known_v2(
57        &self,
58        validator: &TransactionValidator,
59    ) -> Result<ValidatedNotarizedTransactionV2, TransactionValidationError> {
60        self.prepare_as_known_v2(validator.preparation_settings())?
61            .validate(validator)
62    }
63}
64
65pub trait ResolveAsRawNotarizedTransaction {
66    type Intermediate: AsRef<RawNotarizedTransaction>;
67
68    fn resolve_raw_notarized_transaction(self) -> Self::Intermediate;
69}
70
71impl AsRef<RawNotarizedTransaction> for RawNotarizedTransaction {
72    fn as_ref(&self) -> &RawNotarizedTransaction {
73        self
74    }
75}
76
77impl<T: AsRef<RawNotarizedTransaction>> ResolveAsRawNotarizedTransaction for T {
78    type Intermediate = Self;
79
80    fn resolve_raw_notarized_transaction(self) -> Self::Intermediate {
81        self
82    }
83}
84
85impl IntoExecutable for RawNotarizedTransaction {
86    type Error = TransactionValidationError;
87
88    fn into_executable(
89        self,
90        validator: &TransactionValidator,
91    ) -> Result<ExecutableTransaction, Self::Error> {
92        let executable = self.validate(validator)?.create_executable();
93        Ok(executable)
94    }
95}
96
97pub trait HasNotarizedTransactionHash {
98    fn notarized_transaction_hash(&self) -> NotarizedTransactionHash;
99}
100
101pub trait HasNonRootSubintentHashes {
102    /// ## Validity Note
103    /// Preparable but invalid transactions may contain non-root subintents with duplicate [`SubintentHash`]es.
104    /// Therefore we return a `Vec` instead of an `IndexSet` here.
105    fn non_root_subintent_hashes(&self) -> Vec<SubintentHash>;
106}
107
108define_raw_transaction_payload!(RawSubintent, TransactionPayloadKind::Other);
109define_wrapped_hash!(
110    /// A hash of the subintent.
111    /// The engine guarantees each intent hash can only be committed once.
112    SubintentHash
113);
114
115pub trait HasSubintentHash {
116    fn subintent_hash(&self) -> SubintentHash;
117}
118
119// There are no associated hashes for these things, because they don't need them.
120// A solver can work out their own passing strategy
121define_raw_transaction_payload!(RawPartialTransaction, TransactionPayloadKind::Other);
122define_raw_transaction_payload!(RawSignedPartialTransaction, TransactionPayloadKind::Other);
123define_raw_transaction_payload!(RawPreviewTransaction, TransactionPayloadKind::Other);
124
125/// Note - Because transaction hashes do _not_ have a reserved first byte,
126/// we can't encode them to bech32m unless we know their type.
127///
128/// Therefore this type has to be an enum to ensure we maintain the knowledge
129/// of the underlying intent type, to allow the intent hash to be bech32m encoded.
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Sbor)]
131pub enum IntentHash {
132    Transaction(TransactionIntentHash),
133    Subintent(SubintentHash),
134}
135
136impl From<TransactionIntentHash> for IntentHash {
137    fn from(value: TransactionIntentHash) -> Self {
138        Self::Transaction(value)
139    }
140}
141
142impl From<SubintentHash> for IntentHash {
143    fn from(value: SubintentHash) -> Self {
144        Self::Subintent(value)
145    }
146}
147
148impl IntentHash {
149    pub fn is_for_subintent(&self) -> bool {
150        match self {
151            IntentHash::Transaction(_) => false,
152            IntentHash::Subintent(_) => true,
153        }
154    }
155
156    pub fn as_hash(&self) -> &Hash {
157        match self {
158            IntentHash::Transaction(hash) => hash.as_hash(),
159            IntentHash::Subintent(hash) => hash.as_hash(),
160        }
161    }
162
163    pub fn into_hash(self) -> Hash {
164        match self {
165            IntentHash::Transaction(hash) => hash.into_hash(),
166            IntentHash::Subintent(hash) => hash.into_hash(),
167        }
168    }
169
170    pub fn to_nullification(self, expiry_epoch: Epoch) -> IntentHashNullification {
171        match self {
172            IntentHash::Transaction(tx_intent_hash) => IntentHashNullification::TransactionIntent {
173                intent_hash: tx_intent_hash,
174                expiry_epoch,
175            },
176            IntentHash::Subintent(subintent_hash) => IntentHashNullification::Subintent {
177                intent_hash: subintent_hash,
178                expiry_epoch,
179            },
180        }
181    }
182}
183
184define_raw_transaction_payload!(RawSystemTransaction, TransactionPayloadKind::Other);
185define_wrapped_hash!(SystemTransactionHash);
186
187pub trait HasSystemTransactionHash {
188    fn system_transaction_hash(&self) -> SystemTransactionHash;
189}
190
191define_raw_transaction_payload!(RawFlashTransaction, TransactionPayloadKind::Other);
192define_wrapped_hash!(FlashTransactionHash);
193
194pub trait HasFlashTransactionHash {
195    fn flash_transaction_hash(&self) -> FlashTransactionHash;
196}