radix_transactions/model/preparation/
decoder.rs1use crate::internal_prelude::*;
2use sbor::*;
3
4#[derive(Debug, Clone, Eq, PartialEq)]
5pub enum ValueType {
6 Blob,
7 Subintent,
8 ChildSubintentSpecifier,
9 SubintentSignatureBatches,
10 }
12
13#[derive(Debug, Clone, Eq, PartialEq)]
14pub enum PrepareError {
15 TransactionTypeNotSupported,
16 TransactionTooLarge,
17 DecodeError(DecodeError),
18 EncodeError(EncodeError),
19 TooManyValues {
20 value_type: ValueType,
21 actual: usize,
22 max: usize,
23 },
24 LengthOverflow,
25 UnexpectedTransactionDiscriminator {
26 actual: Option<u8>,
27 },
28}
29
30impl From<DecodeError> for PrepareError {
31 fn from(value: DecodeError) -> Self {
32 Self::DecodeError(value)
33 }
34}
35
36impl From<EncodeError> for PrepareError {
37 fn from(value: EncodeError) -> Self {
38 Self::EncodeError(value)
39 }
40}
41
42pub type PreparationSettings = PreparationSettingsV1;
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Sbor)]
45pub struct PreparationSettingsV1 {
46 pub v2_transactions_permitted: bool,
47 pub max_user_payload_length: usize,
48 pub max_ledger_payload_length: usize,
49 pub max_child_subintents_per_intent: usize,
50 pub max_subintents_per_transaction: usize,
51 pub max_blobs: usize,
52}
53
54static LATEST_PREPARATION_SETTINGS: PreparationSettings = PreparationSettings::latest();
55
56impl PreparationSettings {
57 pub const fn latest() -> Self {
58 Self::cuttlefish()
59 }
60
61 pub const fn babylon() -> Self {
62 let max_user_payload_length = 1024 * 1024;
63 Self {
64 v2_transactions_permitted: false,
65 max_user_payload_length,
66 max_ledger_payload_length: max_user_payload_length + 10,
67 max_child_subintents_per_intent: 0,
68 max_subintents_per_transaction: 0,
69 max_blobs: 64,
70 }
71 }
72
73 pub const fn cuttlefish() -> Self {
74 Self {
75 v2_transactions_permitted: true,
76 max_child_subintents_per_intent: 32,
77 max_subintents_per_transaction: 32,
78 ..Self::babylon()
79 }
80 }
81
82 pub fn latest_ref() -> &'static Self {
83 &LATEST_PREPARATION_SETTINGS
84 }
85
86 fn check_len(
87 &self,
88 kind: TransactionPayloadKind,
89 payload_len: usize,
90 ) -> Result<(), PrepareError> {
91 match kind {
92 TransactionPayloadKind::CompleteUserTransaction => {
93 if payload_len > self.max_user_payload_length {
94 return Err(PrepareError::TransactionTooLarge);
95 }
96 }
97 TransactionPayloadKind::LedgerTransaction => {
98 if payload_len > self.max_ledger_payload_length {
99 return Err(PrepareError::TransactionTooLarge);
100 }
101 }
102 TransactionPayloadKind::Other => {
103 }
105 }
106 Ok(())
107 }
108}
109
110pub struct TransactionDecoder<'a> {
111 decoder: ManifestDecoder<'a>,
112 settings: &'a PreparationSettings,
113}
114
115impl<'a> TransactionDecoder<'a> {
116 pub fn new_transaction(
117 payload: &'a [u8],
118 kind: TransactionPayloadKind,
119 settings: &'a PreparationSettings,
120 ) -> Result<Self, PrepareError> {
121 settings.check_len(kind, payload.len())?;
122 let mut decoder = ManifestDecoder::new(payload, MANIFEST_SBOR_V1_MAX_DEPTH);
123 decoder.read_and_check_payload_prefix(MANIFEST_SBOR_V1_PAYLOAD_PREFIX)?;
124 Ok(Self { decoder, settings })
125 }
126
127 pub fn new_partial(
128 payload: &'a [u8],
129 settings: &'a PreparationSettings,
130 ) -> Result<Self, PrepareError> {
131 let mut decoder = ManifestDecoder::new(payload, MANIFEST_SBOR_V1_MAX_DEPTH);
132 decoder.read_and_check_payload_prefix(MANIFEST_SBOR_V1_PAYLOAD_PREFIX)?;
133 Ok(Self { decoder, settings })
134 }
135
136 pub fn settings(&self) -> &PreparationSettings {
137 self.settings
138 }
139
140 pub fn track_stack_depth_increase(&mut self) -> Result<(), PrepareError> {
142 Ok(self.decoder.track_stack_depth_increase()?)
143 }
144
145 pub fn read_header(
146 &mut self,
147 header: ExpectedTupleHeader,
148 expected_length: usize,
149 ) -> Result<(), PrepareError> {
150 match header {
151 ExpectedTupleHeader::EnumNoValueKind { discriminator } => {
152 self.decoder.read_expected_discriminator(discriminator)?;
153 }
154 ExpectedTupleHeader::EnumWithValueKind { discriminator } => {
155 self.read_and_check_value_kind(ValueKind::Enum)?;
156 self.decoder.read_expected_discriminator(discriminator)?;
157 }
158 ExpectedTupleHeader::TupleWithValueKind => {
159 self.read_and_check_value_kind(ValueKind::Tuple)?;
160 }
161 ExpectedTupleHeader::TupleNoValueKind => {}
162 }
163 self.decoder.read_and_check_size(expected_length)?;
164 Ok(())
165 }
166
167 pub fn read_enum_header(&mut self) -> Result<(u8, usize), PrepareError> {
168 self.read_and_check_value_kind(ValueKind::Enum)?;
169 let discriminator = self.decoder.read_discriminator()?;
170 let length = self.decoder.read_size()?;
171 Ok((discriminator, length))
172 }
173
174 pub fn read_array_header(
175 &mut self,
176 element_value_kind: ManifestValueKind,
177 ) -> Result<usize, PrepareError> {
178 self.read_and_check_value_kind(ValueKind::Array)?;
179 self.read_array_header_without_value_kind(element_value_kind)
180 }
181
182 pub fn read_array_header_without_value_kind(
183 &mut self,
184 element_value_kind: ManifestValueKind,
185 ) -> Result<usize, PrepareError> {
186 self.read_and_check_value_kind(element_value_kind)?;
187 Ok(self.decoder.read_size()?)
188 }
189
190 pub fn read_and_check_value_kind(
191 &mut self,
192 value_kind: ManifestValueKind,
193 ) -> Result<(), PrepareError> {
194 self.decoder.read_and_check_value_kind(value_kind)?;
195 Ok(())
196 }
197
198 pub fn track_stack_depth_decrease(&mut self) -> Result<(), PrepareError> {
200 Ok(self.decoder.track_stack_depth_decrease()?)
201 }
202
203 pub fn decode<T: ManifestDecode>(&mut self) -> Result<T, PrepareError> {
204 Ok(self.decoder.decode()?)
205 }
206
207 pub fn decode_deeper_body_with_value_kind<T: ManifestDecode>(
208 &mut self,
209 value_kind: ManifestValueKind,
210 ) -> Result<T, PrepareError> {
211 Ok(self
212 .decoder
213 .decode_deeper_body_with_value_kind(value_kind)?)
214 }
215
216 pub fn get_offset(&self) -> usize {
217 self.decoder.get_offset()
218 }
219
220 pub fn get_slice_with_valid_bounds(&self, start_offset: usize, end_offset: usize) -> &[u8] {
221 &self.decoder.get_input_slice()[start_offset..end_offset]
222 }
223
224 pub fn get_input_slice(&self) -> &[u8] {
225 self.decoder.get_input_slice()
226 }
227
228 pub fn check_complete(self) -> Result<(), PrepareError> {
229 self.decoder.check_end()?;
230 Ok(())
231 }
232}