From a3480af9eb36d95a5d782df1393e995685d8841a Mon Sep 17 00:00:00 2001 From: hu55a1n1 Date: Tue, 19 Dec 2023 06:39:03 -0800 Subject: [PATCH] Verify merkle proofs --- utils/cw-prover/Cargo.lock | 495 +++++++++++++++++++++++++++++++++++- utils/cw-prover/Cargo.toml | 7 +- utils/cw-prover/src/main.rs | 141 +++++++++- 3 files changed, 631 insertions(+), 12 deletions(-) diff --git a/utils/cw-prover/Cargo.lock b/utils/cw-prover/Cargo.lock index abf21eb..20515b4 100644 --- a/utils/cw-prover/Cargo.lock +++ b/utils/cw-prover/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + [[package]] name = "anstream" version = "0.6.5" @@ -71,6 +80,28 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.41", +] + [[package]] name = "async-trait" version = "0.1.74" @@ -88,6 +119,51 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -109,6 +185,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.5" @@ -314,6 +396,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -355,7 +443,12 @@ version = "0.1.0" dependencies = [ "clap", "cosmrs", + "ibc-proto", + "ibc-relayer-types", + "ics23", + "prost", "serde_json", + "tendermint", "tendermint-rpc", "tokio", ] @@ -379,6 +472,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "digest" version = "0.9.0" @@ -497,12 +601,22 @@ dependencies = [ "subtle", ] +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "static_assertions", +] + [[package]] name = "flex-error" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" dependencies = [ + "anyhow", "eyre", "paste", ] @@ -636,13 +750,19 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.3" @@ -748,6 +868,79 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "ibc-proto" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cbf4cbe9e5113cc7c70f3208a7029b2205c629502cbb2ae7ea0a09a97d3005" +dependencies = [ + "base64 0.21.5", + "bytes", + "flex-error", + "ics23", + "prost", + "serde", + "subtle-encoding", + "tendermint-proto", + "tonic", +] + +[[package]] +name = "ibc-relayer-types" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c4ea7fe71d63645ff3fd83929abc3cc1cab1db8777a28a7df4643f021f334e4" +dependencies = [ + "bytes", + "derive_more", + "flex-error", + "ibc-proto", + "ics23", + "itertools 0.10.5", + "num-rational", + "primitive-types", + "prost", + "regex", + "serde", + "serde_derive", + "serde_json", + "subtle-encoding", + "tendermint", + "tendermint-light-client-verifier", + "tendermint-proto", + "time", + "uint", +] + +[[package]] +name = "ics23" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "661e2d6f79952a65bc92b1c81f639ebd37228dae6ff412a5aba7d474bdc4b957" +dependencies = [ + "anyhow", + "bytes", + "hex", + "informalsystems-pbjson", + "prost", + "ripemd", + "serde", + "sha2 0.10.8", + "sha3", +] + [[package]] name = "idna" version = "0.5.0" @@ -758,12 +951,31 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + [[package]] name = "indenter" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.1.0" @@ -771,7 +983,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.3", +] + +[[package]] +name = "informalsystems-pbjson" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4eecd90f87bea412eac91c6ef94f6b1e390128290898cbe14f2b926787ae1fb" +dependencies = [ + "base64 0.13.1", + "serde", ] [[package]] @@ -780,6 +1002,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.11.0" @@ -816,6 +1047,15 @@ dependencies = [ "sha2 0.10.8", ] +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + [[package]] name = "libc" version = "0.2.151" @@ -838,6 +1078,12 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "memchr" version = "2.6.4" @@ -870,6 +1116,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -881,6 +1138,28 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -1037,6 +1316,23 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-serde", + "uint", +] + [[package]] name = "proc-macro2" version = "1.0.70" @@ -1063,7 +1359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools", + "itertools 0.11.0", "proc-macro2", "quote", "syn 2.0.41", @@ -1087,6 +1383,27 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + [[package]] name = "rand_core" version = "0.6.4" @@ -1105,13 +1422,42 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "reqwest" version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -1214,7 +1560,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.5", ] [[package]] @@ -1227,6 +1573,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.16" @@ -1397,6 +1749,16 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1467,6 +1829,12 @@ dependencies = [ "der", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.10.0" @@ -1516,6 +1884,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -1582,6 +1956,19 @@ dependencies = [ "url", ] +[[package]] +name = "tendermint-light-client-verifier" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74994da9de4b1144837a367ca2c60c650f5526a7c1a54760a3020959b522e474" +dependencies = [ + "derive_more", + "flex-error", + "serde", + "tendermint", + "time", +] + [[package]] name = "tendermint-proto" version = "0.34.0" @@ -1714,6 +2101,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.2.0" @@ -1735,6 +2132,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -1758,6 +2166,59 @@ dependencies = [ "serde", ] +[[package]] +name = "tonic" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.5", + "bytes", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -1771,9 +2232,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.41", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -1795,6 +2268,18 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unicode-bidi" version = "0.3.14" diff --git a/utils/cw-prover/Cargo.toml b/utils/cw-prover/Cargo.toml index 525c330..22e289b 100644 --- a/utils/cw-prover/Cargo.toml +++ b/utils/cw-prover/Cargo.toml @@ -8,6 +8,11 @@ edition = "2021" [dependencies] clap = { version = "4.1.8", features = ["derive"] } cosmrs = "0.15.0" +ibc-proto = "=0.38.0" +ibc-relayer-types = "=0.26.4" +ics23 = "0.11.0" +prost = "0.12.3" +serde_json = "1.0.108" +tendermint = "0.34.0" tendermint-rpc = { version = "0.34.0", features = ["http-client"] } tokio = { version = "1.26.0", features = ["full"] } -serde_json = "1.0.108" \ No newline at end of file diff --git a/utils/cw-prover/src/main.rs b/utils/cw-prover/src/main.rs index c78cc00..5e8b13f 100644 --- a/utils/cw-prover/src/main.rs +++ b/utils/cw-prover/src/main.rs @@ -18,6 +18,18 @@ use std::error::Error; use clap::{Parser, Subcommand}; use cosmrs::AccountId; +use ibc_proto::{ + ibc::core::commitment::v1::MerkleProof as RawMerkleProof, ibc::core::commitment::v1::MerkleRoot, +}; +use ibc_relayer_types::{ + core::ics23_commitment::commitment::CommitmentRoot, + core::ics23_commitment::error::Error as ProofError, core::ics23_commitment::specs::ProofSpecs, +}; +use ics23::{ + calculate_existence_root, commitment_proof::Proof, verify_membership, CommitmentProof, + ProofSpec, +}; +use tendermint::merkle::proof::ProofOps as TendermintProof; use tendermint_rpc::{client::HttpClient as TmRpcClient, Client, HttpClientUrl}; #[derive(Debug, Parser)] @@ -67,17 +79,134 @@ async fn main() -> Result<(), Box> { }; let client = TmRpcClient::builder(rpc_url).build()?; - let latest_height = client.status().await?.sync_info.latest_block_height; + let status = client.status().await?; + let latest_height = status.sync_info.latest_block_height; let result = client - .abci_query(Some(path), data, Some(latest_height), true) + .abci_query( + Some(path), + data, + Some( + (latest_height.value() - 1) + .try_into() + .expect("infallible conversion"), + ), + true, + ) .await?; - println!( - "{}", - serde_json::to_string(&result).expect("infallible serializer") - ); + let proof = convert_tm_to_ics_merkle_proof(&result.proof.expect("queried with proof"))?; + proof.verify_membership( + &ProofSpecs::cosmos(), + CommitmentRoot::from_bytes(status.sync_info.latest_app_hash.as_bytes()).into(), + vec!["wasm".to_string().into_bytes(), result.key], + result.value.clone(), + 0, + )?; + + println!("{}", String::from_utf8(result.value)?); } }; Ok(()) } + +#[derive(Clone, Debug, PartialEq)] +struct MerkleProof { + proofs: Vec, +} + +/// Convert to ics23::CommitmentProof +impl From for MerkleProof { + fn from(proof: RawMerkleProof) -> Self { + Self { + proofs: proof.proofs, + } + } +} + +impl From for RawMerkleProof { + fn from(proof: MerkleProof) -> Self { + Self { + proofs: proof.proofs, + } + } +} + +impl MerkleProof { + pub fn verify_membership( + &self, + specs: &ProofSpecs, + root: MerkleRoot, + keys: Vec>, + value: Vec, + start_index: usize, + ) -> Result<(), ProofError> { + // validate arguments + if self.proofs.is_empty() { + return Err(ProofError::empty_merkle_proof()); + } + if root.hash.is_empty() { + return Err(ProofError::empty_merkle_root()); + } + let num = self.proofs.len(); + let ics23_specs = Vec::::from(specs.clone()); + if ics23_specs.len() != num { + return Err(ProofError::number_of_specs_mismatch()); + } + if keys.len() != num { + return Err(ProofError::number_of_keys_mismatch()); + } + if value.is_empty() { + return Err(ProofError::empty_verified_value()); + } + + let mut subroot = value.clone(); + let mut value = value; + + // keys are represented from root-to-leaf + for ((proof, spec), key) in self + .proofs + .iter() + .zip(ics23_specs.iter()) + .zip(keys.iter().rev()) + .skip(start_index) + { + match &proof.proof { + Some(Proof::Exist(existence_proof)) => { + subroot = + calculate_existence_root::(existence_proof) + .map_err(|_| ProofError::invalid_merkle_proof())?; + + if !verify_membership::( + proof, spec, &subroot, key, &value, + ) { + return Err(ProofError::verification_failure()); + } + value = subroot.clone(); + } + _ => return Err(ProofError::invalid_merkle_proof()), + } + } + + if root.hash != subroot { + return Err(ProofError::verification_failure()); + } + + Ok(()) + } +} + +fn convert_tm_to_ics_merkle_proof(tm_proof: &TendermintProof) -> Result { + let mut proofs = Vec::new(); + + for op in &tm_proof.ops { + let mut parsed = CommitmentProof { proof: None }; + + prost::Message::merge(&mut parsed, op.data.as_slice()) + .map_err(ProofError::commitment_proof_decoding_failed)?; + + proofs.push(parsed); + } + + Ok(MerkleProof::from(RawMerkleProof { proofs })) +}