use blake2::{Blake2b, Digest, digest::typenum::U32};
pub use gprimitives::{ActorId, CodeId, MessageId, ReservationId};
type Blake2b256 = Blake2b<U32>;
pub fn hash(data: &[u8]) -> [u8; 32] {
let mut ctx = Blake2b256::new();
ctx.update(data);
ctx.finalize().into()
}
pub fn hash_of_array<T: AsRef<[u8]>, const N: usize>(array: [T; N]) -> [u8; 32] {
let mut ctx = Blake2b256::new();
for data in array {
ctx.update(data);
}
ctx.finalize().into()
}
pub mod prelude {
use super::*;
mod private {
use super::*;
pub trait Sealed {}
impl Sealed for ActorId {}
impl Sealed for CodeId {}
impl Sealed for MessageId {}
impl Sealed for ReservationId {}
}
pub trait ActorIdExt: private::Sealed {
const SYSTEM: Self;
fn generate_from_user(code_id: CodeId, salt: &[u8]) -> Self;
fn generate_from_program(message_id: MessageId, code_id: CodeId, salt: &[u8]) -> Self;
}
impl ActorIdExt for ActorId {
const SYSTEM: Self = Self::new(*b"geargeargeargeargeargeargeargear");
fn generate_from_user(code_id: CodeId, salt: &[u8]) -> Self {
const SALT: &[u8] = b"program_from_user";
hash_of_array([SALT, code_id.as_ref(), salt]).into()
}
fn generate_from_program(message_id: MessageId, code_id: CodeId, salt: &[u8]) -> Self {
const SALT: &[u8] = b"program_from_wasm";
hash_of_array([SALT, message_id.as_ref(), code_id.as_ref(), salt]).into()
}
}
pub trait MessageIdExt: private::Sealed {
fn generate_from_user(block_number: u32, user_id: ActorId, local_nonce: u128) -> MessageId;
fn generate_outgoing(origin_msg_id: MessageId, local_nonce: u32) -> MessageId;
fn generate_reply(origin_msg_id: MessageId) -> MessageId;
fn generate_signal(origin_msg_id: MessageId) -> MessageId;
}
impl MessageIdExt for MessageId {
fn generate_from_user(block_number: u32, user_id: ActorId, local_nonce: u128) -> MessageId {
const SALT: &[u8] = b"external";
hash_of_array([
SALT,
&block_number.to_le_bytes(),
user_id.as_ref(),
&local_nonce.to_le_bytes(),
])
.into()
}
fn generate_outgoing(origin_msg_id: MessageId, local_nonce: u32) -> MessageId {
const SALT: &[u8] = b"outgoing";
hash_of_array([SALT, origin_msg_id.as_ref(), &local_nonce.to_le_bytes()]).into()
}
fn generate_reply(origin_msg_id: MessageId) -> MessageId {
const SALT: &[u8] = b"reply";
hash_of_array([SALT, origin_msg_id.as_ref()]).into()
}
fn generate_signal(origin_msg_id: MessageId) -> MessageId {
const SALT: &[u8] = b"signal";
hash_of_array([SALT, origin_msg_id.as_ref()]).into()
}
}
pub trait CodeIdExt: private::Sealed {
fn generate(code: &[u8]) -> Self;
}
impl CodeIdExt for CodeId {
fn generate(code: &[u8]) -> Self {
hash(code).into()
}
}
pub trait ReservationIdExt: private::Sealed {
fn generate(msg_id: MessageId, nonce: u64) -> Self;
}
impl ReservationIdExt for ReservationId {
fn generate(msg_id: MessageId, nonce: u64) -> Self {
const SALT: &[u8] = b"reservation";
hash_of_array([SALT, msg_id.as_ref(), &nonce.to_le_bytes()]).into()
}
}
}