1use blake2::{Blake2b, Digest, digest::typenum::U32};
7pub use gprimitives::{ActorId, CodeId, MessageId, ReservationId};
8
9type Blake2b256 = Blake2b<U32>;
11
12pub fn hash(data: &[u8]) -> [u8; 32] {
16 let mut ctx = Blake2b256::new();
17 ctx.update(data);
18 ctx.finalize().into()
19}
20
21pub fn hash_of_array<T: AsRef<[u8]>, const N: usize>(array: [T; N]) -> [u8; 32] {
25 let mut ctx = Blake2b256::new();
26 for data in array {
27 ctx.update(data);
28 }
29 ctx.finalize().into()
30}
31
32pub mod prelude {
33 use super::*;
35
36 mod private {
37 use super::*;
38
39 pub trait Sealed {}
40
41 impl Sealed for ActorId {}
42 impl Sealed for CodeId {}
43 impl Sealed for MessageId {}
44 impl Sealed for ReservationId {}
45 }
46
47 pub trait ActorIdExt: private::Sealed {
49 const SYSTEM: Self;
51
52 fn generate_from_user(code_id: CodeId, salt: &[u8]) -> Self;
54
55 fn generate_from_program(message_id: MessageId, code_id: CodeId, salt: &[u8]) -> Self;
57 }
58
59 impl ActorIdExt for ActorId {
60 const SYSTEM: Self = Self::new(*b"geargeargeargeargeargeargeargear");
61
62 fn generate_from_user(code_id: CodeId, salt: &[u8]) -> Self {
63 const SALT: &[u8] = b"program_from_user";
64 hash_of_array([SALT, code_id.as_ref(), salt]).into()
65 }
66
67 fn generate_from_program(message_id: MessageId, code_id: CodeId, salt: &[u8]) -> Self {
68 const SALT: &[u8] = b"program_from_wasm";
69 hash_of_array([SALT, message_id.as_ref(), code_id.as_ref(), salt]).into()
70 }
71 }
72
73 pub trait MessageIdExt: private::Sealed {
75 fn generate_from_user(block_number: u32, user_id: ActorId, local_nonce: u128) -> MessageId;
77
78 fn generate_outgoing(origin_msg_id: MessageId, local_nonce: u32) -> MessageId;
80
81 fn generate_reply(origin_msg_id: MessageId) -> MessageId;
86
87 fn generate_signal(origin_msg_id: MessageId) -> MessageId;
89 }
90
91 impl MessageIdExt for MessageId {
92 fn generate_from_user(block_number: u32, user_id: ActorId, local_nonce: u128) -> MessageId {
93 const SALT: &[u8] = b"external";
94 hash_of_array([
95 SALT,
96 &block_number.to_le_bytes(),
97 user_id.as_ref(),
98 &local_nonce.to_le_bytes(),
99 ])
100 .into()
101 }
102
103 fn generate_outgoing(origin_msg_id: MessageId, local_nonce: u32) -> MessageId {
104 const SALT: &[u8] = b"outgoing";
105 hash_of_array([SALT, origin_msg_id.as_ref(), &local_nonce.to_le_bytes()]).into()
106 }
107
108 fn generate_reply(origin_msg_id: MessageId) -> MessageId {
109 const SALT: &[u8] = b"reply";
110 hash_of_array([SALT, origin_msg_id.as_ref()]).into()
111 }
112
113 fn generate_signal(origin_msg_id: MessageId) -> MessageId {
114 const SALT: &[u8] = b"signal";
115 hash_of_array([SALT, origin_msg_id.as_ref()]).into()
116 }
117 }
118
119 pub trait CodeIdExt: private::Sealed {
121 fn generate(code: &[u8]) -> Self;
123 }
124
125 impl CodeIdExt for CodeId {
126 fn generate(code: &[u8]) -> Self {
127 hash(code).into()
128 }
129 }
130
131 pub trait ReservationIdExt: private::Sealed {
133 fn generate(msg_id: MessageId, nonce: u64) -> Self;
135 }
136
137 impl ReservationIdExt for ReservationId {
138 fn generate(msg_id: MessageId, nonce: u64) -> Self {
139 const SALT: &[u8] = b"reservation";
140 hash_of_array([SALT, msg_id.as_ref(), &nonce.to_le_bytes()]).into()
141 }
142 }
143}