radix_transactions/model/preparation/
traits.rs1use super::*;
2use crate::internal_prelude::*;
3use sbor::*;
4
5pub trait TransactionPayload:
6 ManifestEncode
7 + ManifestDecode
8 + ManifestCategorize
9 + for<'a> ManifestSborEnumVariantFor<
10 AnyTransaction,
11 OwnedVariant: ManifestDecode,
12 BorrowedVariant<'a>: ManifestEncode,
13 >
14{
15 type Prepared: PreparedTransaction<Raw = Self::Raw>;
16 type Raw: RawTransactionPayload;
17
18 fn discriminator() -> u8 {
19 Self::DISCRIMINATOR
20 }
21
22 fn to_raw(&self) -> Result<Self::Raw, EncodeError> {
23 Ok(manifest_encode(&self.as_encodable_variant())?.into())
24 }
25
26 fn from_raw(raw: &Self::Raw) -> Result<Self, DecodeError> {
27 Ok(Self::from_decoded_variant(manifest_decode(raw.as_ref())?))
28 }
29
30 fn from_payload_variant(payload_variant: Self::OwnedVariant) -> Self {
31 Self::from_decoded_variant(payload_variant)
32 }
33
34 fn prepare(&self, settings: &PreparationSettings) -> Result<Self::Prepared, PrepareError> {
35 Ok(Self::Prepared::prepare(&self.to_raw()?, settings)?)
36 }
37}
38
39pub trait TransactionPartialPrepare: ManifestEncode {
40 type Prepared: TransactionPreparableFromValue;
41
42 fn prepare_partial(
43 &self,
44 settings: &PreparationSettings,
45 ) -> Result<Self::Prepared, PrepareError> {
46 let payload = manifest_encode(self).unwrap();
47 let mut transaction_decoder = TransactionDecoder::new_partial(&payload, settings)?;
48 let prepared = Self::Prepared::prepare_from_value(&mut transaction_decoder)?;
49 transaction_decoder.check_complete()?;
50 Ok(prepared)
51 }
52}
53
54pub trait TransactionPreparableFromValueBody: HasSummary + Sized {
64 const ADDITIONAL_SUMMARY_LENGTH_AS_VALUE: usize = 1usize;
68
69 fn prepare_from_value_body(decoder: &mut TransactionDecoder) -> Result<Self, PrepareError>;
72
73 fn value_kind() -> ManifestValueKind;
74}
75
76impl<T: TransactionPreparableFromValueBody> TransactionPreparableFromValue for T {
77 fn prepare_from_value(decoder: &mut TransactionDecoder) -> Result<Self, PrepareError> {
78 decoder.read_and_check_value_kind(Self::value_kind())?;
79 let mut prepared = Self::prepare_from_value_body(decoder)?;
80 prepared.summary_mut().effective_length = prepared
82 .get_summary()
83 .effective_length
84 .checked_add(Self::ADDITIONAL_SUMMARY_LENGTH_AS_VALUE)
85 .ok_or(PrepareError::LengthOverflow)?;
86 Ok(prepared)
87 }
88}
89
90pub trait TransactionPreparableFromValue: HasSummary + Sized {
101 fn prepare_from_value(decoder: &mut TransactionDecoder) -> Result<Self, PrepareError>;
104}
105
106pub trait PreparedTransaction: Sized {
112 type Raw: RawTransactionPayload;
113
114 fn prepare_from_transaction_enum(
117 decoder: &mut TransactionDecoder,
118 ) -> Result<Self, PrepareError>;
119
120 fn prepare(raw: &Self::Raw, settings: &PreparationSettings) -> Result<Self, PrepareError> {
121 let payload = raw.as_slice();
122 let mut transaction_decoder = TransactionDecoder::new_transaction(
123 payload,
124 <Self::Raw as RawTransactionPayload>::KIND,
125 settings,
126 )?;
127 let prepared = Self::prepare_from_transaction_enum(&mut transaction_decoder)?;
128 transaction_decoder.check_complete()?;
129 Ok(prepared)
130 }
131}
132
133macro_rules! define_transaction_payload {
134 (
135 $transaction:ident,
136 $raw:ty,
137 $prepared:ident {
138 $($field_name:ident: $field_type:ty,)*
139 },
140 $discriminator:expr,
141 ) => {
142 #[derive(Debug, Clone, Eq, PartialEq)]
143 pub struct $prepared {
144 $(pub $field_name: $field_type,)*
145 pub summary: Summary,
146 }
147
148 impl TransactionPayload for $transaction {
149 type Prepared = $prepared;
150 type Raw = $raw;
151 }
152
153 impl HasSummary for $prepared {
154 fn get_summary(&self) -> &Summary {
155 &self.summary
156 }
157
158 fn summary_mut(&mut self) -> &mut Summary {
159 &mut self.summary
160 }
161 }
162
163 impl PreparedTransaction for $prepared {
164 type Raw = $raw;
165
166 fn prepare_from_transaction_enum(decoder: &mut TransactionDecoder) -> Result<Self, PrepareError> {
167 let (($($field_name,)*), summary) = ConcatenatedDigest::prepare_transaction_payload(
169 decoder,
170 $discriminator,
171 ExpectedHeaderKind::EnumWithValueKind,
172 )?;
173 Ok(Self {
174 $($field_name,)*
175 summary,
176 })
177 }
178 }
179
180 impl TransactionPreparableFromValueBody for $prepared {
181 const ADDITIONAL_SUMMARY_LENGTH_AS_VALUE: usize = 0;
185
186 fn prepare_from_value_body(decoder: &mut TransactionDecoder) -> Result<Self, PrepareError> {
187 let (($($field_name,)*), summary) =
189 ConcatenatedDigest::prepare_transaction_payload(
190 decoder,
191 $discriminator,
192 ExpectedHeaderKind::TupleNoValueKind,
193 )?;
194 Ok(Self {
195 $($field_name,)*
196 summary,
197 })
198 }
199
200 fn value_kind() -> ManifestValueKind {
201 ManifestValueKind::Tuple
202 }
203 }
204 };
205}
206
207pub(crate) use define_transaction_payload;
208
209pub trait RawTransactionPayload: AsRef<[u8]> + From<Vec<u8>> + Into<Vec<u8>> {
210 const KIND: TransactionPayloadKind;
211
212 fn as_slice(&self) -> &[u8] {
213 self.as_ref()
214 }
215}
216
217pub trait ValidatedTransactionPayload: IntoExecutable {}
218
219#[derive(Debug, Copy, Clone)]
220pub enum TransactionPayloadKind {
221 CompleteUserTransaction,
222 LedgerTransaction,
223 Other,
224}
225
226#[macro_export]
227macro_rules! define_raw_transaction_payload {
228 ($(#[$docs:meta])* $name:ident, $kind:expr) => {
229 #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Sbor)]
230 #[sbor(transparent)]
231 $(#[$docs])*
232 pub struct $name(Vec<u8>);
233
234 impl AsRef<[u8]> for $name {
235 fn as_ref(&self) -> &[u8] {
236 self.0.as_ref()
237 }
238 }
239
240 impl From<Vec<u8>> for $name {
241 fn from(value: Vec<u8>) -> Self {
242 Self(value)
243 }
244 }
245
246 impl From<$name> for Vec<u8> {
247 fn from(value: $name) -> Self {
248 value.0
249 }
250 }
251
252 impl RawTransactionPayload for $name {
253 const KIND: TransactionPayloadKind = $kind;
254 }
255
256 impl $name {
257 pub fn as_slice(&self) -> &[u8] {
258 self.0.as_slice()
259 }
260
261 pub fn len(&self) -> usize {
262 self.as_slice().len()
263 }
264
265 pub fn to_vec(self) -> Vec<u8> {
266 self.0
267 }
268
269 pub fn from_vec(vec: Vec<u8>) -> Self {
270 Self(vec)
271 }
272
273 pub fn from_slice(slice: impl AsRef<[u8]>) -> Self {
274 Self(slice.as_ref().into())
275 }
276
277 pub fn to_hex(&self) -> String {
278 hex::encode(self.as_slice())
279 }
280
281 pub fn from_hex(hex: impl AsRef<[u8]>) -> Result<Self, hex::FromHexError> {
282 Ok(Self(hex::decode(hex)?))
283 }
284 }
285 };
286}