casper_executor_wasm_common/
chain_utils.rs

1use blake2::{digest::consts::U32, Blake2b, Digest};
2
3/// Compute a predictable address for a contract.
4///
5/// The address is computed as the hash of the chain name, initiator account, and the hash of the
6/// Wasm code.
7pub fn compute_predictable_address<T: AsRef<[u8]>>(
8    chain_name: T,
9    initiator_address: [u8; 32],
10    bytecode_hash: [u8; 32],
11    seed: Option<[u8; 32]>,
12) -> [u8; 32] {
13    let mut hasher = Blake2b::<U32>::new();
14
15    hasher.update(chain_name);
16    hasher.update(initiator_address);
17    hasher.update(bytecode_hash);
18
19    if let Some(seed) = seed {
20        hasher.update(seed);
21    }
22
23    hasher.finalize().into()
24}
25
26pub fn compute_wasm_bytecode_hash<T: AsRef<[u8]>>(wasm_bytes: T) -> [u8; 32] {
27    let mut hasher = Blake2b::<U32>::new();
28    hasher.update(wasm_bytes);
29    let hash = hasher.finalize();
30    hash.into()
31}
32
33#[must_use]
34pub fn compute_next_contract_hash_version(
35    smart_contract_addr: [u8; 32],
36    next_version: u32,
37) -> [u8; 32] {
38    let mut hasher = Blake2b::<U32>::new();
39
40    hasher.update(smart_contract_addr);
41    hasher.update(next_version.to_le_bytes());
42
43    hasher.finalize().into()
44}
45
46#[cfg(test)]
47mod tests {
48    const SEED: [u8; 32] = [1u8; 32];
49
50    #[test]
51    fn test_compute_predictable_address() {
52        let initiator = [1u8; 32];
53        let bytecode_hash = [2u8; 32];
54
55        let predictable_address_1 =
56            super::compute_predictable_address("testnet", initiator, bytecode_hash, Some(SEED));
57        let predictable_address_2 =
58            super::compute_predictable_address("mainnet", initiator, bytecode_hash, Some(SEED));
59        assert_ne!(predictable_address_1, predictable_address_2);
60    }
61
62    #[test]
63    fn test_compute_nth_version_hash() {
64        let smart_contract_addr = [1u8; 32];
65        let mut next_version = 1;
66
67        let hash_1 = super::compute_next_contract_hash_version(smart_contract_addr, next_version);
68        next_version += 1;
69
70        let hash_2 = super::compute_next_contract_hash_version(smart_contract_addr, next_version);
71        assert_ne!(hash_1, hash_2);
72    }
73}