1use blake2::{digest::typenum::U32, Blake2b, Digest};
22pub use gprimitives::{ActorId, CodeId, MessageId, ReservationId};
23
24type Blake2b256 = Blake2b<U32>;
26
27pub fn hash(data: &[u8]) -> [u8; 32] {
31 let mut ctx = Blake2b256::new();
32 ctx.update(data);
33 ctx.finalize().into()
34}
35
36pub fn hash_of_array<T: AsRef<[u8]>, const N: usize>(array: [T; N]) -> [u8; 32] {
40 let mut ctx = Blake2b256::new();
41 for data in array {
42 ctx.update(data);
43 }
44 ctx.finalize().into()
45}
46
47pub type ProgramId = ActorId;
49
50pub mod prelude {
51 use super::*;
53
54 mod private {
55 use super::*;
56
57 pub trait Sealed {}
58
59 impl Sealed for ActorId {}
60 impl Sealed for CodeId {}
61 impl Sealed for MessageId {}
62 impl Sealed for ReservationId {}
63 }
64
65 pub trait ActorIdExt: private::Sealed {
67 const SYSTEM: Self;
69
70 fn generate_from_user(code_id: CodeId, salt: &[u8]) -> Self;
72
73 fn generate_from_program(message_id: MessageId, code_id: CodeId, salt: &[u8]) -> Self;
75 }
76
77 impl ActorIdExt for ActorId {
78 const SYSTEM: Self = Self::new(*b"geargeargeargeargeargeargeargear");
79
80 fn generate_from_user(code_id: CodeId, salt: &[u8]) -> Self {
81 const SALT: &[u8] = b"program_from_user";
82 hash_of_array([SALT, code_id.as_ref(), salt]).into()
83 }
84
85 fn generate_from_program(message_id: MessageId, code_id: CodeId, salt: &[u8]) -> Self {
86 const SALT: &[u8] = b"program_from_wasm";
87 hash_of_array([SALT, message_id.as_ref(), code_id.as_ref(), salt]).into()
88 }
89 }
90
91 pub trait MessageIdExt: private::Sealed {
93 fn generate_from_user(
95 block_number: u32,
96 user_id: ProgramId,
97 local_nonce: u128,
98 ) -> MessageId;
99
100 fn generate_outgoing(origin_msg_id: MessageId, local_nonce: u32) -> MessageId;
102
103 fn generate_reply(origin_msg_id: MessageId) -> MessageId;
108
109 fn generate_signal(origin_msg_id: MessageId) -> MessageId;
111 }
112
113 impl MessageIdExt for MessageId {
114 fn generate_from_user(
115 block_number: u32,
116 user_id: ProgramId,
117 local_nonce: u128,
118 ) -> MessageId {
119 const SALT: &[u8] = b"external";
120 hash_of_array([
121 SALT,
122 &block_number.to_le_bytes(),
123 user_id.as_ref(),
124 &local_nonce.to_le_bytes(),
125 ])
126 .into()
127 }
128
129 fn generate_outgoing(origin_msg_id: MessageId, local_nonce: u32) -> MessageId {
130 const SALT: &[u8] = b"outgoing";
131 hash_of_array([SALT, origin_msg_id.as_ref(), &local_nonce.to_le_bytes()]).into()
132 }
133
134 fn generate_reply(origin_msg_id: MessageId) -> MessageId {
135 const SALT: &[u8] = b"reply";
136 hash_of_array([SALT, origin_msg_id.as_ref()]).into()
137 }
138
139 fn generate_signal(origin_msg_id: MessageId) -> MessageId {
140 const SALT: &[u8] = b"signal";
141 hash_of_array([SALT, origin_msg_id.as_ref()]).into()
142 }
143 }
144
145 pub trait CodeIdExt: private::Sealed {
147 fn generate(code: &[u8]) -> Self;
149 }
150
151 impl CodeIdExt for CodeId {
152 fn generate(code: &[u8]) -> Self {
153 hash(code).into()
154 }
155 }
156
157 pub trait ReservationIdExt: private::Sealed {
159 fn generate(msg_id: MessageId, nonce: u64) -> Self;
161 }
162
163 impl ReservationIdExt for ReservationId {
164 fn generate(msg_id: MessageId, nonce: u64) -> Self {
165 const SALT: &[u8] = b"reservation";
166 hash_of_array([SALT, msg_id.as_ref(), &nonce.to_le_bytes()]).into()
167 }
168 }
169}