penumbra_sdk_ibc/
prefix.rs

1use ibc_types::core::commitment::MerklePrefix;
2use once_cell::sync::Lazy;
3
4/// The substore prefix used for IBC data.
5pub static IBC_SUBSTORE_PREFIX: &'static str = "ibc-data";
6
7/// The IBC commitment prefix used for the IBC substore, as a [`MerklePrefix`].
8pub static IBC_COMMITMENT_PREFIX: Lazy<MerklePrefix> = Lazy::new(|| MerklePrefix {
9    key_prefix: IBC_SUBSTORE_PREFIX.as_bytes().to_vec(),
10});
11
12// Vendored from the jmt crate, rather than importing it from e.g., cnidarium
13// The proof specs need to be available for use cases like relayers, so it should be
14// outside of the feature-gated component implementation, and we only depend on
15// cnidarium when actually implementing the component (since that pulls in all of rocksdb, etc).
16// Vendoring isn't ideal, but this data is effectively "vendored" anyways since it needs to
17// be replicated across relayers, chain configs, ....
18mod vendored {
19    const LEAF_DOMAIN_SEPARATOR: &[u8] = b"JMT::LeafNode";
20    const INTERNAL_DOMAIN_SEPARATOR: &[u8] = b"JMT::IntrnalNode";
21
22    const SPARSE_MERKLE_PLACEHOLDER_HASH: [u8; 32] = *b"SPARSE_MERKLE_PLACEHOLDER_HASH__";
23
24    pub fn ics23_spec() -> ics23::ProofSpec {
25        ics23::ProofSpec {
26            leaf_spec: Some(ics23::LeafOp {
27                hash: ics23::HashOp::Sha256.into(),
28                prehash_key: ics23::HashOp::Sha256.into(),
29                prehash_value: ics23::HashOp::Sha256.into(),
30                length: ics23::LengthOp::NoPrefix.into(),
31                prefix: LEAF_DOMAIN_SEPARATOR.to_vec(),
32            }),
33            inner_spec: Some(ics23::InnerSpec {
34                hash: ics23::HashOp::Sha256.into(),
35                child_order: vec![0, 1],
36                min_prefix_length: INTERNAL_DOMAIN_SEPARATOR.len() as i32,
37                max_prefix_length: INTERNAL_DOMAIN_SEPARATOR.len() as i32,
38                child_size: 32,
39                empty_child: SPARSE_MERKLE_PLACEHOLDER_HASH.to_vec(),
40            }),
41            min_depth: 0,
42            max_depth: 64,
43            prehash_key_before_comparison: true,
44        }
45    }
46}
47
48/// The ICS23 proof spec for penumbra's IBC state; this can be used to verify proofs
49/// for other substores in the penumbra state, provided that the data is indeed inside a substore
50/// (as opposed to directly in the root store.)
51pub static IBC_PROOF_SPECS: Lazy<Vec<ics23::ProofSpec>> =
52    Lazy::new(|| vec![vendored::ics23_spec(), vendored::ics23_spec()]);
53
54/// TODO: upstream into ibc-types
55pub trait MerklePrefixExt {
56    fn apply_string(&self, path: String) -> String;
57}
58
59impl MerklePrefixExt for MerklePrefix {
60    fn apply_string(&self, path: String) -> String {
61        let prefix_string = String::from_utf8(self.key_prefix.clone())
62            .expect("commitment prefix is not valid utf-8");
63
64        format!("{}/{}", prefix_string, path)
65    }
66}