radix_transactions/manifest/
manifest_traits.rs1use crate::internal_prelude::*;
2
3pub trait BuildableManifest:
4 TypedReadableManifest
5 + Into<AnyManifest>
6 + TryFrom<AnyManifest, Error = ()>
7 + ManifestEncode
8 + Default
9 + Eq
10 + Debug
11{
12 fn builder() -> ManifestBuilder<Self> {
13 ManifestBuilder::<Self>::new_typed()
14 }
15
16 fn add_instruction(&mut self, instruction: Self::Instruction);
17 fn add_blob(&mut self, hash: Hash, content: Vec<u8>);
18 fn set_names(&mut self, names: KnownManifestObjectNames);
19 fn set_names_if_known(&mut self, names: impl Into<ManifestObjectNames>) {
20 match names.into() {
21 ManifestObjectNames::Unknown => {}
22 ManifestObjectNames::Known(known_names) => self.set_names(known_names),
23 };
24 }
25 fn add_child_subintent(&mut self, _hash: SubintentHash) -> Result<(), ManifestBuildError> {
26 Err(ManifestBuildError::ChildSubintentsUnsupportedByManifestType)
27 }
28 fn add_preallocated_address(
29 &mut self,
30 _preallocated: PreAllocatedAddress,
31 ) -> Result<(), ManifestBuildError> {
32 Err(ManifestBuildError::PreallocatedAddressesUnsupportedByManifestType)
33 }
34 fn preallocation_count(&self) -> usize {
35 0
36 }
37
38 fn default_test_execution_config_type(&self) -> DefaultTestExecutionConfigType;
39 fn into_executable_with_proofs(
40 self,
41 nonce: u32,
42 initial_proofs: BTreeSet<NonFungibleGlobalId>,
43 validator: &TransactionValidator,
44 ) -> Result<ExecutableTransaction, String>;
45
46 fn to_raw(self) -> Result<RawManifest, EncodeError> {
47 let any_manifest: AnyManifest = self.into();
48 any_manifest.to_raw()
49 }
50
51 fn from_raw(raw: &RawManifest) -> Result<Self, String> {
52 let any_manifest = AnyManifest::from_raw(raw)
53 .map_err(|err| format!("Could not decode as `AnyManifest`: {err:?}"))?;
54 Self::try_from(any_manifest)
55 .map_err(|()| format!("Encoded manifest was not of the correct type"))
56 }
57
58 fn decode_arbitrary(bytes: impl AsRef<[u8]>) -> Result<Self, String> {
59 let any_manifest = AnyManifest::attempt_decode_from_arbitrary_payload(bytes.as_ref())?;
60 Self::try_from(any_manifest)
61 .map_err(|()| format!("Encoded manifest was not of the correct type"))
62 }
63}
64
65#[derive(Debug, Copy, Clone, PartialEq, Eq)]
66pub enum DefaultTestExecutionConfigType {
67 Notarized,
68 System,
69 Test,
70}
71
72#[derive(Debug, Copy, Clone, PartialEq, Eq)]
73pub enum ManifestBuildError {
74 DuplicateChildSubintentHash,
75 ChildSubintentsUnsupportedByManifestType,
76 PreallocatedAddressesUnsupportedByManifestType,
77}
78
79pub trait BuildableManifestSupportingChildren: BuildableManifest {}
82
83pub trait BuildableManifestSupportingPreallocatedAddresses: BuildableManifest {}
86
87pub trait BuildableManifestWithParent: BuildableManifest {}
89
90pub trait TypedReadableManifest: ReadableManifestBase {
91 type Instruction: ManifestInstructionSet;
92 fn get_typed_instructions(&self) -> &[Self::Instruction];
93}
94
95pub trait ReadableManifestBase {
96 fn is_subintent(&self) -> bool;
97 fn get_blobs<'a>(&'a self) -> impl Iterator<Item = (&'a Hash, &'a Vec<u8>)>;
98 fn get_preallocated_addresses(&self) -> &[PreAllocatedAddress] {
99 &NO_PREALLOCATED_ADDRESSES
100 }
101 fn get_child_subintent_hashes<'a>(
102 &'a self,
103 ) -> impl ExactSizeIterator<Item = &'a ChildSubintentSpecifier> {
104 NO_CHILD_SUBINTENTS.iter()
105 }
106 fn get_known_object_names_ref(&self) -> ManifestObjectNamesRef;
107}
108
109pub trait ReadableManifest: ReadableManifestBase {
111 fn iter_instruction_effects(&self) -> impl Iterator<Item = ManifestInstructionEffect>;
112 fn iter_cloned_instructions(&self) -> impl Iterator<Item = AnyInstruction>;
113 fn instruction_count(&self) -> usize;
114 fn instruction_effect(&self, index: usize) -> ManifestInstructionEffect;
116
117 fn validate(&self, ruleset: ValidationRuleset) -> Result<(), ManifestValidationError> {
118 StaticManifestInterpreter::new(ruleset, self).validate()
119 }
120}
121
122impl<T: TypedReadableManifest + ?Sized> ReadableManifest for T {
123 fn iter_instruction_effects(&self) -> impl Iterator<Item = ManifestInstructionEffect> {
124 self.get_typed_instructions().iter().map(|i| i.effect())
125 }
126
127 fn iter_cloned_instructions(&self) -> impl Iterator<Item = AnyInstruction> {
128 self.get_typed_instructions()
129 .iter()
130 .map(|i| i.clone().into())
131 }
132
133 fn instruction_count(&self) -> usize {
134 self.get_typed_instructions().len()
135 }
136
137 fn instruction_effect(&self, index: usize) -> ManifestInstructionEffect {
138 self.get_typed_instructions()[index].effect()
139 }
140}
141
142static NO_PREALLOCATED_ADDRESSES: [PreAllocatedAddress; 0] = [];
143static NO_CHILD_SUBINTENTS: [ChildSubintentSpecifier; 0] = [];
144
145pub struct EphemeralManifest<'a, I: ManifestInstructionSet> {
146 pub is_subintent: bool,
147 pub instructions: &'a [I],
148 pub blobs: &'a IndexMap<Hash, Vec<u8>>,
149 pub child_subintent_specifiers: Option<&'a IndexSet<ChildSubintentSpecifier>>,
150 pub known_object_names_ref: ManifestObjectNamesRef<'a>,
151}
152
153impl<'a, I: ManifestInstructionSet> EphemeralManifest<'a, I> {
154 pub fn new_childless_transaction_manifest(
155 instructions: &'a [I],
156 blobs: &'a IndexMap<Hash, Vec<u8>>,
157 ) -> Self {
158 Self {
159 is_subintent: false,
160 instructions,
161 blobs,
162 child_subintent_specifiers: None,
163 known_object_names_ref: ManifestObjectNamesRef::Unknown,
164 }
165 }
166
167 pub fn new(
168 instructions: &'a [I],
169 blobs: &'a IndexMap<Hash, Vec<u8>>,
170 child_subintent_specifiers: &'a IndexSet<ChildSubintentSpecifier>,
171 is_subintent: bool,
172 ) -> Self {
173 Self {
174 is_subintent,
175 instructions,
176 blobs,
177 child_subintent_specifiers: Some(child_subintent_specifiers),
178 known_object_names_ref: ManifestObjectNamesRef::Unknown,
179 }
180 }
181}
182
183impl<'a, I: ManifestInstructionSet> ReadableManifestBase for EphemeralManifest<'a, I> {
184 fn is_subintent(&self) -> bool {
185 self.is_subintent
186 }
187
188 fn get_blobs<'b>(&'b self) -> impl Iterator<Item = (&'b Hash, &'b Vec<u8>)> {
189 self.blobs.iter()
190 }
191
192 fn get_known_object_names_ref(&self) -> ManifestObjectNamesRef {
193 self.known_object_names_ref
194 }
195
196 fn get_child_subintent_hashes<'b>(
197 &'b self,
198 ) -> impl ExactSizeIterator<Item = &'b ChildSubintentSpecifier> {
199 let iterator: Box<dyn ExactSizeIterator<Item = &'b ChildSubintentSpecifier>> =
200 match self.child_subintent_specifiers {
201 Some(specifiers) => Box::new(specifiers.iter()),
202 None => Box::new(NO_CHILD_SUBINTENTS.iter()),
203 };
204 iterator
205 }
206}
207
208impl<'a, I: ManifestInstructionSet> TypedReadableManifest for EphemeralManifest<'a, I> {
209 type Instruction = I;
210
211 fn get_typed_instructions(&self) -> &[I] {
212 self.instructions
213 }
214}