1use blake2::{Blake2b, Digest, digest::typenum::U32};
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 mod prelude {
48 use super::*;
50
51 mod private {
52 use super::*;
53
54 pub trait Sealed {}
55
56 impl Sealed for ActorId {}
57 impl Sealed for CodeId {}
58 impl Sealed for MessageId {}
59 impl Sealed for ReservationId {}
60 }
61
62 pub trait ActorIdExt: private::Sealed {
64 const SYSTEM: Self;
66
67 fn generate_from_user(code_id: CodeId, salt: &[u8]) -> Self;
69
70 fn generate_from_program(message_id: MessageId, code_id: CodeId, salt: &[u8]) -> Self;
72 }
73
74 impl ActorIdExt for ActorId {
75 const SYSTEM: Self = Self::new(*b"geargeargeargeargeargeargeargear");
76
77 fn generate_from_user(code_id: CodeId, salt: &[u8]) -> Self {
78 const SALT: &[u8] = b"program_from_user";
79 hash_of_array([SALT, code_id.as_ref(), salt]).into()
80 }
81
82 fn generate_from_program(message_id: MessageId, code_id: CodeId, salt: &[u8]) -> Self {
83 const SALT: &[u8] = b"program_from_wasm";
84 hash_of_array([SALT, message_id.as_ref(), code_id.as_ref(), salt]).into()
85 }
86 }
87
88 pub trait MessageIdExt: private::Sealed {
90 fn generate_from_user(block_number: u32, user_id: ActorId, local_nonce: u128) -> MessageId;
92
93 fn generate_outgoing(origin_msg_id: MessageId, local_nonce: u32) -> MessageId;
95
96 fn generate_reply(origin_msg_id: MessageId) -> MessageId;
101
102 fn generate_signal(origin_msg_id: MessageId) -> MessageId;
104 }
105
106 impl MessageIdExt for MessageId {
107 fn generate_from_user(block_number: u32, user_id: ActorId, local_nonce: u128) -> MessageId {
108 const SALT: &[u8] = b"external";
109 hash_of_array([
110 SALT,
111 &block_number.to_le_bytes(),
112 user_id.as_ref(),
113 &local_nonce.to_le_bytes(),
114 ])
115 .into()
116 }
117
118 fn generate_outgoing(origin_msg_id: MessageId, local_nonce: u32) -> MessageId {
119 const SALT: &[u8] = b"outgoing";
120 hash_of_array([SALT, origin_msg_id.as_ref(), &local_nonce.to_le_bytes()]).into()
121 }
122
123 fn generate_reply(origin_msg_id: MessageId) -> MessageId {
124 const SALT: &[u8] = b"reply";
125 hash_of_array([SALT, origin_msg_id.as_ref()]).into()
126 }
127
128 fn generate_signal(origin_msg_id: MessageId) -> MessageId {
129 const SALT: &[u8] = b"signal";
130 hash_of_array([SALT, origin_msg_id.as_ref()]).into()
131 }
132 }
133
134 pub trait CodeIdExt: private::Sealed {
136 fn generate(code: &[u8]) -> Self;
138 }
139
140 impl CodeIdExt for CodeId {
141 fn generate(code: &[u8]) -> Self {
142 hash(code).into()
143 }
144 }
145
146 pub trait ReservationIdExt: private::Sealed {
148 fn generate(msg_id: MessageId, nonce: u64) -> Self;
150 }
151
152 impl ReservationIdExt for ReservationId {
153 fn generate(msg_id: MessageId, nonce: u64) -> Self {
154 const SALT: &[u8] = b"reservation";
155 hash_of_array([SALT, msg_id.as_ref(), &nonce.to_le_bytes()]).into()
156 }
157 }
158}