essential_hash/contract_addr.rs
1//! A small collection of helper functions to assist in the calculation of an
2//! contract's content address.
3//!
4//! See the [`PredicateAddress`][essential_types::PredicateAddress] documentation for
5//! more information on the requirements behind the contract content address.
6
7use essential_types::{contract::Contract, ContentAddress, Hash};
8
9/// Shorthand for the common case of producing an contract address from an
10/// iterator yielding references to [`Predicate`][essential_types::predicate::Predicate]s.
11///
12/// If you have already calculated the content address for each predicate consider
13/// using [`from_predicate_addrs`] or [`from_predicate_addrs_slice`].
14pub fn from_contract(contract: &Contract) -> ContentAddress {
15 let predicate_addrs = contract.predicates.iter().map(crate::content_addr);
16 from_predicate_addrs(predicate_addrs, &contract.salt)
17}
18
19/// Given the predicate content address for each predicate in the contract, produce the
20/// contract's content address.
21///
22/// This collects all yielded predicate content addresses into a `Vec`, sorts them and then
23/// hashes the result to produce the contract address.
24///
25/// If you have already collected the content address for each predicate into a
26/// slice, consider [`from_predicate_addrs_slice`].
27pub fn from_predicate_addrs(
28 predicate_addrs: impl IntoIterator<Item = ContentAddress>,
29 salt: &Hash,
30) -> ContentAddress {
31 let mut predicate_addrs: Vec<_> = predicate_addrs.into_iter().collect();
32 from_predicate_addrs_slice(&mut predicate_addrs, salt)
33}
34
35/// Given the predicate content address for each predicate in the contract, produce the
36/// contract's content address.
37///
38/// This first sorts `predicate_addrs` before producing the content address of the
39/// slice, ensuring that the address maintains "contract" semantics (i.e. the order
40/// of the content addresses does not matter).
41pub fn from_predicate_addrs_slice(
42 predicate_addrs: &mut [ContentAddress],
43 salt: &Hash,
44) -> ContentAddress {
45 predicate_addrs.sort();
46 ContentAddress(crate::hash_bytes_iter(
47 predicate_addrs
48 .iter()
49 .map(|addr| addr.0.as_slice())
50 .chain(Some(salt.as_slice())),
51 ))
52}