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