informalsystems_ics23/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#[derive(Clone, PartialEq, ::prost::Message)]
22pub struct ExistenceProof {
23 #[prost(bytes = "vec", tag = "1")]
24 pub key: ::prost::alloc::vec::Vec<u8>,
25 #[prost(bytes = "vec", tag = "2")]
26 pub value: ::prost::alloc::vec::Vec<u8>,
27 #[prost(message, optional, tag = "3")]
28 pub leaf: ::core::option::Option<LeafOp>,
29 #[prost(message, repeated, tag = "4")]
30 pub path: ::prost::alloc::vec::Vec<InnerOp>,
31}
32///
33///NonExistenceProof takes a proof of two neighbors, one left of the desired key,
34///one right of the desired key. If both proofs are valid AND they are neighbors,
35///then there is no valid proof for the given key.
36#[derive(Clone, PartialEq, ::prost::Message)]
37pub struct NonExistenceProof {
38 /// TODO: remove this as unnecessary??? we prove a range
39 #[prost(bytes = "vec", tag = "1")]
40 pub key: ::prost::alloc::vec::Vec<u8>,
41 #[prost(message, optional, tag = "2")]
42 pub left: ::core::option::Option<ExistenceProof>,
43 #[prost(message, optional, tag = "3")]
44 pub right: ::core::option::Option<ExistenceProof>,
45}
46///
47///CommitmentProof is either an ExistenceProof or a NonExistenceProof, or a Batch of such messages
48#[derive(Clone, PartialEq, ::prost::Message)]
49pub struct CommitmentProof {
50 #[prost(oneof = "commitment_proof::Proof", tags = "1, 2, 3, 4")]
51 pub proof: ::core::option::Option<commitment_proof::Proof>,
52}
53/// Nested message and enum types in `CommitmentProof`.
54pub mod commitment_proof {
55 #[derive(Clone, PartialEq, ::prost::Oneof)]
56 pub enum Proof {
57 #[prost(message, tag = "1")]
58 Exist(super::ExistenceProof),
59 #[prost(message, tag = "2")]
60 Nonexist(super::NonExistenceProof),
61 #[prost(message, tag = "3")]
62 Batch(super::BatchProof),
63 #[prost(message, tag = "4")]
64 Compressed(super::CompressedBatchProof),
65 }
66}
67///*
68///LeafOp represents the raw key-value data we wish to prove, and
69///must be flexible to represent the internal transformation from
70///the original key-value pairs into the basis hash, for many existing
71///merkle trees.
72///
73///key and value are passed in. So that the signature of this operation is:
74///leafOp(key, value) -> output
75///
76///To process this, first prehash the keys and values if needed (ANY means no hash in this case):
77///hkey = prehashKey(key)
78///hvalue = prehashValue(value)
79///
80///Then combine the bytes, and hash it
81///output = hash(prefix || length(hkey) || hkey || length(hvalue) || hvalue)
82#[derive(Clone, PartialEq, ::prost::Message)]
83pub struct LeafOp {
84 #[prost(enumeration = "HashOp", tag = "1")]
85 pub hash: i32,
86 #[prost(enumeration = "HashOp", tag = "2")]
87 pub prehash_key: i32,
88 #[prost(enumeration = "HashOp", tag = "3")]
89 pub prehash_value: i32,
90 #[prost(enumeration = "LengthOp", tag = "4")]
91 pub length: i32,
92 /// prefix is a fixed bytes that may optionally be included at the beginning to differentiate
93 /// a leaf node from an inner node.
94 #[prost(bytes = "vec", tag = "5")]
95 pub prefix: ::prost::alloc::vec::Vec<u8>,
96}
97///*
98///InnerOp represents a merkle-proof step that is not a leaf.
99///It represents concatenating two children and hashing them to provide the next result.
100///
101///The result of the previous step is passed in, so the signature of this op is:
102///innerOp(child) -> output
103///
104///The result of applying InnerOp should be:
105///output = op.hash(op.prefix || child || op.suffix)
106///
107///where the || operator is concatenation of binary data,
108///and child is the result of hashing all the tree below this step.
109///
110///Any special data, like prepending child with the length, or prepending the entire operation with
111///some value to differentiate from leaf nodes, should be included in prefix and suffix.
112///If either of prefix or suffix is empty, we just treat it as an empty string
113#[derive(Clone, PartialEq, ::prost::Message)]
114pub struct InnerOp {
115 #[prost(enumeration = "HashOp", tag = "1")]
116 pub hash: i32,
117 #[prost(bytes = "vec", tag = "2")]
118 pub prefix: ::prost::alloc::vec::Vec<u8>,
119 #[prost(bytes = "vec", tag = "3")]
120 pub suffix: ::prost::alloc::vec::Vec<u8>,
121}
122///*
123///ProofSpec defines what the expected parameters are for a given proof type.
124///This can be stored in the client and used to validate any incoming proofs.
125///
126///verify(ProofSpec, Proof) -> Proof | Error
127///
128///As demonstrated in tests, if we don't fix the algorithm used to calculate the
129///LeafHash for a given tree, there are many possible key-value pairs that can
130///generate a given hash (by interpretting the preimage differently).
131///We need this for proper security, requires client knows a priori what
132///tree format server uses. But not in code, rather a configuration object.
133#[derive(Clone, PartialEq, ::prost::Message)]
134pub struct ProofSpec {
135 /// any field in the ExistenceProof must be the same as in this spec.
136 /// except Prefix, which is just the first bytes of prefix (spec can be longer)
137 #[prost(message, optional, tag = "1")]
138 pub leaf_spec: ::core::option::Option<LeafOp>,
139 #[prost(message, optional, tag = "2")]
140 pub inner_spec: ::core::option::Option<InnerSpec>,
141 /// max_depth (if > 0) is the maximum number of InnerOps allowed (mainly for fixed-depth tries)
142 #[prost(int32, tag = "3")]
143 pub max_depth: i32,
144 /// min_depth (if > 0) is the minimum number of InnerOps allowed (mainly for fixed-depth tries)
145 #[prost(int32, tag = "4")]
146 pub min_depth: i32,
147}
148///
149///InnerSpec contains all store-specific structure info to determine if two proofs from a
150///given store are neighbors.
151///
152///This enables:
153///
154///isLeftMost(spec: InnerSpec, op: InnerOp)
155///isRightMost(spec: InnerSpec, op: InnerOp)
156///isLeftNeighbor(spec: InnerSpec, left: InnerOp, right: InnerOp)
157#[derive(Clone, PartialEq, ::prost::Message)]
158pub struct InnerSpec {
159 /// Child order is the ordering of the children node, must count from 0
160 /// iavl tree is [0, 1] (left then right)
161 /// merk is [0, 2, 1] (left, right, here)
162 #[prost(int32, repeated, tag = "1")]
163 pub child_order: ::prost::alloc::vec::Vec<i32>,
164 #[prost(int32, tag = "2")]
165 pub child_size: i32,
166 #[prost(int32, tag = "3")]
167 pub min_prefix_length: i32,
168 #[prost(int32, tag = "4")]
169 pub max_prefix_length: i32,
170 /// empty child is the prehash image that is used when one child is nil (eg. 20 bytes of 0)
171 #[prost(bytes = "vec", tag = "5")]
172 pub empty_child: ::prost::alloc::vec::Vec<u8>,
173 /// hash is the algorithm that must be used for each InnerOp
174 #[prost(enumeration = "HashOp", tag = "6")]
175 pub hash: i32,
176}
177///
178///BatchProof is a group of multiple proof types than can be compressed
179#[derive(Clone, PartialEq, ::prost::Message)]
180pub struct BatchProof {
181 #[prost(message, repeated, tag = "1")]
182 pub entries: ::prost::alloc::vec::Vec<BatchEntry>,
183}
184/// Use BatchEntry not CommitmentProof, to avoid recursion
185#[derive(Clone, PartialEq, ::prost::Message)]
186pub struct BatchEntry {
187 #[prost(oneof = "batch_entry::Proof", tags = "1, 2")]
188 pub proof: ::core::option::Option<batch_entry::Proof>,
189}
190/// Nested message and enum types in `BatchEntry`.
191pub mod batch_entry {
192 #[derive(Clone, PartialEq, ::prost::Oneof)]
193 pub enum Proof {
194 #[prost(message, tag = "1")]
195 Exist(super::ExistenceProof),
196 #[prost(message, tag = "2")]
197 Nonexist(super::NonExistenceProof),
198 }
199}
200//***** all items here are compressed forms ******
201
202#[derive(Clone, PartialEq, ::prost::Message)]
203pub struct CompressedBatchProof {
204 #[prost(message, repeated, tag = "1")]
205 pub entries: ::prost::alloc::vec::Vec<CompressedBatchEntry>,
206 #[prost(message, repeated, tag = "2")]
207 pub lookup_inners: ::prost::alloc::vec::Vec<InnerOp>,
208}
209/// Use BatchEntry not CommitmentProof, to avoid recursion
210#[derive(Clone, PartialEq, ::prost::Message)]
211pub struct CompressedBatchEntry {
212 #[prost(oneof = "compressed_batch_entry::Proof", tags = "1, 2")]
213 pub proof: ::core::option::Option<compressed_batch_entry::Proof>,
214}
215/// Nested message and enum types in `CompressedBatchEntry`.
216pub mod compressed_batch_entry {
217 #[derive(Clone, PartialEq, ::prost::Oneof)]
218 pub enum Proof {
219 #[prost(message, tag = "1")]
220 Exist(super::CompressedExistenceProof),
221 #[prost(message, tag = "2")]
222 Nonexist(super::CompressedNonExistenceProof),
223 }
224}
225#[derive(Clone, PartialEq, ::prost::Message)]
226pub struct CompressedExistenceProof {
227 #[prost(bytes = "vec", tag = "1")]
228 pub key: ::prost::alloc::vec::Vec<u8>,
229 #[prost(bytes = "vec", tag = "2")]
230 pub value: ::prost::alloc::vec::Vec<u8>,
231 #[prost(message, optional, tag = "3")]
232 pub leaf: ::core::option::Option<LeafOp>,
233 /// these are indexes into the lookup_inners table in CompressedBatchProof
234 #[prost(int32, repeated, tag = "4")]
235 pub path: ::prost::alloc::vec::Vec<i32>,
236}
237#[derive(Clone, PartialEq, ::prost::Message)]
238pub struct CompressedNonExistenceProof {
239 /// TODO: remove this as unnecessary??? we prove a range
240 #[prost(bytes = "vec", tag = "1")]
241 pub key: ::prost::alloc::vec::Vec<u8>,
242 #[prost(message, optional, tag = "2")]
243 pub left: ::core::option::Option<CompressedExistenceProof>,
244 #[prost(message, optional, tag = "3")]
245 pub right: ::core::option::Option<CompressedExistenceProof>,
246}
247#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
248#[repr(i32)]
249pub enum HashOp {
250 /// NO_HASH is the default if no data passed. Note this is an illegal argument some places.
251 NoHash = 0,
252 Sha256 = 1,
253 Sha512 = 2,
254 Keccak = 3,
255 Ripemd160 = 4,
256 /// ripemd160(sha256(x))
257 Bitcoin = 5,
258 Sha512256 = 6,
259}
260///*
261///LengthOp defines how to process the key and value of the LeafOp
262///to include length information. After encoding the length with the given
263///algorithm, the length will be prepended to the key and value bytes.
264///(Each one with it's own encoded length)
265#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
266#[repr(i32)]
267pub enum LengthOp {
268 /// NO_PREFIX don't include any length info
269 NoPrefix = 0,
270 /// VAR_PROTO uses protobuf (and go-amino) varint encoding of the length
271 VarProto = 1,
272 /// VAR_RLP uses rlp int encoding of the length
273 VarRlp = 2,
274 /// FIXED32_BIG uses big-endian encoding of the length as a 32 bit integer
275 Fixed32Big = 3,
276 /// FIXED32_LITTLE uses little-endian encoding of the length as a 32 bit integer
277 Fixed32Little = 4,
278 /// FIXED64_BIG uses big-endian encoding of the length as a 64 bit integer
279 Fixed64Big = 5,
280 /// FIXED64_LITTLE uses little-endian encoding of the length as a 64 bit integer
281 Fixed64Little = 6,
282 /// REQUIRE_32_BYTES is like NONE, but will fail if the input is not exactly 32 bytes (sha256 output)
283 Require32Bytes = 7,
284 /// REQUIRE_64_BYTES is like NONE, but will fail if the input is not exactly 64 bytes (sha512 output)
285 Require64Bytes = 8,
286}