radix_engine/system/system_modules/transaction_runtime/
module.rs1use crate::internal_prelude::*;
2use crate::system::module::*;
3use crate::system::system_callback::*;
4use radix_common::crypto::Hash;
5use radix_engine_interface::api::actor_api::EventFlags;
6use radix_engine_interface::api::ModuleId;
7
8#[derive(Debug, Clone)]
9pub struct Event {
10 pub type_identifier: EventTypeIdentifier,
11 pub payload: Vec<u8>,
12 pub flags: EventFlags,
13}
14
15pub const EVENT_FLAGS_LEN: usize = 4;
17
18impl Event {
19 #[allow(clippy::len_without_is_empty)]
20 pub fn len(&self) -> usize {
21 self.type_identifier.len() + self.payload.len() + EVENT_FLAGS_LEN
22 }
23}
24
25#[derive(Debug, Clone)]
26pub struct TransactionRuntimeModule {
27 pub network_definition: NetworkDefinition,
28 pub tx_hash: Hash,
29 pub next_id: u32,
30 pub logs: Vec<(Level, String)>,
31 pub events: Vec<Event>,
32 pub replacements: IndexMap<(NodeId, ModuleId), (NodeId, ModuleId)>,
33}
34
35impl TransactionRuntimeModule {
36 pub fn new(network_definition: NetworkDefinition, tx_hash: Hash) -> Self {
37 TransactionRuntimeModule {
38 network_definition,
39 tx_hash,
40 next_id: 0,
41 logs: Vec::new(),
42 events: Vec::new(),
43 replacements: index_map_new(),
44 }
45 }
46
47 pub fn generate_ruid(&mut self) -> [u8; 32] {
48 let mut bytes = [0u8; 36];
49 bytes[..32].copy_from_slice(self.tx_hash.as_slice());
50 bytes[32..].copy_from_slice(&self.next_id.to_le_bytes());
51
52 self.next_id += 1;
53
54 hash(bytes).0
55 }
56
57 pub fn add_log(&mut self, level: Level, message: String) {
58 self.logs.push((level, message))
59 }
60
61 pub fn add_event(&mut self, event: Event) {
62 self.events.push(event)
63 }
64
65 pub fn add_replacement(&mut self, old: (NodeId, ModuleId), new: (NodeId, ModuleId)) {
66 self.replacements.insert(old, new);
67 }
68
69 #[allow(clippy::type_complexity)]
70 pub fn finalize(
71 self,
72 is_success: bool,
73 ) -> (Vec<(EventTypeIdentifier, Vec<u8>)>, Vec<(Level, String)>) {
74 let mut results = Vec::new();
75
76 for Event {
77 mut type_identifier,
78 payload,
79 flags,
80 } in self.events.into_iter()
81 {
82 if !flags.contains(EventFlags::FORCE_WRITE) && !is_success {
84 continue;
85 }
86
87 if let EventTypeIdentifier(Emitter::Method(node_id, module_id), _) =
89 &mut type_identifier
90 {
91 if let Some((new_node_id, new_module_id)) =
92 self.replacements.get(&(*node_id, *module_id))
93 {
94 *node_id = *new_node_id;
95 *module_id = *new_module_id;
96 }
97 };
98
99 results.push((type_identifier, payload))
101 }
102
103 (results, self.logs)
104 }
105}
106
107impl InitSystemModule for TransactionRuntimeModule {}
108impl ResolvableSystemModule for TransactionRuntimeModule {
109 #[inline]
110 fn resolve_from_system(system: &mut impl HasModules) -> &mut Self {
111 &mut system.modules_mut().transaction_runtime
112 }
113}
114impl PrivilegedSystemModule for TransactionRuntimeModule {}
115impl<ModuleApi: SystemModuleApiFor<Self>> SystemModule<ModuleApi> for TransactionRuntimeModule {}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_ruid_gen() {
123 let mut id = TransactionRuntimeModule {
124 network_definition: NetworkDefinition::simulator(),
125 tx_hash: Hash::from_str(
126 "71f26aab5eec6679f67c71211aba9a3486cc8d24194d339385ee91ee5ca7b30d",
127 )
128 .unwrap(),
129 next_id: 5,
130 logs: Vec::new(),
131 events: Vec::new(),
132 replacements: index_map_new(),
133 };
134 assert_eq!(
135 NonFungibleLocalId::ruid(id.generate_ruid()).to_string(),
136 "{7b003d8e0b2c9e3a-516cf99882de64a1-f1cd6742ce3299e0-357f54f0333d25d0}"
137 );
138
139 let mut id = TransactionRuntimeModule {
140 network_definition: NetworkDefinition::simulator(),
141 tx_hash: Hash([0u8; 32]),
142 next_id: 5,
143 logs: Vec::new(),
144 events: Vec::new(),
145 replacements: index_map_new(),
146 };
147 assert_eq!(
148 NonFungibleLocalId::ruid(id.generate_ruid()).to_string(),
149 "{69f38caee99e9468-866032d1a68b4d2e-7931bb74aede4d0f-8043d3a87e9f2da3}"
150 );
151
152 let mut id = TransactionRuntimeModule {
153 network_definition: NetworkDefinition::simulator(),
154 tx_hash: Hash([255u8; 32]),
155 next_id: 5,
156 logs: Vec::new(),
157 events: Vec::new(),
158 replacements: index_map_new(),
159 };
160 assert_eq!(
161 NonFungibleLocalId::ruid(id.generate_ruid()).to_string(),
162 "{04660ebc8e2a2b36-44a6553bd6a17a3a-ef14ce1fae4cb5bc-000811f979007003}"
163 );
164 }
165}