juno_rust_proto/prost/ibc-go/
ics23.rs

1/// *
2/// ExistenceProof takes a key and a value and a set of steps to perform on it.
3/// The result of peforming all these steps will provide a "root hash", which can
4/// be compared to the value in a header.
5///
6/// Since it is computationally infeasible to produce a hash collission for any of the used
7/// cryptographic hash functions, if someone can provide a series of operations to transform
8/// a given key and value into a root hash that matches some trusted root, these key and values
9/// must be in the referenced merkle tree.
10///
11/// The only possible issue is maliablity in LeafOp, such as providing extra prefix data,
12/// which should be controlled by a spec. Eg. with lengthOp as NONE,
13/// prefix = FOO, key = BAR, value = CHOICE
14/// and
15/// prefix = F, key = OOBAR, value = CHOICE
16/// would produce the same value.
17///
18/// With LengthOp this is tricker but not impossible. Which is why the "leafPrefixEqual" field
19/// in the ProofSpec is valuable to prevent this mutability. And why all trees should
20/// length-prefix the data before hashing it.
21#[allow(clippy::derive_partial_eq_without_eq)]
22#[derive(Clone, PartialEq, ::prost::Message)]
23pub struct ExistenceProof {
24    #[prost(bytes = "vec", tag = "1")]
25    pub key: ::prost::alloc::vec::Vec<u8>,
26    #[prost(bytes = "vec", tag = "2")]
27    pub value: ::prost::alloc::vec::Vec<u8>,
28    #[prost(message, optional, tag = "3")]
29    pub leaf: ::core::option::Option<LeafOp>,
30    #[prost(message, repeated, tag = "4")]
31    pub path: ::prost::alloc::vec::Vec<InnerOp>,
32}
33///
34/// NonExistenceProof takes a proof of two neighbors, one left of the desired key,
35/// one right of the desired key. If both proofs are valid AND they are neighbors,
36/// then there is no valid proof for the given key.
37#[allow(clippy::derive_partial_eq_without_eq)]
38#[derive(Clone, PartialEq, ::prost::Message)]
39pub struct NonExistenceProof {
40    /// TODO: remove this as unnecessary??? we prove a range
41    #[prost(bytes = "vec", tag = "1")]
42    pub key: ::prost::alloc::vec::Vec<u8>,
43    #[prost(message, optional, tag = "2")]
44    pub left: ::core::option::Option<ExistenceProof>,
45    #[prost(message, optional, tag = "3")]
46    pub right: ::core::option::Option<ExistenceProof>,
47}
48///
49/// CommitmentProof is either an ExistenceProof or a NonExistenceProof, or a Batch of such messages
50#[allow(clippy::derive_partial_eq_without_eq)]
51#[derive(Clone, PartialEq, ::prost::Message)]
52pub struct CommitmentProof {
53    #[prost(oneof = "commitment_proof::Proof", tags = "1, 2, 3, 4")]
54    pub proof: ::core::option::Option<commitment_proof::Proof>,
55}
56/// Nested message and enum types in `CommitmentProof`.
57pub mod commitment_proof {
58    #[allow(clippy::derive_partial_eq_without_eq)]
59    #[derive(Clone, PartialEq, ::prost::Oneof)]
60    pub enum Proof {
61        #[prost(message, tag = "1")]
62        Exist(super::ExistenceProof),
63        #[prost(message, tag = "2")]
64        Nonexist(super::NonExistenceProof),
65        #[prost(message, tag = "3")]
66        Batch(super::BatchProof),
67        #[prost(message, tag = "4")]
68        Compressed(super::CompressedBatchProof),
69    }
70}
71/// *
72/// LeafOp represents the raw key-value data we wish to prove, and
73/// must be flexible to represent the internal transformation from
74/// the original key-value pairs into the basis hash, for many existing
75/// merkle trees.
76///
77/// key and value are passed in. So that the signature of this operation is:
78/// leafOp(key, value) -> output
79///
80/// To process this, first prehash the keys and values if needed (ANY means no hash in this case):
81/// hkey = prehashKey(key)
82/// hvalue = prehashValue(value)
83///
84/// Then combine the bytes, and hash it
85/// output = hash(prefix || length(hkey) || hkey || length(hvalue) || hvalue)
86#[allow(clippy::derive_partial_eq_without_eq)]
87#[derive(Clone, PartialEq, ::prost::Message)]
88pub struct LeafOp {
89    #[prost(enumeration = "HashOp", tag = "1")]
90    pub hash: i32,
91    #[prost(enumeration = "HashOp", tag = "2")]
92    pub prehash_key: i32,
93    #[prost(enumeration = "HashOp", tag = "3")]
94    pub prehash_value: i32,
95    #[prost(enumeration = "LengthOp", tag = "4")]
96    pub length: i32,
97    /// prefix is a fixed bytes that may optionally be included at the beginning to differentiate
98    /// a leaf node from an inner node.
99    #[prost(bytes = "vec", tag = "5")]
100    pub prefix: ::prost::alloc::vec::Vec<u8>,
101}
102/// *
103/// InnerOp represents a merkle-proof step that is not a leaf.
104/// It represents concatenating two children and hashing them to provide the next result.
105///
106/// The result of the previous step is passed in, so the signature of this op is:
107/// innerOp(child) -> output
108///
109/// The result of applying InnerOp should be:
110/// output = op.hash(op.prefix || child || op.suffix)
111///
112/// where the || operator is concatenation of binary data,
113/// and child is the result of hashing all the tree below this step.
114///
115/// Any special data, like prepending child with the length, or prepending the entire operation with
116/// some value to differentiate from leaf nodes, should be included in prefix and suffix.
117/// If either of prefix or suffix is empty, we just treat it as an empty string
118#[allow(clippy::derive_partial_eq_without_eq)]
119#[derive(Clone, PartialEq, ::prost::Message)]
120pub struct InnerOp {
121    #[prost(enumeration = "HashOp", tag = "1")]
122    pub hash: i32,
123    #[prost(bytes = "vec", tag = "2")]
124    pub prefix: ::prost::alloc::vec::Vec<u8>,
125    #[prost(bytes = "vec", tag = "3")]
126    pub suffix: ::prost::alloc::vec::Vec<u8>,
127}
128/// *
129/// ProofSpec defines what the expected parameters are for a given proof type.
130/// This can be stored in the client and used to validate any incoming proofs.
131///
132/// verify(ProofSpec, Proof) -> Proof | Error
133///
134/// As demonstrated in tests, if we don't fix the algorithm used to calculate the
135/// LeafHash for a given tree, there are many possible key-value pairs that can
136/// generate a given hash (by interpretting the preimage differently).
137/// We need this for proper security, requires client knows a priori what
138/// tree format server uses. But not in code, rather a configuration object.
139#[allow(clippy::derive_partial_eq_without_eq)]
140#[derive(Clone, PartialEq, ::prost::Message)]
141pub struct ProofSpec {
142    /// any field in the ExistenceProof must be the same as in this spec.
143    /// except Prefix, which is just the first bytes of prefix (spec can be longer)
144    #[prost(message, optional, tag = "1")]
145    pub leaf_spec: ::core::option::Option<LeafOp>,
146    #[prost(message, optional, tag = "2")]
147    pub inner_spec: ::core::option::Option<InnerSpec>,
148    /// max_depth (if > 0) is the maximum number of InnerOps allowed (mainly for fixed-depth tries)
149    #[prost(int32, tag = "3")]
150    pub max_depth: i32,
151    /// min_depth (if > 0) is the minimum number of InnerOps allowed (mainly for fixed-depth tries)
152    #[prost(int32, tag = "4")]
153    pub min_depth: i32,
154}
155///
156/// InnerSpec contains all store-specific structure info to determine if two proofs from a
157/// given store are neighbors.
158///
159/// This enables:
160///
161/// isLeftMost(spec: InnerSpec, op: InnerOp)
162/// isRightMost(spec: InnerSpec, op: InnerOp)
163/// isLeftNeighbor(spec: InnerSpec, left: InnerOp, right: InnerOp)
164#[allow(clippy::derive_partial_eq_without_eq)]
165#[derive(Clone, PartialEq, ::prost::Message)]
166pub struct InnerSpec {
167    /// Child order is the ordering of the children node, must count from 0
168    /// iavl tree is [0, 1] (left then right)
169    /// merk is [0, 2, 1] (left, right, here)
170    #[prost(int32, repeated, tag = "1")]
171    pub child_order: ::prost::alloc::vec::Vec<i32>,
172    #[prost(int32, tag = "2")]
173    pub child_size: i32,
174    #[prost(int32, tag = "3")]
175    pub min_prefix_length: i32,
176    #[prost(int32, tag = "4")]
177    pub max_prefix_length: i32,
178    /// empty child is the prehash image that is used when one child is nil (eg. 20 bytes of 0)
179    #[prost(bytes = "vec", tag = "5")]
180    pub empty_child: ::prost::alloc::vec::Vec<u8>,
181    /// hash is the algorithm that must be used for each InnerOp
182    #[prost(enumeration = "HashOp", tag = "6")]
183    pub hash: i32,
184}
185///
186/// BatchProof is a group of multiple proof types than can be compressed
187#[allow(clippy::derive_partial_eq_without_eq)]
188#[derive(Clone, PartialEq, ::prost::Message)]
189pub struct BatchProof {
190    #[prost(message, repeated, tag = "1")]
191    pub entries: ::prost::alloc::vec::Vec<BatchEntry>,
192}
193/// Use BatchEntry not CommitmentProof, to avoid recursion
194#[allow(clippy::derive_partial_eq_without_eq)]
195#[derive(Clone, PartialEq, ::prost::Message)]
196pub struct BatchEntry {
197    #[prost(oneof = "batch_entry::Proof", tags = "1, 2")]
198    pub proof: ::core::option::Option<batch_entry::Proof>,
199}
200/// Nested message and enum types in `BatchEntry`.
201pub mod batch_entry {
202    #[allow(clippy::derive_partial_eq_without_eq)]
203    #[derive(Clone, PartialEq, ::prost::Oneof)]
204    pub enum Proof {
205        #[prost(message, tag = "1")]
206        Exist(super::ExistenceProof),
207        #[prost(message, tag = "2")]
208        Nonexist(super::NonExistenceProof),
209    }
210}
211#[allow(clippy::derive_partial_eq_without_eq)]
212#[derive(Clone, PartialEq, ::prost::Message)]
213pub struct CompressedBatchProof {
214    #[prost(message, repeated, tag = "1")]
215    pub entries: ::prost::alloc::vec::Vec<CompressedBatchEntry>,
216    #[prost(message, repeated, tag = "2")]
217    pub lookup_inners: ::prost::alloc::vec::Vec<InnerOp>,
218}
219/// Use BatchEntry not CommitmentProof, to avoid recursion
220#[allow(clippy::derive_partial_eq_without_eq)]
221#[derive(Clone, PartialEq, ::prost::Message)]
222pub struct CompressedBatchEntry {
223    #[prost(oneof = "compressed_batch_entry::Proof", tags = "1, 2")]
224    pub proof: ::core::option::Option<compressed_batch_entry::Proof>,
225}
226/// Nested message and enum types in `CompressedBatchEntry`.
227pub mod compressed_batch_entry {
228    #[allow(clippy::derive_partial_eq_without_eq)]
229    #[derive(Clone, PartialEq, ::prost::Oneof)]
230    pub enum Proof {
231        #[prost(message, tag = "1")]
232        Exist(super::CompressedExistenceProof),
233        #[prost(message, tag = "2")]
234        Nonexist(super::CompressedNonExistenceProof),
235    }
236}
237#[allow(clippy::derive_partial_eq_without_eq)]
238#[derive(Clone, PartialEq, ::prost::Message)]
239pub struct CompressedExistenceProof {
240    #[prost(bytes = "vec", tag = "1")]
241    pub key: ::prost::alloc::vec::Vec<u8>,
242    #[prost(bytes = "vec", tag = "2")]
243    pub value: ::prost::alloc::vec::Vec<u8>,
244    #[prost(message, optional, tag = "3")]
245    pub leaf: ::core::option::Option<LeafOp>,
246    /// these are indexes into the lookup_inners table in CompressedBatchProof
247    #[prost(int32, repeated, tag = "4")]
248    pub path: ::prost::alloc::vec::Vec<i32>,
249}
250#[allow(clippy::derive_partial_eq_without_eq)]
251#[derive(Clone, PartialEq, ::prost::Message)]
252pub struct CompressedNonExistenceProof {
253    /// TODO: remove this as unnecessary??? we prove a range
254    #[prost(bytes = "vec", tag = "1")]
255    pub key: ::prost::alloc::vec::Vec<u8>,
256    #[prost(message, optional, tag = "2")]
257    pub left: ::core::option::Option<CompressedExistenceProof>,
258    #[prost(message, optional, tag = "3")]
259    pub right: ::core::option::Option<CompressedExistenceProof>,
260}
261#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
262#[repr(i32)]
263pub enum HashOp {
264    /// NO_HASH is the default if no data passed. Note this is an illegal argument some places.
265    NoHash = 0,
266    Sha256 = 1,
267    Sha512 = 2,
268    Keccak = 3,
269    Ripemd160 = 4,
270    /// ripemd160(sha256(x))
271    Bitcoin = 5,
272}
273impl HashOp {
274    /// String value of the enum field names used in the ProtoBuf definition.
275    ///
276    /// The values are not transformed in any way and thus are considered stable
277    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
278    pub fn as_str_name(&self) -> &'static str {
279        match self {
280            HashOp::NoHash => "NO_HASH",
281            HashOp::Sha256 => "SHA256",
282            HashOp::Sha512 => "SHA512",
283            HashOp::Keccak => "KECCAK",
284            HashOp::Ripemd160 => "RIPEMD160",
285            HashOp::Bitcoin => "BITCOIN",
286        }
287    }
288    /// Creates an enum from field names used in the ProtoBuf definition.
289    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
290        match value {
291            "NO_HASH" => Some(Self::NoHash),
292            "SHA256" => Some(Self::Sha256),
293            "SHA512" => Some(Self::Sha512),
294            "KECCAK" => Some(Self::Keccak),
295            "RIPEMD160" => Some(Self::Ripemd160),
296            "BITCOIN" => Some(Self::Bitcoin),
297            _ => None,
298        }
299    }
300}
301/// *
302/// LengthOp defines how to process the key and value of the LeafOp
303/// to include length information. After encoding the length with the given
304/// algorithm, the length will be prepended to the key and value bytes.
305/// (Each one with it's own encoded length)
306#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
307#[repr(i32)]
308pub enum LengthOp {
309    /// NO_PREFIX don't include any length info
310    NoPrefix = 0,
311    /// VAR_PROTO uses protobuf (and go-amino) varint encoding of the length
312    VarProto = 1,
313    /// VAR_RLP uses rlp int encoding of the length
314    VarRlp = 2,
315    /// FIXED32_BIG uses big-endian encoding of the length as a 32 bit integer
316    Fixed32Big = 3,
317    /// FIXED32_LITTLE uses little-endian encoding of the length as a 32 bit integer
318    Fixed32Little = 4,
319    /// FIXED64_BIG uses big-endian encoding of the length as a 64 bit integer
320    Fixed64Big = 5,
321    /// FIXED64_LITTLE uses little-endian encoding of the length as a 64 bit integer
322    Fixed64Little = 6,
323    /// REQUIRE_32_BYTES is like NONE, but will fail if the input is not exactly 32 bytes (sha256 output)
324    Require32Bytes = 7,
325    /// REQUIRE_64_BYTES is like NONE, but will fail if the input is not exactly 64 bytes (sha512 output)
326    Require64Bytes = 8,
327}
328impl LengthOp {
329    /// String value of the enum field names used in the ProtoBuf definition.
330    ///
331    /// The values are not transformed in any way and thus are considered stable
332    /// (if the ProtoBuf definition does not change) and safe for programmatic use.
333    pub fn as_str_name(&self) -> &'static str {
334        match self {
335            LengthOp::NoPrefix => "NO_PREFIX",
336            LengthOp::VarProto => "VAR_PROTO",
337            LengthOp::VarRlp => "VAR_RLP",
338            LengthOp::Fixed32Big => "FIXED32_BIG",
339            LengthOp::Fixed32Little => "FIXED32_LITTLE",
340            LengthOp::Fixed64Big => "FIXED64_BIG",
341            LengthOp::Fixed64Little => "FIXED64_LITTLE",
342            LengthOp::Require32Bytes => "REQUIRE_32_BYTES",
343            LengthOp::Require64Bytes => "REQUIRE_64_BYTES",
344        }
345    }
346    /// Creates an enum from field names used in the ProtoBuf definition.
347    pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
348        match value {
349            "NO_PREFIX" => Some(Self::NoPrefix),
350            "VAR_PROTO" => Some(Self::VarProto),
351            "VAR_RLP" => Some(Self::VarRlp),
352            "FIXED32_BIG" => Some(Self::Fixed32Big),
353            "FIXED32_LITTLE" => Some(Self::Fixed32Little),
354            "FIXED64_BIG" => Some(Self::Fixed64Big),
355            "FIXED64_LITTLE" => Some(Self::Fixed64Little),
356            "REQUIRE_32_BYTES" => Some(Self::Require32Bytes),
357            "REQUIRE_64_BYTES" => Some(Self::Require64Bytes),
358            _ => None,
359        }
360    }
361}