diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 2f89c85d..0a5d5291 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -59,7 +59,7 @@ jobs: - uses: actions-rs/cargo@v1 with: command: doc - args: --all-features --release + args: --all-features --no-deps --release clippy_all_features: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 11a6ad6f..0f71f74c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target +/contracts .idea/ target-path diff --git a/Cargo.lock b/Cargo.lock index 1fa9d9ca..59458a94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "gimli", + "gimli 0.28.1", ] [[package]] @@ -19,9 +19,20 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.6" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", @@ -40,20 +51,19 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0fac0fc16baf1f63f78b47c3d24718f3619b0714076f6a02957d808d52cbef" +checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ "arrayvec", "bytes", - "smol_str", ] [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ "anstyle", "anstyle-parse", @@ -65,9 +75,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" [[package]] name = "anstyle-parse" @@ -99,9 +109,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "ark-ff" @@ -261,30 +271,29 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -373,9 +382,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -386,9 +395,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basecoin-app" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=25d86e6#25d86e6c2a2dc3472e718b045597a7c4bd37dff7" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=d093cb1#d093cb13dd6a2f62e25f69849e36e6368f49ecf6" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "basecoin-store", "clap", "cosmrs", @@ -404,6 +413,7 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.10.8", + "sov-celestia-client 0.1.0 (git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1)", "tendermint 0.34.0", "tendermint-proto 0.34.0", "tendermint-rpc", @@ -420,13 +430,9 @@ dependencies = [ [[package]] name = "basecoin-store" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=25d86e6#25d86e6c2a2dc3472e718b045597a7c4bd37dff7" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=d093cb1#d093cb13dd6a2f62e25f69849e36e6368f49ecf6" dependencies = [ - "base64 0.21.5", - "derive_more", "displaydoc", - "ed25519", - "ibc", "ics23", "prost", "serde", @@ -488,7 +494,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -500,7 +506,7 @@ dependencies = [ "bs58", "hmac", "k256", - "rand_core", + "rand_core 0.6.4", "ripemd", "sha2 0.10.8", "subtle", @@ -530,9 +536,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitvec" @@ -564,6 +570,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bnum" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9008b6bb9fc80b5277f2fe481c09e828743d9151203e804583eb4c9e15b31d" + [[package]] name = "borsh" version = "0.10.3" @@ -631,6 +643,28 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytecheck" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -699,7 +733,7 @@ name = "celestia-types" version = "0.1.0" source = "git+https://github.com/eigerco/celestia-node-rs.git?rev=66b7c6c#66b7c6cd58213c0cbf79207ba549cef82764ddca" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bech32", "bytes", "celestia-proto", @@ -747,9 +781,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", @@ -758,9 +792,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.11" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ "clap_builder", "clap_derive", @@ -768,9 +802,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.11" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ "anstream", "anstyle", @@ -788,7 +822,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -797,6 +831,12 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +[[package]] +name = "clru" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" + [[package]] name = "colorchoice" version = "1.0.0" @@ -815,9 +855,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const-rollup-config" @@ -875,6 +915,19 @@ dependencies = [ "memchr", ] +[[package]] +name = "corosensei" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "scopeguard", + "windows-sys 0.33.0", +] + [[package]] name = "cosmos-sdk-proto" version = "0.20.0" @@ -897,7 +950,7 @@ dependencies = [ "ecdsa", "eyre", "k256", - "rand_core", + "rand_core 0.6.4", "serde", "serde_json", "signature", @@ -906,15 +959,235 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cosmwasm-crypto" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6aa9f904de106fa16443ad14ec2abe75e94ba003bb61c681c0e43d4c58d2a" +dependencies = [ + "digest 0.10.7", + "ecdsa", + "ed25519-zebra", + "k256", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40abec852f3d4abec6d44ead9a58b78325021a1ead1e7229c3471414e57b2e49" +dependencies = [ + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-schema" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b166215fbfe93dc5575bae062aa57ae7bb41121cffe53bac33b033257949d2a9" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf12f8e20bb29d1db66b7ca590bc2f670b548d21e9be92499bc0f9022a994a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-std" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad011ae7447188e26e4a7dbca2fcd0fc186aa21ae5c86df0503ea44c78f9e469" +dependencies = [ + "base64 0.21.7", + "bech32", + "bnum", + "cosmwasm-crypto", + "cosmwasm-derive", + "derivative", + "forward_ref", + "hex", + "schemars", + "serde", + "serde-json-wasm 0.5.2", + "sha2 0.10.8", + "static_assertions", + "thiserror", +] + +[[package]] +name = "cosmwasm-vm" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ebdf59ae3b9fe66d1eb845cf69aa537c77107d816452595c5796c332af061f" +dependencies = [ + "bitflags 1.3.2", + "bytecheck", + "bytes", + "clru", + "cosmwasm-crypto", + "cosmwasm-std", + "crc32fast", + "derivative", + "enumset", + "hex", + "schemars", + "serde", + "serde_json", + "sha2 0.10.8", + "thiserror", + "wasmer", + "wasmer-middlewares", +] + [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] +[[package]] +name = "cranelift-bforest" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" +dependencies = [ + "arrayvec", + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-egraph", + "cranelift-entity", + "cranelift-isle", + "gimli 0.26.2", + "log", + "regalloc2", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" + +[[package]] +name = "cranelift-egraph" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" +dependencies = [ + "cranelift-entity", + "fxhash", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "log", + "smallvec", +] + +[[package]] +name = "cranelift-entity" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" + +[[package]] +name = "cranelift-frontend" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + [[package]] name = "crunchy" version = "0.2.2" @@ -928,7 +1201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -943,6 +1216,19 @@ dependencies = [ "typenum", ] +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + [[package]] name = "curve25519-dalek" version = "4.1.1" @@ -968,7 +1254,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -979,16 +1265,16 @@ checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" dependencies = [ "byteorder", "digest 0.9.0", - "rand_core", + "rand_core 0.6.4", "subtle-ng", "zeroize", ] [[package]] name = "darling" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "da01daa5f6d41c91358398e8db4dde38e292378da1f28300b59ef4732b879454" dependencies = [ "darling_core", "darling_macro", @@ -996,27 +1282,39 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "f44f6238b948a3c6c3073cdf53bb0c2d5e024ee27e0f35bfe9d556a12395808a" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "0d2d88bd93979b1feb760a6b5c531ac5ba06bd63e74894c377af02faee07b9cd" dependencies = [ "darling_core", "quote", - "syn 2.0.41", + "syn 2.0.48", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] @@ -1057,9 +1355,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -1117,7 +1415,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -1126,6 +1424,32 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +[[package]] +name = "dynasm" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add9a102807b524ec050363f09e06f1504214b0e1c7797f64261c891022dce8b" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "lazy_static", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dynasmrt" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" +dependencies = [ + "byteorder", + "dynasm", + "memmap2 0.5.10", +] + [[package]] name = "ecdsa" version = "0.16.9" @@ -1159,22 +1483,38 @@ checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" dependencies = [ "curve25519-dalek-ng", "hex", - "rand_core", + "rand_core 0.6.4", "sha2 0.9.9", "zeroize", ] [[package]] name = "ed25519-dalek" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" dependencies = [ - "curve25519-dalek", + "curve25519-dalek 4.1.1", "ed25519", - "rand_core", + "rand_core 0.6.4", "serde", "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", "zeroize", ] @@ -1197,7 +1537,7 @@ dependencies = [ "generic-array", "group", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -1212,6 +1552,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-iterator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "enum_dispatch" version = "0.3.12" @@ -1221,7 +1581,28 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", +] + +[[package]] +name = "enumset" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.48", ] [[package]] @@ -1256,6 +1637,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "fastrand" version = "2.0.1" @@ -1279,7 +1666,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1332,6 +1719,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + [[package]] name = "funty" version = "2.0.0" @@ -1340,9 +1733,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1355,9 +1748,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1365,15 +1758,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1382,32 +1775,32 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" @@ -1421,9 +1814,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1437,6 +1830,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1450,9 +1852,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", @@ -1461,6 +1863,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + [[package]] name = "gimli" version = "0.28.1" @@ -1526,7 +1939,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1552,9 +1965,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -1562,7 +1975,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.1", "slab", "tokio", "tokio-util 0.7.10", @@ -1574,6 +1987,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.7", +] [[package]] name = "hashbrown" @@ -1581,7 +1997,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash", + "ahash 0.8.7", ] [[package]] @@ -1608,9 +2024,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "hex" @@ -1632,11 +2048,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1675,9 +2091,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1690,7 +2106,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -1728,8 +2144,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08258907d8b5b20b5de6eb064d17bc45fd4f48e64e96efbe62e035150a7d150e" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-apps", "ibc-clients", @@ -1742,19 +2157,17 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038cacbeb1658ee4295449676a4870fdc79b1edbcb5905f6ad64e68f200d1488" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-app-transfer-types", "ibc-core", - "serde-json-wasm", + "serde-json-wasm 1.0.1", ] [[package]] name = "ibc-app-transfer-types" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d89a3a0233a4e5927b116a9e6dc222cbdab0cf0fd7f0dee6308c8eefc00bb63" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "borsh", "derive_more", @@ -1770,8 +2183,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61d7aafdb984fcfbbc9268fd9fa924964c2f5dfd036c5bbe3695cf28b2b2f0ea" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-app-transfer", ] @@ -1779,8 +2191,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "189dd739853e9cef400b4cb91e58ba261b85f17002caa862a7af924237d14879" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-client-tendermint-types", "ibc-core-client", @@ -1796,8 +2207,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc6e8ff8d3a4477bfe8bc97f100dd7f13a7710e9de6e1541b76d33fa6a472ef" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -1811,20 +2221,34 @@ dependencies = [ "tendermint-proto 0.34.0", ] +[[package]] +name = "ibc-client-wasm-types" +version = "0.49.1" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" +dependencies = [ + "base64 0.21.7", + "cosmwasm-schema", + "displaydoc", + "ibc-core-client", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "serde", +] + [[package]] name = "ibc-clients" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875afb9fd11cfeaa23de0234b5a353781fb18b4c4fb165719eb29a9c69a3fae6" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-client-tendermint", + "ibc-client-wasm-types", ] [[package]] name = "ibc-core" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91444e562962b9dab6f44117cb8a20a2a681733108343c4d9fbf89c506fa8081" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -1833,14 +2257,14 @@ dependencies = [ "ibc-core-handler", "ibc-core-host", "ibc-core-router", + "ibc-derive", "ibc-primitives", ] [[package]] name = "ibc-core-channel" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6279ffdba5f9ea605688d2e769f5cefecd77c888d9b9d001862d2d9dfa16ee4d" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -1855,8 +2279,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445888ebca9e2e72a3c03a758254887ef5ef9a1bae6baf204f2b1f6f656f70ff" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "borsh", "derive_more", @@ -1877,8 +2300,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8744739af25917b484d1030712af53331e62f0477b8411bd9ce5691c46a1b6dc" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -1891,8 +2313,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a87a59fa85ceb0bcf5973e2327094605d2a0ef7f51e519a47f242d6d1322fe0" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "derive_more", "displaydoc", @@ -1900,7 +2321,6 @@ dependencies = [ "ibc-core-commitment-types", "ibc-core-handler-types", "ibc-core-host-types", - "ibc-derive", "ibc-primitives", "subtle-encoding", "tendermint 0.34.0", @@ -1909,8 +2329,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20be8f5b66c483810ff3bda67db59e5dedeeb5cef0edd18dc08f8c1f32804a2d" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "borsh", "derive_more", @@ -1928,8 +2347,7 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f784dd0a1d15430dee55558b3f7d270d3a52539ad20e1e4530bd60959e590324" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "borsh", "derive_more", @@ -1945,8 +2363,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0075f40dae0d9d18b3e4335db78ec7cda962ba2ed791673d9015e636810b04fb" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-core-client", "ibc-core-connection-types", @@ -1958,8 +2375,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b27882397e2d105ddc57718b18c74c5b6db76ed40c97c5c53dc1620c99d0554c" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "borsh", "derive_more", @@ -1978,8 +2394,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd99fb91b3a2a4fe410a7d3f91a177f0cec32e4b29d878a334503d2341ea226" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -1994,8 +2409,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf5890e3a731ba6f615853858b73f5db91f5f31648208250e64473c44d90e36" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "borsh", "derive_more", @@ -2017,8 +2431,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0e4e1f9e595af3f371e5cbeca6916e23eab1d2c172591fab51c21c0307642d7" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "derive_more", "displaydoc", @@ -2036,8 +2449,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d7c5228389e154b3a5ba9cc1c33eb481855aa8ae732a9135cb205a0acbca0a" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "derive_more", "displaydoc", @@ -2060,8 +2472,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02ecf33c6a328b922b819c336a85a8ca9ff404c64ce024d01181754b3c2671f1" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "borsh", "derive_more", @@ -2074,8 +2485,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bc590d9460935782d15f9ec307fa705847f88ca0a271c417f8b61ac4b7b55e0" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "derive_more", "displaydoc", @@ -2089,8 +2499,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81c009c007673cfc677b120577dd11d95e8a7613eed5a8f0b9a9f0a23f9a4895" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "borsh", "derive_more", @@ -2107,20 +2516,17 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cac1e3c7ab92abf785bb86675bdc02e3d67e9e4624c1d513e83ff3098f9c461" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ - "darling", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "ibc-primitives" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff38e0e738c53cb38fe8a7b52571a7205c3014fa194dcebc018b5f0528258cc5" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "borsh", "derive_more", @@ -2135,15 +2541,15 @@ dependencies = [ [[package]] name = "ibc-proto" -version = "0.39.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8a8b1356652b9f160f5a010dd6b084675b8a28e163bf2b41ca5abecf27d9701" +version = "0.41.0" +source = "git+https://github.com/cosmos/ibc-proto-rs.git?rev=d1daaab#d1daaab67e41b3519a86febf7f62ba2ad24120ce" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "borsh", "bytes", "flex-error", "ics23", + "informalsystems-pbjson 0.7.0", "prost", "schemars", "serde", @@ -2155,8 +2561,7 @@ dependencies = [ [[package]] name = "ibc-query" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6b842c18a030e4ad39f577739d0cce3ae47016b94ec59a8d200d326088bf51e" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "displaydoc", "ibc", @@ -2167,8 +2572,7 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.49.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d5f48ab07acbbf1f05fdc05ebe128610c83c21b9d3381a75cfeec7427c0bd5" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=1ef8777#1ef87778b4578f1e13b1370d9a3ac24995c988b4" dependencies = [ "derive_more", "displaydoc", @@ -2191,7 +2595,7 @@ dependencies = [ "anyhow", "bytes", "hex", - "informalsystems-pbjson", + "informalsystems-pbjson 0.6.0", "prost", "ripemd", "serde", @@ -2262,9 +2666,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -2280,6 +2684,16 @@ dependencies = [ "serde", ] +[[package]] +name = "informalsystems-pbjson" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa4a0980c8379295100d70854354e78df2ee1c6ca0f96ffe89afeb3140e3a3d" +dependencies = [ + "base64 0.21.7", + "serde", +] + [[package]] name = "instant" version = "0.1.12" @@ -2354,9 +2768,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -2524,21 +2938,23 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", + "once_cell", "sha2 0.10.8", + "signature", ] [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -2553,22 +2969,28 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" name = "lazycell" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -2595,9 +3017,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.12" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" dependencies = [ "cc", "pkg-config", @@ -2606,9 +3028,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -2636,6 +3058,15 @@ dependencies = [ "libc", ] +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + [[package]] name = "matchers" version = "0.1.0" @@ -2653,9 +3084,36 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "memmap2" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memmap2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] [[package]] name = "mime" @@ -2695,6 +3153,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" +[[package]] +name = "more-asserts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" + [[package]] name = "multibase" version = "0.9.1" @@ -2822,9 +3286,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -2949,9 +3413,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" dependencies = [ "memchr", "thiserror", @@ -2965,27 +3429,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.1.0", + "indexmap 2.2.1", ] [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -3012,15 +3476,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "platforms" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" [[package]] name = "powerfmt" @@ -3036,12 +3500,12 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -3110,9 +3574,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -3139,7 +3603,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.1", + "bitflags 2.4.2", "lazy_static", "num-traits", "rand", @@ -3178,7 +3642,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.41", + "syn 2.0.48", "tempfile", "which", ] @@ -3193,7 +3657,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -3205,6 +3669,26 @@ dependencies = [ "prost", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -3213,9 +3697,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -3234,7 +3718,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3244,9 +3728,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", ] +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + [[package]] name = "rand_core" version = "0.6.4" @@ -3262,7 +3752,27 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rayon" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", ] [[package]] @@ -3274,15 +3784,27 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "regalloc2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" +dependencies = [ + "fxhash", + "log", + "slice-group-by", + "smallvec", +] + [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.5", "regex-syntax 0.8.2", ] @@ -3297,9 +3819,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -3318,13 +3840,34 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "region" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach", + "winapi", +] + +[[package]] +name = "rend" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +dependencies = [ + "bytecheck", +] + [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -3391,6 +3934,36 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "rkyv" +version = "0.7.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527a97cdfef66f65998b5f3b637c26f5a5ec09cc52a3f9932313ac645f4190f5" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid 1.7.0", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5c462a1328c8e67e4d6dbad1eb0355dd43e8ab432c6e227a43657f16ade5033" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rlp" version = "0.5.2" @@ -3480,16 +4053,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.20", + "semver 1.0.21", ] [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", @@ -3526,7 +4099,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] @@ -3574,11 +4147,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3627,6 +4200,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "sec1" version = "0.7.3" @@ -3664,6 +4243,12 @@ dependencies = [ "libc", ] +[[package]] +name = "self_cell" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" + [[package]] name = "semver" version = "0.11.0" @@ -3675,9 +4260,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "semver-parser" @@ -3696,40 +4281,60 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde-json-wasm" -version = "1.0.0" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" +dependencies = [ + "serde", +] + +[[package]] +name = "serde-json-wasm" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" +dependencies = [ + "serde", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c37d03f3b0f6b5f77c11af1e7c772de1c9af83e50bef7bb6069601900ba67b" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" dependencies = [ + "js-sys", "serde", + "wasm-bindgen", ] [[package]] name = "serde_bytes" -version = "0.11.12" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -3745,9 +4350,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", @@ -3756,20 +4361,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "serde_spanned" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -3842,11 +4447,21 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared-buffer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" +dependencies = [ + "bytes", + "memmap2 0.6.2", +] + [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" @@ -3864,9 +4479,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core", + "rand_core 0.6.4", ] +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + [[package]] name = "simple-error" version = "0.2.3" @@ -3883,29 +4504,16 @@ dependencies = [ ] [[package]] -name = "smallvec" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] -name = "smol_str" -version = "0.2.0" +name = "slice-group-by" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" -dependencies = [ - "serde", -] +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] -name = "socket2" -version = "0.4.10" +name = "smallvec" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" @@ -3934,50 +4542,143 @@ dependencies = [ ] [[package]] -name = "sov-bank" -version = "0.3.0" -source = "git+https://github.com/informalsystems/sovereign-sdk.git?rev=6e22b4c#6e22b4c91bce64b70cb1624770ce10a773c36a08" +name = "sov-bank" +version = "0.3.0" +source = "git+https://github.com/informalsystems/sovereign-sdk.git?rev=6e22b4c#6e22b4c91bce64b70cb1624770ce10a773c36a08" +dependencies = [ + "anyhow", + "borsh", + "clap", + "jsonrpsee", + "schemars", + "serde", + "serde_json", + "sov-modules-api", + "sov-state", + "thiserror", +] + +[[package]] +name = "sov-celestia-adapter" +version = "0.3.0" +source = "git+https://github.com/informalsystems/sovereign-sdk.git?rev=6e22b4c#6e22b4c91bce64b70cb1624770ce10a773c36a08" +dependencies = [ + "anyhow", + "async-trait", + "base64 0.21.7", + "bech32", + "borsh", + "celestia-proto", + "celestia-rpc", + "celestia-types", + "futures", + "hex", + "jsonrpsee", + "nmt-rs", + "pin-project", + "prost", + "serde", + "serde_json", + "sha2 0.10.8", + "sov-rollup-interface", + "tendermint 0.32.0", + "tendermint-proto 0.32.0", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "sov-celestia-client" +version = "0.1.0" +dependencies = [ + "derive_more", + "ibc-client-tendermint", + "ibc-core", + "ics23", + "prost", + "schemars", + "serde", + "sov-celestia-client-types 0.1.0", + "tendermint 0.34.0", + "tendermint-light-client-verifier", + "tendermint-proto 0.34.0", + "typed-builder", +] + +[[package]] +name = "sov-celestia-client" +version = "0.1.0" +source = "git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1#b9ac0b1382ecf325c04a959583de4221d79cc1ab" +dependencies = [ + "derive_more", + "ibc-client-tendermint", + "ibc-core", + "ics23", + "prost", + "serde", + "sov-celestia-client-types 0.1.0 (git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1)", + "tendermint 0.34.0", + "tendermint-light-client-verifier", + "tendermint-proto 0.34.0", +] + +[[package]] +name = "sov-celestia-client-cw" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-vm", + "derive_more", + "ibc-client-tendermint", + "ibc-client-wasm-types", + "ibc-core", + "ibc-proto", + "prost", + "serde", + "sov-celestia-client 0.1.0", + "test-log", + "thiserror", + "tracing-subscriber", +] + +[[package]] +name = "sov-celestia-client-types" +version = "0.1.0" dependencies = [ - "anyhow", - "borsh", - "clap", - "jsonrpsee", + "base64 0.21.7", + "bytes", + "derive_more", + "ibc-client-tendermint", + "ibc-core", + "ibc-proto", + "ics23", + "prost", "schemars", "serde", - "serde_json", - "sov-modules-api", - "sov-state", - "thiserror", + "tendermint 0.34.0", + "tendermint-light-client-verifier", + "tendermint-proto 0.34.0", ] [[package]] -name = "sov-celestia-adapter" -version = "0.3.0" -source = "git+https://github.com/informalsystems/sovereign-sdk.git?rev=6e22b4c#6e22b4c91bce64b70cb1624770ce10a773c36a08" +name = "sov-celestia-client-types" +version = "0.1.0" +source = "git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1#b9ac0b1382ecf325c04a959583de4221d79cc1ab" dependencies = [ - "anyhow", - "async-trait", - "base64 0.21.5", - "bech32", - "borsh", - "celestia-proto", - "celestia-rpc", - "celestia-types", - "futures", - "hex", - "jsonrpsee", - "nmt-rs", - "pin-project", + "base64 0.21.7", + "bytes", + "derive_more", + "ibc-client-tendermint", + "ibc-core", + "ibc-proto", + "ics23", "prost", "serde", - "serde_json", - "sha2 0.10.8", - "sov-rollup-interface", - "tendermint 0.32.0", - "tendermint-proto 0.32.0", - "thiserror", - "tokio", - "tracing", + "tendermint 0.34.0", + "tendermint-light-client-verifier", + "tendermint-proto 0.34.0", ] [[package]] @@ -4027,8 +4728,37 @@ dependencies = [ "schemars", "serde", "serde_json", + "sov-celestia-client 0.1.0", + "sov-chain-state", + "sov-ibc-transfer 0.1.0", + "sov-modules-api", + "sov-modules-macros", + "sov-rollup-interface", + "sov-state", + "tendermint 0.34.0", + "thiserror", +] + +[[package]] +name = "sov-ibc" +version = "0.1.0" +source = "git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1#b9ac0b1382ecf325c04a959583de4221d79cc1ab" +dependencies = [ + "anyhow", + "borsh", + "derive_more", + "ibc-app-transfer", + "ibc-client-tendermint", + "ibc-core", + "ibc-query", + "jsonrpsee", + "prost", + "schemars", + "serde", + "serde_json", + "sov-celestia-client 0.1.0 (git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1)", "sov-chain-state", - "sov-ibc-transfer", + "sov-ibc-transfer 0.1.0 (git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1)", "sov-modules-api", "sov-modules-macros", "sov-rollup-interface", @@ -4043,13 +4773,15 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "base64 0.21.5", + "base64 0.21.7", "basecoin-app", "basecoin-store", "borsh", "const-rollup-config", + "hex", "ibc-app-transfer", "ibc-client-tendermint", + "ibc-client-wasm-types", "ibc-core", "ibc-core-host-cosmos", "ibc-query", @@ -4061,9 +4793,10 @@ dependencies = [ "sha2 0.10.8", "sov-bank", "sov-celestia-adapter", + "sov-celestia-client 0.1.0 (git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1)", "sov-chain-state", - "sov-ibc", - "sov-ibc-transfer", + "sov-ibc 0.1.0 (git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1)", + "sov-ibc-transfer 0.1.0 (git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1)", "sov-mock-da", "sov-modules-api", "sov-rollup-interface", @@ -4086,7 +4819,30 @@ name = "sov-ibc-transfer" version = "0.1.0" dependencies = [ "anyhow", - "base64 0.21.5", + "base64 0.21.7", + "borsh", + "ibc-app-transfer", + "ibc-core", + "jsonrpsee", + "prost", + "schemars", + "serde", + "serde_json", + "sov-bank", + "sov-modules-api", + "sov-modules-macros", + "sov-rollup-interface", + "thiserror", + "uint", +] + +[[package]] +name = "sov-ibc-transfer" +version = "0.1.0" +source = "git+https://github.com/informalsystems/sovereign-ibc.git?rev=b9ac0b1#b9ac0b1382ecf325c04a959583de4221d79cc1ab" +dependencies = [ + "anyhow", + "base64 0.21.7", "borsh", "ibc-app-transfer", "ibc-core", @@ -4251,6 +5007,12 @@ dependencies = [ "der", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -4297,9 +5059,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.41" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -4351,17 +5113,23 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "target-lexicon" +version = "0.12.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" + [[package]] name = "tempfile" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4500,7 +5268,7 @@ dependencies = [ "peg", "pin-project", "reqwest", - "semver 1.0.20", + "semver 1.0.21", "serde", "serde_bytes", "serde_json", @@ -4514,7 +5282,7 @@ dependencies = [ "tokio", "tracing", "url", - "uuid", + "uuid 0.8.2", "walkdir", ] @@ -4562,27 +5330,27 @@ checksum = "7ba277e77219e9eea169e8508942db1bf5d8a41ff2db9b20aab5a5aadc9fa25d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -4597,9 +5365,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "powerfmt", @@ -4616,9 +5384,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -4640,9 +5408,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", @@ -4652,7 +5420,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -4675,7 +5443,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -4765,7 +5533,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -4776,7 +5544,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "serde", "serde_spanned", "toml_datetime", @@ -4792,7 +5560,7 @@ dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.21.5", + "base64 0.21.7", "bytes", "h2", "http", @@ -4895,7 +5663,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -4945,22 +5713,22 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typed-builder" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47c0496149861b7c95198088cbf36645016b1a0734cf350c50e2a38e070f38a" +checksum = "444d8748011b93cb168770e8092458cb0f8854f931ff82fdf6ddfbd72a9c933e" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982ee4197351b5c9782847ef5ec1fdcaf50503fb19d68f9771adae314e72b492" +checksum = "563b3b88238ec95680aef36bdece66896eaa7ce3c0f1b4f39d38fb2435261352" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -4995,9 +5763,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -5055,6 +5823,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +[[package]] +name = "uuid" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" + [[package]] name = "valuable" version = "0.1.0" @@ -5109,9 +5883,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -5119,24 +5893,47 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-downcast" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dac026d43bcca6e7ce1c0956ba68f59edf6403e8e930a5d891be72c31a44340" +dependencies = [ + "js-sys", + "once_cell", + "wasm-bindgen", + "wasm-bindgen-downcast-macros", +] + +[[package]] +name = "wasm-bindgen-downcast-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", @@ -5146,9 +5943,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5156,28 +5953,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "wasm-bindgen-test" -version = "0.3.39" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403" +checksum = "139bd73305d50e1c1c4333210c0db43d989395b64a237bd35c10ef3832a7f70c" dependencies = [ "console_error_panic_hook", "js-sys", @@ -5189,20 +5986,191 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.39" +version = "0.3.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70072aebfe5da66d2716002c729a14e4aec4da0e23cc2ea66323dac541c93928" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "wasmer" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e626f958755a90a6552b9528f59b58a62ae288e6c17fcf40e99495bc33c60f0" +dependencies = [ + "bytes", + "cfg-if", + "derivative", + "indexmap 1.9.3", + "js-sys", + "more-asserts", + "rustc-demangle", + "serde", + "serde-wasm-bindgen", + "shared-buffer", + "target-lexicon", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-downcast", + "wasmer-compiler", + "wasmer-compiler-cranelift", + "wasmer-compiler-singlepass", + "wasmer-derive", + "wasmer-types", + "wasmer-vm", + "winapi", +] + +[[package]] +name = "wasmer-compiler" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "848e1922694cf97f4df680a0534c9d72c836378b5eb2313c1708fe1a75b40044" +dependencies = [ + "backtrace", + "bytes", + "cfg-if", + "enum-iterator", + "enumset", + "lazy_static", + "leb128", + "memmap2 0.5.10", + "more-asserts", + "region", + "rkyv", + "self_cell", + "shared-buffer", + "smallvec", + "thiserror", + "wasmer-types", + "wasmer-vm", + "wasmparser", + "winapi", +] + +[[package]] +name = "wasmer-compiler-cranelift" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d96bce6fad15a954edcfc2749b59e47ea7de524b6ef3df392035636491a40b4" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "gimli 0.26.2", + "more-asserts", + "rayon", + "smallvec", + "target-lexicon", + "tracing", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-compiler-singlepass" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebaa865b40ffb3351b03dab9fe9930a5248c25daebd55b464b79b862d9b55ccd" +dependencies = [ + "byteorder", + "dynasm", + "dynasmrt", + "enumset", + "gimli 0.26.2", + "lazy_static", + "more-asserts", + "rayon", + "smallvec", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-derive" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89" +checksum = "7f08f80d166a9279671b7af7a09409c28ede2e0b4e3acabbf0e3cb22c8038ba7" dependencies = [ + "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.41", + "syn 1.0.109", +] + +[[package]] +name = "wasmer-middlewares" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeb4b87c0ea9f8636c81a8ab8f52bad01c8623c9fcbb3db5f367d5f157fada30" +dependencies = [ + "wasmer", + "wasmer-types", + "wasmer-vm", +] + +[[package]] +name = "wasmer-types" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae2c892882f0b416783fb4310e5697f5c30587f6f9555f9d4f2be85ab39d5d3d" +dependencies = [ + "bytecheck", + "enum-iterator", + "enumset", + "indexmap 1.9.3", + "more-asserts", + "rkyv", + "target-lexicon", + "thiserror", +] + +[[package]] +name = "wasmer-vm" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c0a9a57b627fb39e5a491058d4365f099bc9b140031c000fded24a3306d9480" +dependencies = [ + "backtrace", + "cc", + "cfg-if", + "corosensei", + "crossbeam-queue", + "dashmap", + "derivative", + "enum-iterator", + "fnv", + "indexmap 1.9.3", + "lazy_static", + "libc", + "mach", + "memoffset", + "more-asserts", + "region", + "scopeguard", + "thiserror", + "wasmer-types", + "winapi", +] + +[[package]] +name = "wasmparser" +version = "0.95.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a" +dependencies = [ + "indexmap 1.9.3", + "url", ] [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", @@ -5257,6 +6225,19 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43dbb096663629518eb1dfa72d80243ca5a6aca764cae62a2df70af760a9be75" +dependencies = [ + "windows_aarch64_msvc 0.33.0", + "windows_i686_gnu 0.33.0", + "windows_i686_msvc 0.33.0", + "windows_x86_64_gnu 0.33.0", + "windows_x86_64_msvc 0.33.0", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -5317,6 +6298,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +[[package]] +name = "windows_aarch64_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -5329,6 +6316,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +[[package]] +name = "windows_i686_gnu" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -5341,6 +6334,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +[[package]] +name = "windows_i686_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -5353,6 +6352,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +[[package]] +name = "windows_x86_64_gnu" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -5377,6 +6382,12 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +[[package]] +name = "windows_x86_64_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -5391,9 +6402,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.28" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] @@ -5419,22 +6430,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.31" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.31" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] @@ -5454,7 +6465,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.48", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9b77377c..aedc0272 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,13 @@ [workspace] resolver = "2" -members = ["modules/sov-ibc", "modules/sov-ibc-transfer", "mocks"] +members = [ + "clients/sov-celestia/types", + "clients/sov-celestia", + "clients/sov-celestia-cw", + "modules/sov-ibc-transfer", + "modules/sov-ibc", + "mocks", +] [workspace.package] version = "0.1.0" @@ -14,9 +21,9 @@ repository = "https://github.com/informalsystems/sovereign-ibc" [workspace.dependencies] # external dependencies anyhow = "1.0.68" -base64 = "0.21.5" +base64 = { version = "0.21", default-features = false } borsh = { version = "0.10.3", features = ["rc", "bytes"] } -bytes = "1.2.1" +bytes = { version = "1.2.1", default-features = false } derive_more = { version = "0.99.11", features = ["from", "try_into"] } digest = "0.10.6" hex = "0.4.3" @@ -29,17 +36,22 @@ tempfile = "3.5" thiserror = "1.0.38" # ibc depedenencies -ibc-core = { version = "0.49.1", default-features = false, features = ["borsh","schema","serde"] } -ibc-core-host-cosmos = { version = "0.49.1", default-features = false } -ibc-client-tendermint = { version = "0.49.1", default-features = false } -ibc-app-transfer = { version = "0.49.1", default-features = false } -ibc-query = { version = "0.49.1", default-features = false } -ibc-testkit = { version = "0.49.1", default-features = false } +ibc-core = { git = "https://github.com/cosmos/ibc-rs.git", rev = "1ef8777", default-features = false, features = ["borsh","schema","serde"] } +ibc-core-client = { git = "https://github.com/cosmos/ibc-rs.git", rev = "1ef8777", default-features = false } +ibc-core-host-cosmos = { git = "https://github.com/cosmos/ibc-rs.git", rev = "1ef8777", default-features = false } +ibc-client-tendermint = { git = "https://github.com/cosmos/ibc-rs.git", rev = "1ef8777", default-features = false } +ibc-client-wasm-types = { git = "https://github.com/cosmos/ibc-rs.git", rev = "1ef8777", default-features = false } +ibc-app-transfer = { git = "https://github.com/cosmos/ibc-rs.git", rev = "1ef8777", default-features = false } +ibc-primitives = { git = "https://github.com/cosmos/ibc-rs.git", rev = "1ef8777", default-features = false } +ibc-query = { git = "https://github.com/cosmos/ibc-rs.git", rev = "1ef8777", default-features = false } +ibc-testkit = { git = "https://github.com/cosmos/ibc-rs.git", rev = "1ef8777", default-features = false } +ibc-proto = { git = "https://github.com/cosmos/ibc-proto-rs.git", rev = "d1daaab", default-features = false } # cosmos dependencies tendermint = { version = "0.34", default-features = false } tendermint-proto = { version = "0.34", default-features = false } tendermint-testgen = { version = "0.34", default-features = false } +tendermint-light-client-verifier = { version = "0.34", default-features = false } # sovereign dependencies const-rollup-config = { git = "https://github.com/informalsystems/sovereign-sdk.git", rev = "6e22b4c" } @@ -51,4 +63,3 @@ sov-modules-api = { git = "https://github.com/informalsystems/sovereign-sd sov-modules-macros = { git = "https://github.com/informalsystems/sovereign-sdk.git", rev = "6e22b4c" } sov-state = { git = "https://github.com/informalsystems/sovereign-sdk.git", rev = "6e22b4c" } sov-rollup-interface = { git = "https://github.com/informalsystems/sovereign-sdk.git", rev = "6e22b4c" } - diff --git a/Makefile b/Makefile index 959aeda4..9c3588cf 100644 --- a/Makefile +++ b/Makefile @@ -3,18 +3,6 @@ help: ## Display this help message @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) -build: ## Build the the project - @cargo build - -clean: ## Cleans compiled - @cargo clean - -test-legacy: ## Runs test suite with output from tests printed - @cargo test -- --nocapture -Zunstable-options --report-time - -test: ## Runs test suite using next test - @cargo nextest run --workspace --all-features - install-dev-tools: ## Installs all necessary cargo helpers cargo install cargo-llvm-cov cargo install cargo-hack @@ -24,6 +12,25 @@ install-dev-tools: ## Installs all necessary cargo helpers cargo install cargo-risczero cargo risczero install +build: ## Build the the entire project + @cargo build + +build-sov-celestia-cw: ## Build the WASM file for the sov-celestia-cw light client + @echo "Building the WASM file for the sov-celestia-cw light client" + @RUSTFLAGS='-C link-arg=-s' cargo build -p sov-celestia-client-cw --target wasm32-unknown-unknown --release --lib --locked + @mkdir -p contracts + @cp target/wasm32-unknown-unknown/release/sov_celestia_client_cw.wasm contracts/ + +optimize-contracts: ## Optimize WASM files in contracts directory + @echo "Optimizing WASM files..." + @for wasm_file in contracts/*.wasm; do \ + optimized_file="contracts/$$(basename $$wasm_file .wasm).opt.wasm"; \ + wasm-opt "$$wasm_file" -o "$$optimized_file" -Os; \ + done + +clean: ## Cleans compiled + @cargo clean + lint: ## cargo check and clippy. Skip clippy on guest code since it's not supported by risc0 ## fmt first, because it's the cheapest cargo +nightly fmt --all --check @@ -35,26 +42,18 @@ lint-fix: ## cargo fmt, fix and clippy. Skip clippy on guest code since it's no cargo fix --allow-dirty CI_SKIP_GUEST_BUILD=1 cargo clippy --fix --allow-dirty -check-features: ## Checks that project compiles with all combinations of features. default is not needed because we never check `cfg(default)`, we only use it as an alias. - cargo hack check --workspace --feature-powerset --exclude-features default - -check-fuzz: ## Checks that fuzz member compiles - $(MAKE) -C fuzz check - find-unused-deps: ## Prints unused dependencies for project. Note: requires nightly cargo udeps --all-targets --all-features -find-flaky-tests: ## Runs tests over and over to find if there's flaky tests - flaky-finder -j16 -r320 --continue "cargo test -- --nocapture" - -coverage: ## Coverage in lcov format - cargo llvm-cov --locked --lcov --output-path lcov.info +check-features: ## Checks that project compiles with all combinations of features. default is not needed because we never check `cfg(default)`, we only use it as an alias. + cargo hack check --workspace --feature-powerset --exclude-features default -coverage-html: ## Coverage in HTML format - cargo llvm-cov --locked --all-features --html +test-legacy: ## Runs test suite with output from tests printed + @cargo test -- --nocapture -Zunstable-options --report-time -dry-run-publish: - yq '.[]' packages_to_publish.yml | xargs -I _ cargo publish --allow-dirty --dry-run -p _ +test: ## Runs test suite using next test + @cargo nextest run --workspace --all-features docs: ## Generates documentation locally - cargo doc --open + cargo doc --all-features --no-deps --release --open + diff --git a/clients/README.md b/clients/README.md new file mode 100644 index 00000000..c7e58e39 --- /dev/null +++ b/clients/README.md @@ -0,0 +1 @@ +# `sov-celestia-client` diff --git a/clients/sov-celestia-cw/Cargo.toml b/clients/sov-celestia-cw/Cargo.toml new file mode 100644 index 00000000..daf9aba2 --- /dev/null +++ b/clients/sov-celestia-cw/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "sov-celestia-client-cw" +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } +keywords = ["rollup", "sovereign", "ibc", "light-client", "CosmWasm"] +readme = "./../README.md" +description = """ + Contains the CosmWasm contract implementation of the `sov-celesita` light client. +""" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +# external dependencies +derive_more = { workspace = true } +prost = { workspace = true, default-features = false } +serde = { workspace = true, features = ["derive"] } +thiserror = { version = "1.0.31" } + +# ibc dependencies +ibc-core = { workspace = true } +ibc-client-tendermint = { workspace = true } +ibc-client-wasm-types = { workspace = true, features = ["cosmwasm"] } +ibc-proto = { workspace = true, features = ["json-schema"] } +sov-celestia-client = { path = "../sov-celestia", default-features = false, features = ["serde"] } + +# cosmwasm dependencies +cosmwasm-schema = "1.4.1" +cosmwasm-std = "1.4.1" + +[dev-dependencies] +cosmwasm-vm = "1.4.1" +test-log = { version = "0.2.14", default-features = false, features = ["trace"] } +tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } + +[features] +default = ["std"] +std = [ + "ibc-core/std", + "ibc-proto/std", + "ibc-client-wasm-types/std", + "ibc-client-tendermint/std", + "sov-celestia-client/std", + "prost/std", + "serde/std", +] +test = [ + "std" +] +# use library feature to disable entry points +library = [] diff --git a/clients/sov-celestia-cw/src/contexts/client_ctx.rs b/clients/sov-celestia-cw/src/contexts/client_ctx.rs new file mode 100644 index 00000000..fda882e5 --- /dev/null +++ b/clients/sov-celestia-cw/src/contexts/client_ctx.rs @@ -0,0 +1,201 @@ +use ibc_core::client::context::{ClientExecutionContext, ClientValidationContext}; +use ibc_core::client::types::error::ClientError; +use ibc_core::client::types::Height; +use ibc_core::handler::types::error::ContextError; +use ibc_core::host::types::identifiers::ClientId; +use ibc_core::host::types::path::{ClientConsensusStatePath, ClientStatePath}; +use ibc_core::host::ValidationContext; +use ibc_core::primitives::proto::Any; +use ibc_core::primitives::Timestamp; + +use super::definition::StorageMut; +use super::{Context, StorageRef}; +use crate::types::{AnyClientState, AnyConsensusState, ProcessedStates, ReadonlyProcessedStates}; + +impl ClientValidationContext for Context<'_> { + fn client_update_time( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result { + client_update_time(self, client_id, height) + } + + fn client_update_height( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result { + client_update_height(self, client_id, height) + } +} + +impl ClientExecutionContext for Context<'_> { + type V = ::V; + type AnyClientState = ::AnyClientState; + type AnyConsensusState = ::AnyConsensusState; + + fn store_client_state( + &mut self, + client_state_path: ClientStatePath, + client_state: AnyClientState, + ) -> Result<(), ContextError> { + store_client_state(self, client_state_path, client_state) + } + + fn store_consensus_state( + &mut self, + consensus_state_path: ClientConsensusStatePath, + consensus_state: AnyConsensusState, + ) -> Result<(), ContextError> { + store_consensus_state(self, consensus_state_path, consensus_state) + } + + fn store_update_time( + &mut self, + client_id: ClientId, + height: Height, + timestamp: Timestamp, + ) -> Result<(), ContextError> { + store_update_time(self, client_id, height, timestamp) + } + + fn store_update_height( + &mut self, + client_id: ClientId, + height: Height, + host_height: Height, + ) -> Result<(), ContextError> { + store_update_height(self, client_id, height, host_height) + } + + fn delete_consensus_state( + &mut self, + _consensus_state_path: ClientConsensusStatePath, + ) -> Result<(), ContextError> { + todo!() + } + + fn delete_update_time( + &mut self, + _client_id: ClientId, + _height: Height, + ) -> Result<(), ContextError> { + todo!() + } + + fn delete_update_height( + &mut self, + _client_id: ClientId, + _height: Height, + ) -> Result<(), ContextError> { + todo!() + } +} + +fn client_update_time( + ctx: &Ctx, + _client_id: &ClientId, + height: &Height, +) -> Result +where + Ctx: ClientValidationContext + StorageRef, +{ + let processed_state = ReadonlyProcessedStates::new(ctx.storage_ref()); + let timestamp = match processed_state.get_processed_time(*height, &mut Vec::new()) { + Some(time) => { + Timestamp::from_nanoseconds(time).map_err(ClientError::InvalidPacketTimestamp)? + } + None => Err(ClientError::Other { + description: "problem getting processed time".to_string(), + })?, + }; + + Ok(timestamp) +} + +fn client_update_height( + ctx: &Ctx, + _client_id: &ClientId, + height: &Height, +) -> Result +where + Ctx: ClientValidationContext + StorageRef, +{ + let processed_state = ReadonlyProcessedStates::new(ctx.storage_ref()); + + let height = match processed_state.get_processed_height(*height, &mut Vec::new()) { + Some(h) => Height::new(0, h)?, + None => Err(ClientError::Other { + description: "problem getting processed time".to_string(), + })?, + }; + + Ok(height) +} + +fn store_client_state( + ctx: &mut Ctx, + client_state_path: ClientStatePath, + client_state: AnyClientState, +) -> Result<(), ContextError> +where + Ctx: ClientExecutionContext + StorageMut, +{ + let client_state_value = Any::from(client_state).value; + + ctx.storage_mut().set( + client_state_path.to_string().as_bytes(), + client_state_value.as_slice(), + ); + + Ok(()) +} + +fn store_consensus_state( + ctx: &mut Ctx, + consensus_state_path: ClientConsensusStatePath, + consensus_state: AnyConsensusState, +) -> Result<(), ContextError> +where + Ctx: ClientExecutionContext + StorageMut, +{ + let consensus_state_value = Any::from(consensus_state).value; + + ctx.storage_mut().set( + consensus_state_path.to_string().as_bytes(), + consensus_state_value.as_slice(), + ); + + Ok(()) +} + +fn store_update_time( + ctx: &mut Ctx, + _client_id: ClientId, + height: Height, + timestamp: Timestamp, +) -> Result<(), ContextError> +where + Ctx: ClientExecutionContext + StorageMut, +{ + let mut processed_state = ProcessedStates::new(ctx.storage_mut()); + processed_state.set_processed_time(height, timestamp.nanoseconds(), &mut Vec::new()); + + Ok(()) +} + +fn store_update_height( + ctx: &mut Ctx, + _client_id: ClientId, + height: Height, + host_height: Height, +) -> Result<(), ContextError> +where + Ctx: ClientExecutionContext + StorageMut, +{ + let mut processed_state = ProcessedStates::new(ctx.storage_mut()); + processed_state.set_processed_height(height, host_height.revision_height(), &mut Vec::new()); + processed_state.set_iteration_key(height, &mut Vec::new()); + Ok(()) +} diff --git a/clients/sov-celestia-cw/src/contexts/core_ctx.rs b/clients/sov-celestia-cw/src/contexts/core_ctx.rs new file mode 100644 index 00000000..7aac91f7 --- /dev/null +++ b/clients/sov-celestia-cw/src/contexts/core_ctx.rs @@ -0,0 +1,322 @@ +use std::time::Duration; + +use ibc_core::channel::types::channel::ChannelEnd; +use ibc_core::channel::types::commitment::{AcknowledgementCommitment, PacketCommitment}; +use ibc_core::channel::types::packet::Receipt; +use ibc_core::client::types::error::ClientError; +use ibc_core::client::types::Height; +use ibc_core::commitment_types::commitment::CommitmentPrefix; +use ibc_core::connection::types::ConnectionEnd; +use ibc_core::handler::types::error::ContextError; +use ibc_core::handler::types::events::IbcEvent; +use ibc_core::host::types::identifiers::{ClientId, ConnectionId, Sequence}; +use ibc_core::host::types::path::{ + AckPath, ChannelEndPath, ClientConnectionPath, ClientConsensusStatePath, ClientStatePath, + CommitmentPath, ConnectionPath, ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, +}; +use ibc_core::host::{ExecutionContext, ValidationContext}; +use ibc_core::primitives::proto::{Any, Protobuf}; +use ibc_core::primitives::{Signer, Timestamp}; +use sov_celestia_client::types::client_state::SOV_TENDERMINT_CLIENT_STATE_TYPE_URL; +use sov_celestia_client::types::proto::v1::{ + ClientState as RawClientState, ConsensusState as RawConsensusState, +}; + +use super::{Context, StorageRef}; +use crate::types::{AnyClientState, AnyConsensusState}; + +impl ValidationContext for Context<'_> { + type V = Self; + type E = Self; + type AnyConsensusState = AnyConsensusState; + type AnyClientState = AnyClientState; + + fn get_client_validation_context(&self) -> &Self::V { + self + } + + fn client_state(&self, client_id: &ClientId) -> Result { + client_state(self, client_id) + } + + fn decode_client_state(&self, client_state: Any) -> Result { + decode_client_state(self, client_state) + } + + fn consensus_state( + &self, + client_cons_state_path: &ClientConsensusStatePath, + ) -> Result { + consensus_state(self, client_cons_state_path) + } + + fn host_height(&self) -> Result { + let host_height = Height::new(0, self.env().block.height)?; + + Ok(host_height) + } + + fn host_timestamp(&self) -> Result { + let time = self.env().block.time; + let host_timestamp = Timestamp::from_nanoseconds(time.nanos()).expect("invalid timestamp"); + + Ok(host_timestamp) + } + + fn host_consensus_state( + &self, + _height: &Height, + ) -> Result { + unimplemented!() + } + + fn client_counter(&self) -> Result { + unimplemented!() + } + + fn connection_end(&self, _conn_id: &ConnectionId) -> Result { + unimplemented!() + } + + fn validate_self_client( + &self, + _client_state_of_host_on_counterparty: Any, + ) -> Result<(), ContextError> { + Ok(()) + } + + fn commitment_prefix(&self) -> CommitmentPrefix { + unimplemented!() + } + + fn connection_counter(&self) -> Result { + unimplemented!() + } + + fn channel_end(&self, _channel_end_path: &ChannelEndPath) -> Result { + unimplemented!() + } + + fn get_next_sequence_send( + &self, + _seq_send_path: &SeqSendPath, + ) -> Result { + unimplemented!() + } + + fn get_next_sequence_recv( + &self, + _seq_recv_path: &SeqRecvPath, + ) -> Result { + unimplemented!() + } + + fn get_next_sequence_ack(&self, _seq_ack_path: &SeqAckPath) -> Result { + unimplemented!() + } + + fn get_packet_commitment( + &self, + _commitment_path: &CommitmentPath, + ) -> Result { + unimplemented!() + } + + fn get_packet_receipt(&self, _receipt_path: &ReceiptPath) -> Result { + unimplemented!() + } + + fn get_packet_acknowledgement( + &self, + _ack_path: &AckPath, + ) -> Result { + unimplemented!() + } + + fn channel_counter(&self) -> Result { + unimplemented!() + } + + fn max_expected_time_per_block(&self) -> Duration { + // This effectively cancels the check on connection block delays. + Duration::ZERO + } + + fn validate_message_signer(&self, _signer: &Signer) -> Result<(), ContextError> { + Ok(()) + } +} + +impl ExecutionContext for Context<'_> { + fn get_client_execution_context(&mut self) -> &mut Self::E { + todo!() + } + + fn increase_client_counter(&mut self) -> Result<(), ContextError> { + todo!() + } + + fn store_connection( + &mut self, + _connection_path: &ConnectionPath, + _connection_end: ConnectionEnd, + ) -> Result<(), ContextError> { + todo!() + } + + fn store_connection_to_client( + &mut self, + _client_connection_path: &ClientConnectionPath, + _conn_id: ConnectionId, + ) -> Result<(), ContextError> { + todo!() + } + + fn increase_connection_counter(&mut self) -> Result<(), ContextError> { + todo!() + } + + fn store_packet_commitment( + &mut self, + _commitment_path: &CommitmentPath, + _commitment: PacketCommitment, + ) -> Result<(), ContextError> { + todo!() + } + + fn delete_packet_commitment( + &mut self, + _commitment_path: &CommitmentPath, + ) -> Result<(), ContextError> { + todo!() + } + + fn store_packet_receipt( + &mut self, + _receipt_path: &ReceiptPath, + _receipt: Receipt, + ) -> Result<(), ContextError> { + todo!() + } + + fn store_packet_acknowledgement( + &mut self, + _ack_path: &AckPath, + _ack_commitment: AcknowledgementCommitment, + ) -> Result<(), ContextError> { + todo!() + } + + fn delete_packet_acknowledgement(&mut self, _ack_path: &AckPath) -> Result<(), ContextError> { + todo!() + } + + fn store_channel( + &mut self, + _channel_end_path: &ChannelEndPath, + _channel_end: ChannelEnd, + ) -> Result<(), ContextError> { + todo!() + } + + fn store_next_sequence_send( + &mut self, + _seq_send_path: &SeqSendPath, + _seq: Sequence, + ) -> Result<(), ContextError> { + todo!() + } + + fn store_next_sequence_recv( + &mut self, + _seq_recv_path: &SeqRecvPath, + _seq: Sequence, + ) -> Result<(), ContextError> { + todo!() + } + + fn store_next_sequence_ack( + &mut self, + _seq_ack_path: &SeqAckPath, + _seq: Sequence, + ) -> Result<(), ContextError> { + todo!() + } + + fn increase_channel_counter(&mut self) -> Result<(), ContextError> { + todo!() + } + + fn emit_ibc_event(&mut self, _event: IbcEvent) -> Result<(), ContextError> { + todo!() + } + + fn log_message(&mut self, _message: String) -> Result<(), ContextError> { + todo!() + } +} + +pub fn client_state(ctx: &Ctx, client_id: &ClientId) -> Result +where + Ctx: ValidationContext + StorageRef, +{ + let client_state_path = ClientStatePath::new(client_id).to_string(); + + let client_state_value = + ctx.storage_ref() + .get(client_state_path.as_bytes()) + .ok_or(ClientError::Other { + description: "Client state not found".to_string(), + })?; + + let sov_client_state = Protobuf::::decode(client_state_value.as_slice()) + .map_err(|e| ClientError::Other { + description: e.to_string(), + })?; + + Ok(AnyClientState::Sovereign(sov_client_state)) +} + +fn decode_client_state(_ctx: &Ctx, client_state: Any) -> Result +where + Ctx: ValidationContext + StorageRef, +{ + match client_state.type_url.as_str() { + SOV_TENDERMINT_CLIENT_STATE_TYPE_URL => { + let sov_client_state = + Protobuf::::decode(client_state.value.as_slice()).map_err(|e| { + ClientError::Other { + description: e.to_string(), + } + })?; + + Ok(AnyClientState::Sovereign(sov_client_state)) + } + _ => Err(ClientError::Other { + description: "Client state type not supported".to_string(), + } + .into()), + } +} + +fn consensus_state( + ctx: &Ctx, + client_cons_state_path: &ClientConsensusStatePath, +) -> Result +where + Ctx: ValidationContext + StorageRef, +{ + let consensus_state_value = ctx + .storage_ref() + .get(client_cons_state_path.to_string().as_bytes()) + .ok_or(ClientError::Other { + description: "Consensus state not found".to_string(), + })?; + + let consensus_state = Protobuf::::decode(consensus_state_value.as_slice()) + .map_err(|e| ClientError::Other { + description: e.to_string(), + })?; + + Ok(AnyConsensusState::Sovereign(consensus_state)) +} diff --git a/clients/sov-celestia-cw/src/contexts/custom_ctx.rs b/clients/sov-celestia-cw/src/contexts/custom_ctx.rs new file mode 100644 index 00000000..30711622 --- /dev/null +++ b/clients/sov-celestia-cw/src/contexts/custom_ctx.rs @@ -0,0 +1,75 @@ +use ibc_core::client::types::error::ClientError; +use ibc_core::client::types::Height; +use ibc_core::handler::types::error::ContextError; +use ibc_core::host::types::identifiers::ClientId; +use ibc_core::host::types::path::ClientConsensusStatePath; +use ibc_core::host::ValidationContext as CoreValidationContext; +use ibc_core::primitives::Timestamp; +use sov_celestia_client::context::{CommonContext, ValidationContext}; + +use super::{Context, StorageRef}; +use crate::types::{AnyConsensusState, ReadonlyProcessedStates}; + +impl CommonContext for Context<'_> { + type ConversionError = ClientError; + type AnyConsensusState = AnyConsensusState; + + fn host_timestamp(&self) -> Result { + CoreValidationContext::host_timestamp(self) + } + + fn host_height(&self) -> Result { + CoreValidationContext::host_height(self) + } + + fn consensus_state( + &self, + client_cons_state_path: &ClientConsensusStatePath, + ) -> Result { + CoreValidationContext::consensus_state(self, client_cons_state_path) + } + + fn consensus_state_heights(&self, _client_id: &ClientId) -> Result, ContextError> { + unimplemented!() + } +} + +impl ValidationContext for Context<'_> { + fn next_consensus_state( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result, ContextError> { + let processed_state = ReadonlyProcessedStates::new(self.storage_ref()); + match processed_state.get_next_height(*height) { + Some(next_height) => { + let cons_state_path = ClientConsensusStatePath::new( + client_id.clone(), + next_height.revision_number(), + next_height.revision_height(), + ); + CoreValidationContext::consensus_state(self, &cons_state_path).map(Some) + } + None => Ok(None), + } + } + + fn prev_consensus_state( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result, ContextError> { + let processed_state = ReadonlyProcessedStates::new(self.storage_ref()); + match processed_state.get_prev_height(*height) { + Some(prev_height) => { + let cons_state_path = ClientConsensusStatePath::new( + client_id.clone(), + prev_height.revision_number(), + prev_height.revision_height(), + ); + CoreValidationContext::consensus_state(self, &cons_state_path).map(Some) + } + None => Ok(None), + } + } +} diff --git a/clients/sov-celestia-cw/src/contexts/definition.rs b/clients/sov-celestia-cw/src/contexts/definition.rs new file mode 100644 index 00000000..62db9dcd --- /dev/null +++ b/clients/sov-celestia-cw/src/contexts/definition.rs @@ -0,0 +1,281 @@ +use std::str::FromStr; + +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, Storage}; +use ibc_core::client::context::client_state::{ + ClientStateCommon, ClientStateExecution, ClientStateValidation, +}; +use ibc_core::client::context::consensus_state::ConsensusState as _; +use ibc_core::client::types::UpdateKind; +use ibc_core::handler::types::error::ContextError; +use ibc_core::host::types::error::IdentifierError; +use ibc_core::host::types::identifiers::ClientId; +use ibc_core::host::types::path::ClientConsensusStatePath; +use ibc_core::host::ValidationContext; +use ibc_proto::google::protobuf::Any; +use prost::Message; +use sov_celestia_client::client_state::ClientState; +use sov_celestia_client::types::client_message::ClientMessage; + +use crate::types::{ + CheckForMisbehaviourMsg, ContractError, ContractResult, ExecuteMsg, ExportMetadataMsg, + InstantiateMsg, QueryMsg, QueryResponse, ReadonlyProcessedStates, StatusMsg, UpdateStateMsg, + UpdateStateOnMisbehaviourMsg, VerifyClientMessageMsg, VerifyMembershipMsg, + VerifyNonMembershipMsg, VerifyUpgradeAndUpdateStateMsg, +}; + +/// Context is a wrapper around the deps and env that gives access to the +/// methods of the ibc-rs Validation and Execution traits. +pub struct Context<'a> { + deps: Option>, + deps_mut: Option>, + env: Env, +} + +impl<'a> Context<'a> { + pub fn new_ref(deps: Deps<'a>, env: Env) -> Self { + Self { + deps: Some(deps), + deps_mut: None, + env, + } + } + + pub fn new_mut(deps: DepsMut<'a>, env: Env) -> Self { + Self { + deps: None, + deps_mut: Some(deps), + env, + } + } + + pub fn env(&self) -> &Env { + &self.env + } + + pub fn log(&self, msg: &str) -> Option<()> { + self.deps.map(|deps| deps.api.debug(msg)) + } + + pub fn client_id(&self) -> Result { + ClientId::from_str(self.env.contract.address.as_str()) + } + + pub fn instantiate(&mut self, msg: InstantiateMsg) -> Result { + let client_id = self.client_id()?; + + let any = Any::decode(&mut msg.client_state.as_slice())?; + + let client_state = ClientState::try_from(any)?; + + let any_consensus_state = Any::decode(&mut msg.consensus_state.as_slice())?; + + client_state.initialise(self, &client_id, any_consensus_state)?; + + Ok(to_json_binary(&ContractResult::success())?) + } + + pub fn execute(&mut self, msg: ExecuteMsg) -> Result { + let client_id = self.client_id()?; + + let client_state = self.client_state(&client_id)?; + + let result = match msg { + ExecuteMsg::VerifyMembership(msg) => { + let msg = VerifyMembershipMsg::try_from(msg)?; + + let client_cons_state_path = ClientConsensusStatePath::new( + client_id.clone(), + msg.height.revision_number(), + msg.height.revision_height(), + ); + + let consensus_state = self.consensus_state(&client_cons_state_path)?; + + client_state + .verify_membership( + &msg.prefix, + &msg.proof, + consensus_state.root(), + msg.path, + msg.value, + ) + .map_err(ContextError::from)?; + + ContractResult::success() + } + ExecuteMsg::VerifyNonMembership(msg) => { + let msg = VerifyNonMembershipMsg::try_from(msg)?; + + let client_cons_state_path = ClientConsensusStatePath::new( + client_id.clone(), + msg.height.revision_number(), + msg.height.revision_height(), + ); + + let consensus_state = self.consensus_state(&client_cons_state_path)?; + + client_state.verify_non_membership( + &msg.prefix, + &msg.proof, + consensus_state.root(), + msg.path, + )?; + + ContractResult::success() + } + ExecuteMsg::VerifyClientMessage(msg) => { + let msg = VerifyClientMessageMsg::try_from(msg)?; + + let (update_kind, any_client_msg): (_, Any) = match msg.client_message { + ClientMessage::Header(header) => (UpdateKind::UpdateClient, (*header).into()), + ClientMessage::Misbehaviour(misbehaviour) => { + (UpdateKind::SubmitMisbehaviour, (*misbehaviour).into()) + } + }; + + client_state.verify_client_message( + self, + &client_id, + any_client_msg, + &update_kind, + )?; + + ContractResult::success() + } + ExecuteMsg::CheckForMisbehaviour(msg) => { + let msg = CheckForMisbehaviourMsg::try_from(msg)?; + + let (update_kind, any_client_msg): (_, Any) = match msg.client_message { + ClientMessage::Header(header) => (UpdateKind::UpdateClient, (*header).into()), + ClientMessage::Misbehaviour(misbehaviour) => { + (UpdateKind::SubmitMisbehaviour, (*misbehaviour).into()) + } + }; + + let result = client_state.check_for_misbehaviour( + self, + &client_id, + any_client_msg, + &update_kind, + )?; + + ContractResult::success().misbehaviour(result) + } + ExecuteMsg::UpdateStateOnMisbehaviour(msg_raw) => { + let msg: UpdateStateOnMisbehaviourMsg = + UpdateStateOnMisbehaviourMsg::try_from(msg_raw)?; + + let (update_kind, any_client_msg) = match msg.client_message { + ClientMessage::Header(header) => (UpdateKind::UpdateClient, (*header).into()), + ClientMessage::Misbehaviour(misbehaviour) => { + (UpdateKind::SubmitMisbehaviour, (*misbehaviour).into()) + } + }; + + client_state.update_state_on_misbehaviour( + self, + &client_id, + any_client_msg, + &update_kind, + )?; + + ContractResult::success() + } + ExecuteMsg::UpdateState(msg_raw) => { + let msg = UpdateStateMsg::try_from(msg_raw)?; + + let (_, any_client_msg) = match msg.client_message { + ClientMessage::Header(header) => (UpdateKind::UpdateClient, (*header).into()), + ClientMessage::Misbehaviour(misbehaviour) => { + (UpdateKind::SubmitMisbehaviour, (*misbehaviour).into()) + } + }; + + client_state.update_state(self, &client_id, any_client_msg)?; + + ContractResult::success() + } + ExecuteMsg::CheckSubstituteAndUpdateState(_) => { + ContractResult::error("ibc-rs does no support this feature yet".to_string()) + } + ExecuteMsg::VerifyUpgradeAndUpdateState(msg) => { + let msg = VerifyUpgradeAndUpdateStateMsg::try_from(msg)?; + + let client_cons_state_path = ClientConsensusStatePath::new( + client_id.clone(), + client_state.latest_height().revision_number(), + client_state.latest_height().revision_height(), + ); + + let consensus_state = self.consensus_state(&client_cons_state_path)?; + + client_state.verify_upgrade_client( + msg.upgrade_client_state.clone(), + msg.upgrade_consensus_state.clone(), + msg.proof_upgrade_client, + msg.proof_upgrade_consensus_state, + consensus_state.root(), + )?; + + client_state.update_state_on_upgrade( + self, + &client_id, + msg.upgrade_client_state, + msg.upgrade_consensus_state, + )?; + + ContractResult::success() + } + }; + Ok(to_json_binary(&result)?) + } + + pub fn query(&self, msg: QueryMsg) -> Result { + let client_id = self.client_id()?; + + let resp = match msg { + QueryMsg::ClientTypeMsg(_) => unimplemented!("ClientTypeMsg"), + QueryMsg::GetLatestHeightsMsg(_) => unimplemented!("GetLatestHeightsMsg"), + QueryMsg::ExportMetadata(ExportMetadataMsg {}) => { + let ro_proceeded_state = ReadonlyProcessedStates::new(self.storage_ref()); + QueryResponse::genesis_metadata(ro_proceeded_state.get_metadata()) + } + QueryMsg::Status(StatusMsg {}) => { + let client_state = self.client_state(&client_id)?; + + match client_state.status(self, &client_id) { + Ok(status) => QueryResponse::status(status.to_string()), + Err(err) => QueryResponse::status(err.to_string()), + } + } + }; + + Ok(to_json_binary(&resp)?) + } +} + +pub trait StorageRef { + fn storage_ref(&self) -> &dyn Storage; +} + +impl StorageRef for Context<'_> { + fn storage_ref(&self) -> &dyn Storage { + match self.deps { + Some(ref deps) => deps.storage, + None => panic!("storage should be available"), + } + } +} + +pub trait StorageMut: StorageRef { + fn storage_mut(&mut self) -> &mut dyn Storage; +} + +impl StorageMut for Context<'_> { + fn storage_mut(&mut self) -> &mut dyn Storage { + match self.deps_mut { + Some(ref mut deps) => deps.storage, + None => panic!("storage should be available"), + } + } +} diff --git a/clients/sov-celestia-cw/src/contexts/mod.rs b/clients/sov-celestia-cw/src/contexts/mod.rs new file mode 100644 index 00000000..f0080f6a --- /dev/null +++ b/clients/sov-celestia-cw/src/contexts/mod.rs @@ -0,0 +1,6 @@ +pub mod client_ctx; +pub mod core_ctx; +pub mod custom_ctx; +mod definition; + +pub use definition::{Context, StorageMut, StorageRef}; diff --git a/clients/sov-celestia-cw/src/entrypoints.rs b/clients/sov-celestia-cw/src/entrypoints.rs new file mode 100644 index 00000000..67fc93c2 --- /dev/null +++ b/clients/sov-celestia-cw/src/entrypoints.rs @@ -0,0 +1,42 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult}; + +use crate::contexts::Context; +use crate::types::{ContractError, ExecuteMsg, InstantiateMsg, QueryMsg}; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut<'_>, + env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + let mut ctx = Context::new_mut(deps, env); + + let data = ctx.instantiate(msg)?; + + Ok(Response::default().set_data(data)) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut<'_>, + env: Env, + _info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + let mut ctx = Context::new_mut(deps, env); + + let data = ctx.execute(msg)?; + + Ok(Response::default().set_data(data)) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> StdResult { + let ctx = Context::new_ref(deps, env); + + ctx.query(msg) + .map_err(|e| StdError::generic_err(e.to_string())) +} diff --git a/clients/sov-celestia-cw/src/lib.rs b/clients/sov-celestia-cw/src/lib.rs new file mode 100644 index 00000000..706fba8f --- /dev/null +++ b/clients/sov-celestia-cw/src/lib.rs @@ -0,0 +1,16 @@ +#![cfg_attr(not(test), deny(clippy::unwrap_used))] +#![deny( + warnings, + trivial_casts, + trivial_numeric_casts, + unused_import_braces, + unused_qualifications, + rust_2018_idioms +)] +#![forbid(unsafe_code)] + +extern crate alloc; + +pub mod contexts; +pub mod entrypoints; +pub mod types; diff --git a/clients/sov-celestia-cw/src/types/client_state.rs b/clients/sov-celestia-cw/src/types/client_state.rs new file mode 100644 index 00000000..6b702ff1 --- /dev/null +++ b/clients/sov-celestia-cw/src/types/client_state.rs @@ -0,0 +1,43 @@ +use ibc_core::client::types::error::ClientError; +use ibc_core::derive::ClientState as ClientStateDerive; +use ibc_core::primitives::proto::{Any, Protobuf}; +use sov_celestia_client::client_state::ClientState; +use sov_celestia_client::types::client_state::{ + ClientState as ClientStateType, SOV_TENDERMINT_CLIENT_STATE_TYPE_URL, +}; + +use crate::contexts::Context; + +#[derive(ClientStateDerive, Debug, derive_more::From)] +#[validation(Context<'a>)] +#[execution(Context<'a>)] +pub enum AnyClientState { + Sovereign(ClientState), +} + +impl TryFrom for ClientState { + type Error = ClientError; + + fn try_from(value: AnyClientState) -> Result { + match value { + AnyClientState::Sovereign(state) => Ok(state), + } + } +} + +impl From for AnyClientState { + fn from(value: ClientStateType) -> Self { + AnyClientState::Sovereign(ClientState::from(value)) + } +} + +impl From for Any { + fn from(value: AnyClientState) -> Self { + match value { + AnyClientState::Sovereign(cs) => Any { + type_url: SOV_TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(cs), + }, + } + } +} diff --git a/clients/sov-celestia-cw/src/types/consensus_state.rs b/clients/sov-celestia-cw/src/types/consensus_state.rs new file mode 100644 index 00000000..17285e18 --- /dev/null +++ b/clients/sov-celestia-cw/src/types/consensus_state.rs @@ -0,0 +1,31 @@ +use ibc_core::client::types::error::ClientError; +use ibc_core::derive::ConsensusState as ConsensusStateDerive; +use ibc_core::primitives::proto::{Any, Protobuf}; +use sov_celestia_client::consensus_state::ConsensusState; +use sov_celestia_client::types::consensus_state::SOV_TENDERMINT_CONSENSUS_STATE_TYPE_URL; + +#[derive(Clone, Debug, derive_more::From, ConsensusStateDerive)] +pub enum AnyConsensusState { + Sovereign(ConsensusState), +} + +impl TryFrom for ConsensusState { + type Error = ClientError; + + fn try_from(value: AnyConsensusState) -> Result { + match value { + AnyConsensusState::Sovereign(state) => Ok(state), + } + } +} + +impl From for Any { + fn from(value: AnyConsensusState) -> Self { + match value { + AnyConsensusState::Sovereign(cs) => Any { + type_url: SOV_TENDERMINT_CONSENSUS_STATE_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(cs), + }, + } + } +} diff --git a/clients/sov-celestia-cw/src/types/error.rs b/clients/sov-celestia-cw/src/types/error.rs new file mode 100644 index 00000000..c6aa565b --- /dev/null +++ b/clients/sov-celestia-cw/src/types/error.rs @@ -0,0 +1,30 @@ +use alloc::string::String; +use std::error::Error as StdError; + +use derive_more::{Display, From}; +use ibc_core::client::types::error::ClientError; +use ibc_core::commitment_types::error::CommitmentError; +use ibc_core::handler::types::error::ContextError; +use ibc_core::host::types::error::IdentifierError; +use ibc_core::host::types::path::PathError; + +#[derive(From, Display, Debug)] +pub enum ContractError { + Std(cosmwasm_std::StdError), + #[display(fmt = "invalid message: {_0}")] + InvalidMsg(String), + #[display(fmt = "IBC validation/execution context error: {_0}")] + Context(ContextError), + #[display(fmt = "IBC client error: {_0}")] + ClientError(ClientError), + #[display(fmt = "IBC commitment error: {_0}")] + Commitment(CommitmentError), + #[display(fmt = "IBC identifier error: {_0}")] + Identifier(IdentifierError), + #[display(fmt = "IBC path error: {_0}")] + Path(PathError), + #[display(fmt = "Proto decode error: {_0}")] + ProtoDecode(prost::DecodeError), +} + +impl StdError for ContractError {} diff --git a/clients/sov-celestia-cw/src/types/mod.rs b/clients/sov-celestia-cw/src/types/mod.rs new file mode 100644 index 00000000..eec974b7 --- /dev/null +++ b/clients/sov-celestia-cw/src/types/mod.rs @@ -0,0 +1,15 @@ +mod client_state; +mod consensus_state; +mod error; +mod msgs; +mod processed_states; +mod response; + +pub use client_state::*; +pub use consensus_state::*; +pub use error::*; +pub use msgs::*; +pub use processed_states::*; +pub use response::*; + +pub const STORAGE_PREFIX: &[u8] = b""; diff --git a/clients/sov-celestia-cw/src/types/msgs.rs b/clients/sov-celestia-cw/src/types/msgs.rs new file mode 100644 index 00000000..dc21db0f --- /dev/null +++ b/clients/sov-celestia-cw/src/types/msgs.rs @@ -0,0 +1,316 @@ +use alloc::vec::Vec; +use std::str::FromStr; + +use cosmwasm_schema::cw_serde; +use ibc_client_wasm_types::client_state::ClientState as WasmClientState; +use ibc_client_wasm_types::consensus_state::ConsensusState as WasmConsensusState; +use ibc_client_wasm_types::serializer::Base64; +use ibc_core::client::types::error::ClientError; +use ibc_core::client::types::Height; +use ibc_core::commitment_types::commitment::{CommitmentPrefix, CommitmentProofBytes}; +use ibc_core::handler::types::error::ContextError; +use ibc_core::host::types::path::Path; +use ibc_core::primitives::proto::Any; +use ibc_proto::ibc::core::client::v1::Height as RawHeight; +use ibc_proto::ibc::lightclients::wasm::v1::ClientMessage as RawClientMessage; +use prost::Message; +use sov_celestia_client::types::client_message::{ + ClientMessage, Header, SovMisbehaviour, SovTmClientMessage, SOV_TENDERMINT_HEADER_TYPE_URL, + SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL, +}; + +pub type Bytes = Vec; + +use super::error::ContractError; + +#[cw_serde] +pub struct GenesisMetadata { + pub key: Vec, + pub value: Vec, +} + +#[cw_serde] +pub struct InstantiateMsg { + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub client_state: Bytes, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub consensus_state: Bytes, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub checksum: Bytes, +} + +#[cw_serde] +pub enum ExecuteMsg { + VerifyMembership(VerifyMembershipMsgRaw), + VerifyNonMembership(VerifyNonMembershipMsgRaw), + VerifyClientMessage(VerifyClientMessageMsgRaw), + CheckForMisbehaviour(CheckForMisbehaviourMsgRaw), + UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsgRaw), + UpdateState(UpdateStateMsgRaw), + CheckSubstituteAndUpdateState(CheckSubstituteAndUpdateStateMsg), + VerifyUpgradeAndUpdateState(VerifyUpgradeAndUpdateStateMsgRaw), +} + +#[cw_serde] +pub enum QueryMsg { + ClientTypeMsg(ClientTypeMsg), + GetLatestHeightsMsg(GetLatestHeightsMsg), + ExportMetadata(ExportMetadataMsg), + Status(StatusMsg), +} + +#[cw_serde] +pub struct ClientTypeMsg {} + +#[cw_serde] +pub struct GetLatestHeightsMsg {} + +#[cw_serde] +pub struct StatusMsg {} + +#[cw_serde] +pub struct ExportMetadataMsg {} + +#[cw_serde] +pub struct MerklePath { + pub key_path: Vec, +} + +#[cw_serde] +pub struct VerifyMembershipMsgRaw { + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub proof: Bytes, + pub path: MerklePath, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub value: Bytes, + pub height: RawHeight, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +pub struct VerifyMembershipMsg { + pub prefix: CommitmentPrefix, + pub proof: CommitmentProofBytes, + pub path: Path, + pub value: Vec, + pub height: Height, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +impl TryFrom for VerifyMembershipMsg { + type Error = ContractError; + + fn try_from(mut raw: VerifyMembershipMsgRaw) -> Result { + let proof = CommitmentProofBytes::try_from(raw.proof)?; + let prefix = raw.path.key_path.remove(0).into_bytes(); + let path_str = raw.path.key_path.join(""); + let path = Path::from_str(&path_str)?; + let height = Height::try_from(raw.height).map_err(|e| { + ContractError::Context(ContextError::ClientError(ClientError::Other { + description: e.to_string(), + })) + })?; + Ok(Self { + proof, + path, + value: raw.value, + height, + prefix: CommitmentPrefix::try_from(prefix)?, + delay_block_period: raw.delay_block_period, + delay_time_period: raw.delay_time_period, + }) + } +} + +#[cw_serde] +pub struct VerifyNonMembershipMsgRaw { + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub proof: Bytes, + pub path: MerklePath, + pub height: RawHeight, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +pub struct VerifyNonMembershipMsg { + pub prefix: CommitmentPrefix, + pub proof: CommitmentProofBytes, + pub path: Path, + pub height: Height, + pub delay_block_period: u64, + pub delay_time_period: u64, +} + +impl TryFrom for VerifyNonMembershipMsg { + type Error = ContractError; + + fn try_from(mut raw: VerifyNonMembershipMsgRaw) -> Result { + let proof = CommitmentProofBytes::try_from(raw.proof)?; + let prefix = raw.path.key_path.remove(0).into_bytes(); + let path_str = raw.path.key_path.join(""); + let path = Path::from_str(&path_str)?; + let height = raw.height.try_into().expect("invalid height"); + Ok(Self { + proof, + path, + height, + prefix: CommitmentPrefix::try_from(prefix)?, + delay_block_period: raw.delay_block_period, + delay_time_period: raw.delay_time_period, + }) + } +} + +#[cw_serde] +pub struct WasmMisbehaviour { + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub data: Bytes, +} + +#[cw_serde] +pub struct VerifyClientMessageMsgRaw { + pub client_message: RawClientMessage, +} + +pub struct VerifyClientMessageMsg { + pub client_message: SovTmClientMessage, +} + +impl TryFrom for VerifyClientMessageMsg { + type Error = ContractError; + + fn try_from(raw: VerifyClientMessageMsgRaw) -> Result { + let client_message = Self::decode_client_message(raw.client_message)?; + Ok(Self { client_message }) + } +} + +impl VerifyClientMessageMsg { + fn decode_client_message(raw: RawClientMessage) -> Result { + let maybe_any_header = Any { + type_url: SOV_TENDERMINT_HEADER_TYPE_URL.to_string(), + value: raw.data.clone(), + }; + + if let Ok(header) = Header::try_from(maybe_any_header) { + return Ok(ClientMessage::Header(Box::new(header))); + } + + let maybe_any_misbehaviour = Any { + type_url: SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL.to_string(), + value: raw.data, + }; + + if let Ok(misbehaviour) = SovMisbehaviour::try_from(maybe_any_misbehaviour) { + return Ok(ClientMessage::Misbehaviour(Box::new(misbehaviour))); + } + + Err(ContractError::InvalidMsg( + "Unknown client message type".to_string(), + )) + } +} + +#[cw_serde] +pub struct CheckForMisbehaviourMsgRaw { + pub client_message: RawClientMessage, +} + +pub struct CheckForMisbehaviourMsg { + pub client_message: SovTmClientMessage, +} + +impl TryFrom for CheckForMisbehaviourMsg { + type Error = ContractError; + + fn try_from(raw: CheckForMisbehaviourMsgRaw) -> Result { + let client_message = VerifyClientMessageMsg::decode_client_message(raw.client_message)?; + Ok(Self { client_message }) + } +} + +#[cw_serde] +pub struct UpdateStateOnMisbehaviourMsgRaw { + pub client_message: RawClientMessage, +} + +pub struct UpdateStateOnMisbehaviourMsg { + pub client_message: SovTmClientMessage, +} + +impl TryFrom for UpdateStateOnMisbehaviourMsg { + type Error = ContractError; + + fn try_from(raw: UpdateStateOnMisbehaviourMsgRaw) -> Result { + let client_message = VerifyClientMessageMsg::decode_client_message(raw.client_message)?; + Ok(Self { client_message }) + } +} + +#[cw_serde] +pub struct UpdateStateMsgRaw { + pub client_message: RawClientMessage, +} + +pub struct UpdateStateMsg { + pub client_message: SovTmClientMessage, +} + +impl TryFrom for UpdateStateMsg { + type Error = ContractError; + + fn try_from(raw: UpdateStateMsgRaw) -> Result { + let client_message = VerifyClientMessageMsg::decode_client_message(raw.client_message)?; + Ok(Self { client_message }) + } +} + +#[cw_serde] +pub struct CheckSubstituteAndUpdateStateMsg {} + +#[cw_serde] +pub struct VerifyUpgradeAndUpdateStateMsgRaw { + pub upgrade_client_state: WasmClientState, + pub upgrade_consensus_state: WasmConsensusState, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub proof_upgrade_client: Bytes, + #[schemars(with = "String")] + #[serde(with = "Base64", default)] + pub proof_upgrade_consensus_state: Bytes, +} + +pub struct VerifyUpgradeAndUpdateStateMsg { + pub upgrade_client_state: Any, + pub upgrade_consensus_state: Any, + pub proof_upgrade_client: CommitmentProofBytes, + pub proof_upgrade_consensus_state: CommitmentProofBytes, +} + +impl TryFrom for VerifyUpgradeAndUpdateStateMsg { + type Error = ContractError; + + fn try_from(raw: VerifyUpgradeAndUpdateStateMsgRaw) -> Result { + let upgrade_client_state = Any::decode(&mut raw.upgrade_client_state.data.as_slice())?; + + let upgrade_consensus_state = + Any::decode(&mut raw.upgrade_consensus_state.data.as_slice())?; + + Ok(VerifyUpgradeAndUpdateStateMsg { + upgrade_client_state, + upgrade_consensus_state, + proof_upgrade_client: CommitmentProofBytes::try_from(raw.proof_upgrade_client)?, + proof_upgrade_consensus_state: CommitmentProofBytes::try_from( + raw.proof_upgrade_consensus_state, + )?, + }) + } +} diff --git a/clients/sov-celestia-cw/src/types/processed_states.rs b/clients/sov-celestia-cw/src/types/processed_states.rs new file mode 100644 index 00000000..0dfe5e73 --- /dev/null +++ b/clients/sov-celestia-cw/src/types/processed_states.rs @@ -0,0 +1,199 @@ +use alloc::format; +use alloc::vec::Vec; + +use cosmwasm_std::{Order, Storage}; +use ibc_core::client::types::Height; + +use crate::types::msgs::GenesisMetadata; + +pub struct ProcessedStates<'a>(&'a mut dyn Storage); + +impl<'a> ProcessedStates<'a> { + pub fn new(storage: &'a mut dyn Storage) -> Self { + ProcessedStates(storage) + } + + pub fn processed_time_key(height: Height, prefix: &mut Vec) -> Vec { + prefix.append(&mut "consensusStates/".to_string().into_bytes()); + prefix.append(&mut format!("{height}").into_bytes()); + prefix.append(&mut "/processedTime".to_string().into_bytes()); + prefix.clone() + } + + pub fn processed_height_key(height: Height, prefix: &mut Vec) -> Vec { + prefix.append(&mut "consensusStates/".to_string().into_bytes()); + prefix.append(&mut format!("{height}").into_bytes()); + prefix.append(&mut "/processedHeight".to_string().into_bytes()); + prefix.clone() + } + + pub fn iteration_key(height: Height, prefix: &mut Vec) -> Vec { + prefix.append(&mut "iterateConsensusStates".to_string().into_bytes()); + prefix.append(&mut height.revision_number().to_be_bytes().to_vec()); + prefix.append(&mut height.revision_height().to_be_bytes().to_vec()); + prefix.clone() + } + + pub fn get_processed_time(&self, height: Height, prefix: &mut Vec) -> Option { + let full_key = Self::processed_time_key(height, prefix); + self.0 + .get(&full_key) + .map(|timestamp| u64::from_be_bytes(timestamp.try_into().expect("invalid timestamp"))) + } + + pub fn set_processed_time(&mut self, height: Height, timestamp: u64, prefix: &mut Vec) { + let full_key = Self::processed_time_key(height, prefix); + let time_vec: [u8; 8] = timestamp.to_be_bytes(); + self.0.set(&full_key, &time_vec); + } + + pub fn get_processed_height(&self, height: Height, prefix: &mut Vec) -> Option { + let full_key = Self::processed_height_key(height, prefix); + self.0 + .get(&full_key) + .map(|height| u64::from_be_bytes(height.try_into().expect("invalid height"))) + } + + pub fn set_processed_height( + &mut self, + height: Height, + processed_height: u64, + prefix: &mut Vec, + ) { + let full_key = Self::processed_height_key(height, prefix); + let height_vec: [u8; 8] = processed_height.to_be_bytes(); + self.0.set(&full_key, &height_vec); + } + + pub fn get_iteration_key(&self, height: Height, prefix: &mut Vec) -> Option { + let full_key = Self::iteration_key(height, prefix); + match self.0.get(&full_key) { + Some(height) => match alloc::str::from_utf8(height.as_slice()) { + Ok(height_str) => Height::try_from(height_str).ok(), + Err(_) => None, + }, + None => None, + } + } + + pub fn set_iteration_key(&mut self, height: Height, prefix: &mut Vec) { + let full_key = Self::iteration_key(height, prefix); + let height_vec = format!("{height}").into_bytes(); + self.0.set(&full_key, &height_vec); + } + + pub fn get_earliest_height(&mut self, current_height: Height) -> Option { + let full_key = Self::iteration_key(current_height, &mut Vec::new()); + let start_key = "iterateConsensusStates".to_string().into_bytes(); + let mut iterator = self + .0 + .range(Some(&start_key), Some(&full_key), Order::Ascending); + match iterator.next() { + Some((_, height)) => match alloc::str::from_utf8(height.as_slice()) { + Ok(height_str) => Height::try_from(height_str).ok(), + Err(_) => None, + }, + None => None, + } + } + + pub fn remove_states_at_height(&mut self, height: Height) { + let processed_time_key = Self::processed_time_key(height, &mut Vec::new()); + let processed_height_key = Self::processed_height_key(height, &mut Vec::new()); + let iteration_key = Self::iteration_key(height, &mut Vec::new()); + + self.0.remove(&processed_time_key); + self.0.remove(&processed_height_key); + self.0.remove(&iteration_key) + } +} + +pub struct ReadonlyProcessedStates<'a>(&'a dyn Storage); + +impl<'a> ReadonlyProcessedStates<'a> { + pub fn new(storage: &'a dyn Storage) -> Self { + ReadonlyProcessedStates(storage) + } + + pub fn get_processed_time(&self, height: Height, prefix: &mut Vec) -> Option { + let full_key = ProcessedStates::processed_time_key(height, prefix); + self.0 + .get(&full_key) + .map(|timestamp| u64::from_be_bytes(timestamp.try_into().expect("invalid timestamp"))) + } + + pub fn get_processed_height(&self, height: Height, prefix: &mut Vec) -> Option { + let full_key = ProcessedStates::processed_height_key(height, prefix); + self.0 + .get(&full_key) + .map(|height| u64::from_be_bytes(height.try_into().expect("invalid height"))) + } + + pub fn get_iteration_key(&self, height: Height, prefix: &mut Vec) -> Option { + let full_key = ProcessedStates::iteration_key(height, prefix); + match self.0.get(&full_key) { + Some(height) => match alloc::str::from_utf8(height.as_slice()) { + Ok(height_str) => Height::try_from(height_str).ok(), + Err(_) => None, + }, + None => None, + } + } + + pub fn get_next_height(&self, height: Height) -> Option { + let full_key = ProcessedStates::iteration_key(height, &mut Vec::new()); + let mut iterator = self.0.range(Some(&full_key), None, Order::Ascending); + match iterator.next() { + Some((_, height)) => match alloc::str::from_utf8(height.as_slice()) { + Ok(height_str) => Height::try_from(height_str).ok(), + Err(_) => None, + }, + None => None, + } + } + + pub fn get_prev_height(&self, height: Height) -> Option { + let full_key = ProcessedStates::iteration_key(height, &mut Vec::new()); + let mut iterator = self.0.range(None, Some(&full_key), Order::Descending); + match iterator.next() { + Some((_, height)) => match alloc::str::from_utf8(height.as_slice()) { + Ok(height_str) => Height::try_from(height_str).ok(), + Err(_) => None, + }, + None => None, + } + } + + pub fn get_metadata(&self) -> Option> { + let mut gm: Vec = Vec::::new(); + + let start_key = "iterateConsensusStates".to_string().into_bytes(); + let iterator = self.0.range(Some(&start_key), None, Order::Ascending); + for (_, height) in iterator { + match alloc::str::from_utf8(height.as_slice()) { + Ok(height_str) => { + let height = Height::try_from(height_str).expect("height"); + let processed_height_key = + ProcessedStates::processed_height_key(height, &mut Vec::new()); + gm.push(GenesisMetadata { + key: processed_height_key.clone(), + value: self.0.get(&processed_height_key).expect("processed height"), + }); + let processed_time_key = + ProcessedStates::processed_time_key(height, &mut Vec::new()); + gm.push(GenesisMetadata { + key: processed_time_key.clone(), + value: self.0.get(&processed_time_key).expect("processed time"), + }); + } + Err(_) => break, + } + } + + let iterator = self.0.range(Some(&start_key), None, Order::Ascending); + for (key, height) in iterator { + gm.push(GenesisMetadata { key, value: height }); + } + Some(gm) + } +} diff --git a/clients/sov-celestia-cw/src/types/response.rs b/clients/sov-celestia-cw/src/types/response.rs new file mode 100644 index 00000000..ee17c6c5 --- /dev/null +++ b/clients/sov-celestia-cw/src/types/response.rs @@ -0,0 +1,68 @@ +use alloc::string::String; +use alloc::vec::Vec; + +use cosmwasm_schema::cw_serde; + +use super::msgs::GenesisMetadata; + +#[cw_serde] +pub struct QueryResponse { + pub status: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub genesis_metadata: Option>, +} + +impl QueryResponse { + pub fn status(status: String) -> Self { + Self { + status, + genesis_metadata: None, + } + } + + pub fn genesis_metadata(genesis_metadata: Option>) -> Self { + Self { + status: "".to_string(), + genesis_metadata, + } + } +} + +#[cw_serde] +pub struct ContractResult { + pub is_valid: bool, + pub error_msg: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option>, + pub found_misbehaviour: bool, +} + +impl ContractResult { + pub fn success() -> Self { + Self { + is_valid: true, + error_msg: "".to_string(), + data: None, + found_misbehaviour: false, + } + } + + pub fn error(msg: String) -> Self { + Self { + is_valid: false, + error_msg: msg, + data: None, + found_misbehaviour: false, + } + } + + pub fn misbehaviour(mut self, found: bool) -> Self { + self.found_misbehaviour = found; + self + } + + pub fn data(mut self, data: Vec) -> Self { + self.data = Some(data); + self + } +} diff --git a/clients/sov-celestia/Cargo.toml b/clients/sov-celestia/Cargo.toml new file mode 100644 index 00000000..4ca0abe1 --- /dev/null +++ b/clients/sov-celestia/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "sov-celestia-client" +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } +keywords = ["rollup", "sovereign", "ibc", "light-client"] +readme = "./../README.md" +description = """ + Contains the implementation of `sov-celestia` light client, and re-exports + essential data structures and domain types from `ibc-core-client-types` crate. +""" + +[dependencies] +# external dependencies +derive_more = { workspace = true } +prost = { workspace = true } +schemars = { workspace = true, optional = true } +serde = { workspace = true, features = ["derive"], optional = true } +typed-builder = { version = "0.18.0", optional = true } + +# ibc dependencies +ibc-core = { workspace = true } +ibc-client-tendermint = { workspace = true } +sov-celestia-client-types = { path = "./types", default-features = false } +ics23 = { version = "0.11", default-features = false } + +# DA layer dependencies +tendermint = { workspace = true } +tendermint-proto = { workspace = true } +tendermint-light-client-verifier = { workspace = true } + +[features] +default = ["std"] +std = [ + "ibc-core/std", + "ibc-client-tendermint/std", + "sov-celestia-client-types/std", + "ics23/std", + "prost/std", + "serde/std", + "tendermint/std" +] +serde = [ + "ibc-core/serde", + "ibc-client-tendermint/serde", + "sov-celestia-client-types/serde", + "ics23/serde", + "dep:serde", +] +json-schema = [ + "ibc-core/schema", + "dep:schemars", +] diff --git a/clients/sov-celestia/src/client_state.rs b/clients/sov-celestia/src/client_state.rs new file mode 100644 index 00000000..bad6d27d --- /dev/null +++ b/clients/sov-celestia/src/client_state.rs @@ -0,0 +1,382 @@ +//! Implements the core [`ClientState`](ibc_core::client::context::client_state::ClientState) trait +//! for the Sovereign light client. +use alloc::vec::Vec; +use core::convert::{TryFrom, TryInto}; + +use ibc_core::client::context::client_state::{ + ClientStateCommon, ClientStateExecution, ClientStateValidation, +}; +use ibc_core::client::context::consensus_state::ConsensusState as ConsensusStateTrait; +use ibc_core::client::context::{ClientExecutionContext, ClientValidationContext}; +use ibc_core::client::types::error::ClientError; +use ibc_core::client::types::{Height, Status, UpdateKind}; +use ibc_core::commitment_types::commitment::{ + CommitmentPrefix, CommitmentProofBytes, CommitmentRoot, +}; +use ibc_core::host::types::identifiers::{ClientId, ClientType}; +use ibc_core::host::types::path::{ClientConsensusStatePath, ClientStatePath, Path}; +use ibc_core::host::ExecutionContext; +use ibc_core::primitives::proto::{Any, Protobuf}; +use sov_celestia_client_types::client_message::Header; +use sov_celestia_client_types::client_state::{ + sov_client_type, ClientState as ClientStateType, SOV_TENDERMINT_CLIENT_STATE_TYPE_URL, +}; +use sov_celestia_client_types::consensus_state::ConsensusState as ConsensusStateType; +use sov_celestia_client_types::proto::v1::ClientState as RawSovTmClientState; + +use crate::consensus_state::ConsensusState; +use crate::context::{CommonContext, ValidationContext as SovValidationContext}; + +/// Newtype wrapper exists so that we can bypass Rust's orphan rules and +/// implement traits from `ibc::core::client::context` on the `ClientState` +/// type. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, derive_more::From)] +pub struct ClientState(ClientStateType); + +impl ClientState { + pub fn inner(&self) -> &ClientStateType { + &self.0 + } +} + +impl Protobuf for ClientState {} + +impl TryFrom for ClientState { + type Error = ClientError; + + fn try_from(raw: RawSovTmClientState) -> Result { + let sov_client_state = ClientStateType::try_from(raw)?; + + Ok(Self(sov_client_state)) + } +} + +impl From for RawSovTmClientState { + fn from(client_state: ClientState) -> Self { + client_state.0.into() + } +} + +impl Protobuf for ClientState {} + +impl TryFrom for ClientState { + type Error = ClientError; + + fn try_from(raw: Any) -> Result { + let any = ClientStateType::try_from(raw)?; + + Ok(Self(any)) + } +} + +impl From for Any { + fn from(client_state: ClientState) -> Self { + Any { + type_url: SOV_TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(client_state), + } + } +} + +impl ClientStateCommon for ClientState { + fn verify_consensus_state(&self, consensus_state: Any) -> Result<(), ClientError> { + let tm_consensus_state = ConsensusState::try_from(consensus_state)?; + if tm_consensus_state.root().is_empty() { + return Err(ClientError::Other { + description: "empty commitment root".into(), + }); + }; + + Ok(()) + } + + fn client_type(&self) -> ClientType { + sov_client_type() + } + + fn latest_height(&self) -> Height { + self.0.latest_height() + } + + fn validate_proof_height(&self, proof_height: Height) -> Result<(), ClientError> { + if self.latest_height() < proof_height { + return Err(ClientError::InvalidProofHeight { + latest_height: self.latest_height(), + proof_height, + }); + } + Ok(()) + } + + /// Perform client-specific verifications and check all data in the new + /// client state to be the same across all valid clients for the new chain. + /// + /// You can learn more about how to upgrade IBC-connected SDK chains in + /// [this](https://ibc.cosmos.network/main/ibc/upgrades/quick-guide.html) + /// guide + fn verify_upgrade_client( + &self, + _upgraded_client_state: Any, + _upgraded_consensus_state: Any, + _proof_upgrade_client: CommitmentProofBytes, + _proof_upgrade_consensus_state: CommitmentProofBytes, + _root: &CommitmentRoot, + ) -> Result<(), ClientError> { + Ok(()) + } + + fn verify_membership( + &self, + _prefix: &CommitmentPrefix, + _proof: &CommitmentProofBytes, + _root: &CommitmentRoot, + _path: Path, + _value: Vec, + ) -> Result<(), ClientError> { + Ok(()) + } + + fn verify_non_membership( + &self, + _prefix: &CommitmentPrefix, + _proof: &CommitmentProofBytes, + _root: &CommitmentRoot, + _path: Path, + ) -> Result<(), ClientError> { + Ok(()) + } +} + +impl ClientStateValidation for ClientState +where + V: ClientValidationContext + SovValidationContext, + V::AnyConsensusState: TryInto, + ClientError: From<>::Error>, +{ + fn verify_client_message( + &self, + _ctx: &V, + _client_id: &ClientId, + _client_message: Any, + _update_kind: &UpdateKind, + ) -> Result<(), ClientError> { + Ok(()) + } + + fn check_for_misbehaviour( + &self, + _ctx: &V, + _client_id: &ClientId, + _client_message: Any, + _update_kind: &UpdateKind, + ) -> Result { + Ok(false) + } + + fn status(&self, ctx: &V, client_id: &ClientId) -> Result { + if self.0.is_frozen() { + return Ok(Status::Frozen); + } + + let latest_consensus_state: ConsensusState = { + let any_latest_consensus_state = + match ctx.consensus_state(&ClientConsensusStatePath::new( + client_id.clone(), + self.0.latest_height.revision_number(), + self.0.latest_height.revision_height(), + )) { + Ok(cs) => cs, + // if the client state does not have an associated consensus state for its latest height + // then it must be expired + Err(_) => return Ok(Status::Expired), + }; + + any_latest_consensus_state.try_into()? + }; + + // Note: if the `duration_since()` is `None`, indicating that the latest + // consensus state is in the future, then we don't consider the client + // to be expired. + let now = ctx.host_timestamp()?; + if let Some(elapsed_since_latest_consensus_state) = + now.duration_since(&latest_consensus_state.timestamp().into()) + { + if elapsed_since_latest_consensus_state > self.0.tendermint_params.trusting_period { + return Ok(Status::Expired); + } + } + + Ok(Status::Active) + } +} + +impl ClientStateExecution for ClientState +where + E: ClientExecutionContext + SovValidationContext + ExecutionContext, + ::AnyClientState: From, + ::AnyConsensusState: From, +{ + fn initialise( + &self, + ctx: &mut E, + client_id: &ClientId, + consensus_state: Any, + ) -> Result<(), ClientError> { + let host_timestamp = CommonContext::host_timestamp(ctx)?; + let host_height = CommonContext::host_height(ctx)?; + + let sov_consensus_state = ConsensusState::try_from(consensus_state)?; + + ctx.store_client_state(ClientStatePath::new(client_id), self.clone().into())?; + ctx.store_consensus_state( + ClientConsensusStatePath::new( + client_id.clone(), + self.latest_height().revision_number(), + self.latest_height().revision_height(), + ), + sov_consensus_state.into(), + )?; + ctx.store_update_time(client_id.clone(), self.latest_height(), host_timestamp)?; + ctx.store_update_height(client_id.clone(), self.latest_height(), host_height)?; + + Ok(()) + } + + fn update_state( + &self, + ctx: &mut E, + client_id: &ClientId, + header: Any, + ) -> Result, ClientError> { + let header = Header::try_from(header)?; + let header_height = header.height(); + + // self.prune_oldest_consensus_state(ctx, client_id)?; + + let maybe_existing_consensus_state = { + let path_at_header_height = ClientConsensusStatePath::new( + client_id.clone(), + header_height.revision_number(), + header_height.revision_height(), + ); + + CommonContext::consensus_state(ctx, &path_at_header_height).ok() + }; + + if maybe_existing_consensus_state.is_some() { + // if we already had the header installed by a previous relayer + // then this is a no-op. + // + // Do nothing. + } else { + let host_timestamp = CommonContext::host_timestamp(ctx)?; + let host_height = CommonContext::host_height(ctx)?; + + let new_consensus_state = ConsensusStateType::from(header.clone()); + let new_client_state = self.0.clone().with_header(header.da_header)?; + + ctx.store_consensus_state( + ClientConsensusStatePath::new( + client_id.clone(), + new_client_state.latest_height.revision_number(), + new_client_state.latest_height.revision_height(), + ), + ConsensusState::from(new_consensus_state).into(), + )?; + ctx.store_client_state( + ClientStatePath::new(client_id), + ClientState::from(new_client_state).into(), + )?; + ctx.store_update_time(client_id.clone(), header_height, host_timestamp)?; + ctx.store_update_height(client_id.clone(), header_height, host_height)?; + } + + Ok(vec![header_height]) + } + + fn update_state_on_misbehaviour( + &self, + ctx: &mut E, + client_id: &ClientId, + _client_message: Any, + _update_kind: &UpdateKind, + ) -> Result<(), ClientError> { + let frozen_client_state = self.0.clone().with_frozen_height(Height::min(0)); + + let wrapped_frozen_client_state = ClientState::from(frozen_client_state); + + ctx.store_client_state( + ClientStatePath::new(client_id), + wrapped_frozen_client_state.into(), + )?; + + Ok(()) + } + + // Commit the new client state and consensus state to the store + fn update_state_on_upgrade( + &self, + ctx: &mut E, + client_id: &ClientId, + upgraded_client_state: Any, + upgraded_consensus_state: Any, + ) -> Result { + let mut upgraded_client_state = Self::try_from(upgraded_client_state)?; + let upgraded_tm_cons_state = ConsensusState::try_from(upgraded_consensus_state)?; + + upgraded_client_state.0.zero_custom_fields(); + + // Construct new client state and consensus state relayer chosen client + // parameters are ignored. All chain-chosen parameters come from + // committed client, all client-chosen parameters come from current + // client. + let new_client_state = ClientStateType::new( + upgraded_client_state.0.rollup_id, + upgraded_client_state.0.latest_height, + upgraded_client_state.0.upgrade_path, + upgraded_client_state.0.tendermint_params, + ); + + // The new consensus state is merely used as a trusted kernel against + // which headers on the new chain can be verified. The root is just a + // stand-in sentinel value as it cannot be known in advance, thus no + // proof verification will pass. The timestamp and the + // NextValidatorsHash of the consensus state is the blocktime and + // NextValidatorsHash of the last block committed by the old chain. This + // will allow the first block of the new chain to be verified against + // the last validators of the old chain so long as it is submitted + // within the TrustingPeriod of this client. + // NOTE: We do not set processed time for this consensus state since + // this consensus state should not be used for packet verification as + // the root is empty. The next consensus state submitted using update + // will be usable for packet-verification. + let sentinel_root = "sentinel_root".as_bytes().to_vec(); + let new_consensus_state = ConsensusStateType::new( + sentinel_root.into(), + upgraded_tm_cons_state.timestamp(), + upgraded_tm_cons_state.next_validators_hash(), + ); + + let latest_height = new_client_state.latest_height; + let host_timestamp = CommonContext::host_timestamp(ctx)?; + let host_height = CommonContext::host_height(ctx)?; + + ctx.store_client_state( + ClientStatePath::new(client_id), + ClientState::from(new_client_state).into(), + )?; + ctx.store_consensus_state( + ClientConsensusStatePath::new( + client_id.clone(), + latest_height.revision_number(), + latest_height.revision_height(), + ), + ConsensusState::from(new_consensus_state).into(), + )?; + ctx.store_update_time(client_id.clone(), latest_height, host_timestamp)?; + ctx.store_update_height(client_id.clone(), latest_height, host_height)?; + + Ok(latest_height) + } +} diff --git a/clients/sov-celestia/src/consensus_state.rs b/clients/sov-celestia/src/consensus_state.rs new file mode 100644 index 00000000..d11917d5 --- /dev/null +++ b/clients/sov-celestia/src/consensus_state.rs @@ -0,0 +1,77 @@ +use ibc_core::client::context::consensus_state::ConsensusState as ConsensusStateTrait; +use ibc_core::client::types::error::ClientError; +use ibc_core::commitment_types::commitment::CommitmentRoot; +use ibc_core::primitives::proto::{Any, Protobuf}; +use ibc_core::primitives::Timestamp; +use sov_celestia_client_types::consensus_state::ConsensusState as ConsensusStateType; +use sov_celestia_client_types::proto::v1::ConsensusState as RawConsensusState; +use tendermint::{Hash, Time}; + +/// Newtype wrapper around the `ConsensusState` type imported from the +/// `ibc-client-tendermint-types` crate. This wrapper exists so that we can +/// bypass Rust's orphan rules and implement traits from +/// `ibc::core::client::context` on the `ConsensusState` type. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, derive_more::From)] +pub struct ConsensusState(ConsensusStateType); + +impl ConsensusState { + pub fn inner(&self) -> &ConsensusStateType { + &self.0 + } + + pub fn timestamp(&self) -> Time { + self.0.timestamp + } + + pub fn next_validators_hash(&self) -> Hash { + self.0.next_validators_hash + } +} + +impl Protobuf for ConsensusState {} + +impl TryFrom for ConsensusState { + type Error = ClientError; + + fn try_from(raw: RawConsensusState) -> Result { + Ok(Self(ConsensusStateType::try_from(raw)?)) + } +} + +impl From for RawConsensusState { + fn from(client_state: ConsensusState) -> Self { + client_state.0.into() + } +} + +impl Protobuf for ConsensusState {} + +impl TryFrom for ConsensusState { + type Error = ClientError; + + fn try_from(raw: Any) -> Result { + Ok(Self(ConsensusStateType::try_from(raw)?)) + } +} + +impl From for Any { + fn from(client_state: ConsensusState) -> Self { + client_state.0.into() + } +} + +impl ConsensusStateTrait for ConsensusState { + fn root(&self) -> &CommitmentRoot { + &self.0.root + } + + fn timestamp(&self) -> Timestamp { + let time = self.0.timestamp.unix_timestamp_nanos(); + Timestamp::from_nanoseconds(time as u64).expect("invalid timestamp") + } + + fn encode_vec(self) -> Vec { + >::encode_vec(self) + } +} diff --git a/clients/sov-celestia/src/context.rs b/clients/sov-celestia/src/context.rs new file mode 100644 index 00000000..1b702d78 --- /dev/null +++ b/clients/sov-celestia/src/context.rs @@ -0,0 +1,60 @@ +use alloc::string::ToString; + +use ibc_core::client::context::ClientExecutionContext; +use ibc_core::client::types::Height; +use ibc_core::handler::types::error::ContextError; +use ibc_core::host::types::identifiers::ClientId; +use ibc_core::host::types::path::ClientConsensusStatePath; +use ibc_core::primitives::prelude::*; +use ibc_core::primitives::Timestamp; + +use crate::consensus_state::ConsensusState; + +/// Client's context required during both validation and execution +pub trait CommonContext { + type ConversionError: ToString; + type AnyConsensusState: TryInto; + + /// Returns the current timestamp of the local chain. + fn host_timestamp(&self) -> Result; + + /// Returns the current height of the local chain. + fn host_height(&self) -> Result; + + /// Retrieve the consensus state for the given client ID at the specified + /// height. + /// + /// Returns an error if no such state exists. + fn consensus_state( + &self, + client_cons_state_path: &ClientConsensusStatePath, + ) -> Result; + + /// Returns all the heights at which a consensus state is stored + fn consensus_state_heights(&self, client_id: &ClientId) -> Result, ContextError>; +} + +/// Client's context required during validation +pub trait ValidationContext: CommonContext { + /// Search for the lowest consensus state higher than `height`. + fn next_consensus_state( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result, ContextError>; + + /// Search for the highest consensus state lower than `height`. + fn prev_consensus_state( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result, ContextError>; +} + +/// Client's context required during execution. +/// +/// This trait is automatically implemented for all types that implement +/// [`CommonContext`] and [`ClientExecutionContext`] +pub trait ExecutionContext: CommonContext + ClientExecutionContext {} + +impl ExecutionContext for T where T: CommonContext + ClientExecutionContext {} diff --git a/clients/sov-celestia/src/lib.rs b/clients/sov-celestia/src/lib.rs new file mode 100644 index 00000000..6d9a37c3 --- /dev/null +++ b/clients/sov-celestia/src/lib.rs @@ -0,0 +1,23 @@ +#![cfg_attr(not(test), deny(clippy::unwrap_used))] +#![deny( + warnings, + trivial_casts, + trivial_numeric_casts, + unused_import_braces, + unused_qualifications, + rust_2018_idioms +)] +#![forbid(unsafe_code)] + +extern crate alloc; + +pub mod client_state; +pub mod consensus_state; +pub mod context; + +/// Re-exports `sov-celestia` light client data structures from the +/// `sov-celestia-client-types` crate. +pub mod types { + #[doc(inline)] + pub use sov_celestia_client_types::*; +} diff --git a/clients/sov-celestia/types/Cargo.toml b/clients/sov-celestia/types/Cargo.toml new file mode 100644 index 00000000..815ae94a --- /dev/null +++ b/clients/sov-celestia/types/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "sov-celestia-client-types" +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } +repository = { workspace = true } +keywords = ["rollup", "sovereign", "ibc", "light-client"] +readme = "./../../README.md" +description = """ + Encapsulates essential `sov-celestia` light client data structures and domain types, + as specified in the Inter-Blockchain Communication (IBC) protocol. Designed for universal + applicability to facilitate development and integration across diverse IBC-enabled projects. +""" + +[dependencies] +# external dependencies +base64 = { workspace = true, features = ["alloc"] } +bytes = { workspace = true } +derive_more = { workspace = true } +prost = { workspace = true } +schemars = { workspace = true, optional = true } +serde = { workspace = true, features = ["derive"], optional = true } + +# ibc dependencies +ibc-core = { workspace = true } +ibc-client-tendermint = { workspace = true } +ibc-proto = { workspace = true } +ics23 = { version = "0.11", default-features = false } + +# DA layer dependencies +tendermint = { workspace = true } +tendermint-proto = { workspace = true } +tendermint-light-client-verifier = { workspace = true } + +[features] +default = ["std"] +std = [ + "ibc-core/std", + "ibc-client-tendermint/std", + "ibc-proto/std", + "ics23/std", + "bytes/std", + "prost/std", + "serde/std", + "tendermint/std" +] +serde = [ + "ibc-core/serde", + "ibc-client-tendermint/serde", + "ibc-proto/serde", + "ics23/serde", + "dep:serde", +] +json-schema = [ + "ibc-core/schema", + "ibc-client-tendermint/schema", + "ibc-proto/json-schema", + "dep:schemars", +] diff --git a/clients/sov-celestia/types/src/client_message/aggregated_proof.rs b/clients/sov-celestia/types/src/client_message/aggregated_proof.rs new file mode 100644 index 00000000..566dc976 --- /dev/null +++ b/clients/sov-celestia/types/src/client_message/aggregated_proof.rs @@ -0,0 +1,129 @@ +use alloc::vec::Vec; + +use ibc_core::client::types::Height; +use ibc_core::primitives::proto::Protobuf; +use ibc_proto::sovereign::types::v1::{ + AggregatedProof as RawAggregatedProof, AggregatedProofData as RawAggregatedProofData, + ProofDataInfo as RawProofDataInfo, PublicInput as RawPublicInput, +}; + +use crate::error::Error; + +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AggregatedProofData { + pub public_input: PublicInput, + pub proof_data_info: ProofDataInfo, + pub aggregated_proof: AggregatedProof, +} + +impl TryFrom for AggregatedProofData { + type Error = Error; + + fn try_from(raw: RawAggregatedProofData) -> Result { + Ok(Self { + public_input: raw + .public_input + .ok_or(Error::missing("public input"))? + .try_into()?, + proof_data_info: raw + .proof_data_info + .ok_or(Error::missing("proof data info"))? + .try_into()?, + aggregated_proof: raw + .aggregated_proof + .ok_or(Error::missing("aggregated proof"))? + .into(), + }) + } +} + +impl From for RawAggregatedProofData { + fn from(value: AggregatedProofData) -> Self { + Self { + public_input: Some(value.public_input.into()), + proof_data_info: Some(value.proof_data_info.into()), + aggregated_proof: Some(value.aggregated_proof.into()), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct PublicInput { + pub initial_da_block_hash: Vec, + pub final_da_block_hash: Vec, + pub input_state_root: Vec, + pub final_state_root: Vec, +} + +impl TryFrom for PublicInput { + type Error = Error; + + fn try_from(raw: RawPublicInput) -> Result { + Ok(Self { + initial_da_block_hash: raw.initial_da_block_hash, + final_da_block_hash: raw.final_da_block_hash, + input_state_root: raw.initial_state_root, + final_state_root: raw.final_state_root, + }) + } +} + +impl From for RawPublicInput { + fn from(value: PublicInput) -> Self { + Self { + initial_da_block_hash: value.initial_da_block_hash, + final_da_block_hash: value.final_da_block_hash, + initial_state_root: value.input_state_root, + final_state_root: value.final_state_root, + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ProofDataInfo { + pub initial_state_height: Height, + pub final_state_height: Height, +} + +impl Protobuf for ProofDataInfo {} + +impl TryFrom for ProofDataInfo { + type Error = Error; + + fn try_from(raw: RawProofDataInfo) -> Result { + Ok(Self { + initial_state_height: Height::new(0, raw.initial_state_height)?, + final_state_height: Height::new(0, raw.final_state_height)?, + }) + } +} + +impl From for RawProofDataInfo { + fn from(value: ProofDataInfo) -> Self { + Self { + initial_state_height: value.initial_state_height.revision_height(), + final_state_height: value.final_state_height.revision_height(), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AggregatedProof(Vec); + +impl Protobuf for AggregatedProof {} + +impl From for AggregatedProof { + fn from(raw: RawAggregatedProof) -> Self { + Self(raw.proof) + } +} + +impl From for RawAggregatedProof { + fn from(value: AggregatedProof) -> Self { + Self { proof: value.0 } + } +} diff --git a/clients/sov-celestia/types/src/client_message/header.rs b/clients/sov-celestia/types/src/client_message/header.rs new file mode 100644 index 00000000..4f506918 --- /dev/null +++ b/clients/sov-celestia/types/src/client_message/header.rs @@ -0,0 +1,122 @@ +use core::fmt::{Debug, Display, Error as FmtError, Formatter}; + +use ibc_client_tendermint::types::Header as TmHeader; +use ibc_core::client::types::Height; +use ibc_core::host::types::identifiers::ChainId; +use ibc_core::primitives::proto::{Any, Protobuf}; +use ibc_core::primitives::Timestamp; +use ibc_proto::ibc::lightclients::sovereign::tendermint::v1::Header as RawSovTmHeader; + +use super::aggregated_proof::AggregatedProofData; +use crate::client_message::pretty::PrettyAggregatedProofData; +use crate::error::Error; + +pub const SOV_TENDERMINT_HEADER_TYPE_URL: &str = "/ibc.lightclients.sovereign.tendermint.v1.Header"; + +#[derive(Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Header { + pub da_header: H, + pub aggregated_proof_data: AggregatedProofData, +} + +impl Debug for Header { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!(f, "Header {{...}}") + } +} + +impl Display for Header { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!( + f, + "Header {{ da_header: {}, aggregated_proof_data: {} }}", + &self.da_header, + PrettyAggregatedProofData(&self.aggregated_proof_data) + ) + } +} + +/// Header type alias for the Sovereign SDK rollups operating on the +/// Tendermint-driven DA layer. +pub type SovTmHeader = Header; + +impl SovTmHeader { + pub fn timestamp(&self) -> Timestamp { + self.da_header.timestamp() + } + + pub fn height(&self) -> Height { + self.da_header.height() + } + + pub fn verify_chain_id_version_matches_height(&self, chain_id: &ChainId) -> Result<(), Error> { + self.da_header + .verify_chain_id_version_matches_height(chain_id) + .map_err(Error::source) + } + + /// Checks if the fields of a given header are consistent with the trusted fields of this header. + pub fn validate_basic(&self) -> Result<(), Error> { + self.da_header.validate_basic().map_err(Error::source) + } +} + +impl Protobuf for SovTmHeader {} + +impl TryFrom for SovTmHeader { + type Error = Error; + + fn try_from(value: RawSovTmHeader) -> Result { + let da_header = value + .da_header + .ok_or(Error::missing("missing core header"))?; + + let da_header = TmHeader::try_from(da_header).map_err(Error::source)?; + + let aggregated_proof_data = value + .aggregated_proof_data + .ok_or(Error::missing("missing aggregated proof"))? + .try_into()?; + + Ok(Header { + da_header, + aggregated_proof_data, + }) + } +} + +impl From for RawSovTmHeader { + fn from(value: SovTmHeader) -> RawSovTmHeader { + RawSovTmHeader { + da_header: Some(value.da_header.into()), + aggregated_proof_data: Some(value.aggregated_proof_data.into()), + } + } +} + +impl Protobuf for SovTmHeader {} + +impl TryFrom for SovTmHeader { + type Error = Error; + + fn try_from(any: Any) -> Result { + let msg = match any.type_url.as_str() { + SOV_TENDERMINT_HEADER_TYPE_URL => { + Protobuf::::decode_vec(&any.value).map_err(Error::source)? + } + _ => Err(Error::invalid(any.type_url.clone()))?, + }; + + Ok(msg) + } +} + +impl From for Any { + fn from(header: SovTmHeader) -> Self { + Any { + type_url: SOV_TENDERMINT_HEADER_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(header), + } + } +} diff --git a/clients/sov-celestia/types/src/client_message/misbehaviour.rs b/clients/sov-celestia/types/src/client_message/misbehaviour.rs new file mode 100644 index 00000000..379a5242 --- /dev/null +++ b/clients/sov-celestia/types/src/client_message/misbehaviour.rs @@ -0,0 +1,165 @@ +//! Defines the misbehaviour type for the Sovereign light client + +use alloc::format; + +use ibc_client_tendermint::types::{Header as TmHeader, Misbehaviour}; +use ibc_core::client::types::error::ClientError; +use ibc_core::host::types::identifiers::ClientId; +use ibc_core::primitives::proto::{Any, Protobuf}; +use ibc_proto::ibc::lightclients::sovereign::tendermint::v1::Misbehaviour as RawSovTmMisbehaviour; + +use super::header::{Header, SovTmHeader}; +use crate::error::Error; + +pub const SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL: &str = + "/ibc.lightclients.sovereign.tendermint.v1.Misbehaviour"; + +/// Sovereign light client's misbehaviour type +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SovMisbehaviour { + client_id: ClientId, + header1: Header, + header2: Header, +} + +/// Misbehaviour type alias for the Sovereign SDK rollups operating on the +/// Tendermint-driven DA layer. +pub type SovTmMisbehaviour = SovMisbehaviour; + +impl SovTmMisbehaviour { + pub fn new(client_id: ClientId, header1: SovTmHeader, header2: SovTmHeader) -> Self { + Self { + client_id, + header1, + header2, + } + } + + pub fn client_id(&self) -> &ClientId { + &self.client_id + } + + pub fn header1(&self) -> &SovTmHeader { + &self.header1 + } + + pub fn header2(&self) -> &SovTmHeader { + &self.header2 + } + + pub fn validate_basic(&self) -> Result<(), Error> { + self.header1.validate_basic()?; + self.header2.validate_basic()?; + + if self.header1.da_header.signed_header.header.chain_id + != self.header2.da_header.signed_header.header.chain_id + { + return Err(Error::invalid("headers must have identical chain_ids")); + } + + if self.header1.height() < self.header2.height() { + return Err(Error::invalid(format!( + "header1 height is less than header2 height ({} < {})", + self.header1.height(), + self.header2.height() + ))); + } + + Ok(()) + } + + pub fn into_tendermint_misbehaviour(&self) -> Misbehaviour { + Misbehaviour::new( + self.client_id.clone(), + self.header1.da_header.clone(), + self.header2.da_header.clone(), + ) + } +} + +impl core::fmt::Display for SovTmMisbehaviour { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { + write!( + f, + "{} h1: {}-{} h2: {}-{}", + self.client_id, + self.header1.height(), + self.header1.da_header, + self.header2.height(), + self.header2.da_header, + ) + } +} + +impl Protobuf for SovTmMisbehaviour {} + +impl TryFrom for SovTmMisbehaviour { + type Error = ClientError; + #[allow(deprecated)] + fn try_from(raw: RawSovTmMisbehaviour) -> Result { + let client_id = raw.client_id.parse().map_err(|_| ClientError::Other { + description: "".into(), + })?; + + let header1: SovTmHeader = raw + .header_1 + .ok_or(ClientError::Other { + description: "".into(), + })? + .try_into()?; + + let header2: SovTmHeader = raw + .header_2 + .ok_or(ClientError::Other { + description: "".into(), + })? + .try_into()?; + + Ok(Self::new(client_id, header1, header2)) + } +} + +impl From for RawSovTmMisbehaviour { + fn from(value: SovTmMisbehaviour) -> Self { + #[allow(deprecated)] + RawSovTmMisbehaviour { + client_id: value.client_id.to_string(), + header_1: Some(value.header1.into()), + header_2: Some(value.header2.into()), + } + } +} + +impl Protobuf for SovTmMisbehaviour {} + +impl TryFrom for SovTmMisbehaviour { + type Error = ClientError; + + fn try_from(raw: Any) -> Result { + fn decode_misbehaviour(value: &[u8]) -> Result { + let misbehaviour = Protobuf::::decode(value).map_err(|e| { + ClientError::Other { + description: e.to_string(), + } + })?; + Ok(misbehaviour) + } + + match raw.type_url.as_str() { + SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL => decode_misbehaviour(&raw.value), + _ => Err(ClientError::Other { + description: "".into(), + }), + } + } +} + +impl From for Any { + fn from(misbehaviour: SovTmMisbehaviour) -> Self { + Any { + type_url: SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(misbehaviour), + } + } +} diff --git a/clients/sov-celestia/types/src/client_message/mod.rs b/clients/sov-celestia/types/src/client_message/mod.rs new file mode 100644 index 00000000..3e173dd6 --- /dev/null +++ b/clients/sov-celestia/types/src/client_message/mod.rs @@ -0,0 +1,72 @@ +mod aggregated_proof; +mod header; +mod misbehaviour; +mod pretty; + +use core::fmt::Debug; + +pub use aggregated_proof::*; +pub use header::*; +use ibc_client_tendermint::types::Header as TmHeader; +use ibc_core::primitives::prelude::*; +use ibc_core::primitives::proto::{Any, Protobuf}; +use ibc_proto::ibc::lightclients::sovereign::tendermint::v1::{ + Header as RawSovTmHeader, Misbehaviour as RawSovTmMisbehaviour, +}; +pub use misbehaviour::*; + +use crate::error::Error; + +/// Defines the union ClientMessage type allowing to submit all possible +/// messages for updating clients or reporting misbehaviour. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum ClientMessage +where + H: Clone + Debug, +{ + Header(Box>), + Misbehaviour(Box>), +} + +/// ClientMessage type alias for the Sovereign SDK rollups operating on the +/// Tendermint-driven DA layer. +pub type SovTmClientMessage = ClientMessage; + +impl Protobuf for SovTmClientMessage {} + +impl TryFrom for SovTmClientMessage { + type Error = Error; + + fn try_from(any: Any) -> Result { + let msg = match &*any.type_url { + SOV_TENDERMINT_HEADER_TYPE_URL => { + let header = + Protobuf::::decode(&*any.value).map_err(Error::source)?; + Self::Header(Box::new(header)) + } + SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL => { + let misbehaviour = + Protobuf::::decode(&*any.value).map_err(Error::source)?; + Self::Misbehaviour(Box::new(misbehaviour)) + } + _ => Err(Error::invalid(format!("Unknown type: {}", any.type_url)))?, + }; + + Ok(msg) + } +} + +impl From for Any { + fn from(msg: SovTmClientMessage) -> Self { + match msg { + ClientMessage::Header(header) => Any { + type_url: SOV_TENDERMINT_HEADER_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(*header), + }, + ClientMessage::Misbehaviour(misbehaviour) => Any { + type_url: SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(*misbehaviour), + }, + } + } +} diff --git a/clients/sov-celestia/types/src/client_message/pretty.rs b/clients/sov-celestia/types/src/client_message/pretty.rs new file mode 100644 index 00000000..69ab8ffc --- /dev/null +++ b/clients/sov-celestia/types/src/client_message/pretty.rs @@ -0,0 +1,70 @@ +use core::fmt::{Display, Error as FmtError, Formatter}; + +use super::aggregated_proof::AggregatedProofData; +use super::{AggregatedProof, ProofDataInfo}; +use crate::client_message::aggregated_proof::PublicInput; +pub struct PrettySlice<'a, T>(pub &'a [T]); + +impl<'a, T: Display> Display for PrettySlice<'a, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!(f, "[ ")?; + let mut vec_iterator = self.0.iter().peekable(); + while let Some(element) = vec_iterator.next() { + write!(f, "{element}")?; + // If it is not the last element, add separator. + if vec_iterator.peek().is_some() { + write!(f, ", ")?; + } + } + write!(f, " ]") + } +} + +pub struct PrettyAggregatedProofData<'a>(pub &'a AggregatedProofData); + +impl Display for PrettyAggregatedProofData<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!( + f, + "AggregatedProofData {{ public_input: {}, proof_data_info: {}, aggregated_proof: {} }}", + PrettyPublicInput(&self.0.public_input), + PrettyProofDataInfo(&self.0.proof_data_info), + PrettyAggregatedProof(&self.0.aggregated_proof) + ) + } +} + +pub struct PrettyPublicInput<'a>(pub &'a PublicInput); + +impl Display for PrettyPublicInput<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!( + f, + "PublicInput {{ initial_da_block_hash: {:?}, final_da_block_hash: {:?}, input_state_root: {:?}, post_state_root: {:?} }}", + self.0.initial_da_block_hash, + self.0.final_da_block_hash, + self.0.input_state_root, + self.0.final_state_root + ) + } +} + +pub struct PrettyProofDataInfo<'a>(pub &'a ProofDataInfo); + +impl Display for PrettyProofDataInfo<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!( + f, + "ProofDataInfo {{ initial_state_height: {}, final_state_height: {} }}", + self.0.initial_state_height, self.0.final_state_height + ) + } +} + +pub struct PrettyAggregatedProof<'a>(pub &'a AggregatedProof); + +impl Display for PrettyAggregatedProof<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!(f, "AggregatedProof {{ {:?} }}", self.0) + } +} diff --git a/clients/sov-celestia/types/src/client_state/da_params.rs b/clients/sov-celestia/types/src/client_state/da_params.rs new file mode 100644 index 00000000..ebe8bf50 --- /dev/null +++ b/clients/sov-celestia/types/src/client_state/da_params.rs @@ -0,0 +1,94 @@ +use core::time::Duration; + +use ibc_client_tendermint::types::TrustThreshold; +use ibc_core::host::types::identifiers::ChainId; +use ibc_core::primitives::proto::Protobuf; +use ibc_proto::ibc::lightclients::sovereign::tendermint::v1::{ + Fraction, TendermintParams as RawTendermintParams, +}; + +use crate::error::Error; + +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TendermintParams { + pub chain_id: ChainId, + pub trust_level: TrustThreshold, + pub trusting_period: Duration, + pub unbonding_period: Duration, + pub max_clock_drift: Duration, +} + +impl TendermintParams { + pub fn new( + chain_id: ChainId, + trust_level: TrustThreshold, + trusting_period: Duration, + unbonding_period: Duration, + max_clock_drift: Duration, + ) -> Self { + Self { + chain_id, + trust_level, + trusting_period, + unbonding_period, + max_clock_drift, + } + } +} + +impl Protobuf for TendermintParams {} + +impl TryFrom for TendermintParams { + type Error = Error; + + fn try_from(raw: RawTendermintParams) -> Result { + let chain_id = raw.chain_id.parse().map_err(Error::source)?; + + let trust_level = { + let fraction = raw.trust_level.ok_or(Error::missing("trust_level"))?; + TrustThreshold::new(fraction.numerator, fraction.denominator)? + }; + + let trusting_period = raw + .trusting_period + .ok_or(Error::missing("trusting_period"))? + .try_into() + .map_err(|_| Error::invalid("trusting_period"))?; + + let unbonding_period = raw + .unbonding_period + .ok_or(Error::missing("unbonding_period"))? + .try_into() + .map_err(|_| Error::invalid("unbonding_period"))?; + + let max_clock_drift = raw + .max_clock_drift + .ok_or(Error::missing("max_clock_drift"))? + .try_into() + .map_err(|_| Error::invalid("max_clock_drift"))?; + + Ok(Self::new( + chain_id, + trust_level, + trusting_period, + unbonding_period, + max_clock_drift, + )) + } +} + +impl From for RawTendermintParams { + fn from(value: TendermintParams) -> Self { + Self { + chain_id: value.chain_id.to_string(), + trust_level: Some(Fraction { + numerator: value.trust_level.numerator(), + denominator: value.trust_level.denominator(), + }), + trusting_period: Some(value.trusting_period.into()), + unbonding_period: Some(value.unbonding_period.into()), + max_clock_drift: Some(value.max_clock_drift.into()), + } + } +} diff --git a/clients/sov-celestia/types/src/client_state/definition.rs b/clients/sov-celestia/types/src/client_state/definition.rs new file mode 100644 index 00000000..cdfdc37a --- /dev/null +++ b/clients/sov-celestia/types/src/client_state/definition.rs @@ -0,0 +1,159 @@ +use core::cmp::max; + +use ibc_client_tendermint::types::{Header as TmHeader, TrustThreshold}; +use ibc_core::client::types::error::ClientError; +use ibc_core::client::types::Height; +use ibc_core::host::types::identifiers::ChainId; +use ibc_core::primitives::proto::{Any, Protobuf}; +use ibc_core::primitives::ZERO_DURATION; +use ibc_proto::ibc::lightclients::sovereign::tendermint::v1::ClientState as RawClientState; + +use super::TendermintParams; +use crate::error::Error; + +pub const SOV_TENDERMINT_CLIENT_STATE_TYPE_URL: &str = + "/ibc.lightclients.sovereign.tendermint.v1.ClientState"; + +/// Contains the core implementation of the Sovereign light client +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq)] +pub struct ClientState { + pub rollup_id: ChainId, + pub latest_height: Height, + pub frozen_height: Option, + pub upgrade_path: Vec, + pub tendermint_params: TendermintParams, +} + +impl ClientState { + pub fn new( + rollup_id: ChainId, + latest_height: Height, + upgrade_path: Vec, + tendermint_params: TendermintParams, + ) -> Self { + Self { + rollup_id, + latest_height, + frozen_height: None, + upgrade_path, + tendermint_params, + } + } + + pub fn rollup_id(&self) -> &ChainId { + &self.rollup_id + } + + pub fn chain_id(&self) -> &ChainId { + &self.tendermint_params.chain_id + } + + pub fn latest_height(&self) -> Height { + self.latest_height + } + + pub fn is_frozen(&self) -> bool { + self.frozen_height.is_some() + } + + pub fn with_header(self, header: TmHeader) -> Result { + Ok(Self { + latest_height: max(header.height(), self.latest_height), + ..self + }) + } + + pub fn with_frozen_height(self, h: Height) -> Self { + Self { + frozen_height: Some(h), + ..self + } + } + + // Resets custom fields to zero values (used in `update_client`) + pub fn zero_custom_fields(&mut self) { + self.frozen_height = None; + self.tendermint_params.trusting_period = ZERO_DURATION; + self.tendermint_params.trust_level = TrustThreshold::ZERO; + self.tendermint_params.max_clock_drift = ZERO_DURATION; + } +} + +impl Protobuf for ClientState {} + +impl TryFrom for ClientState { + type Error = ClientError; + + fn try_from(raw: RawClientState) -> Result { + let rollup_id = raw.rollup_id.parse().map_err(Error::source)?; + + let latest_height = raw + .latest_height + .ok_or(Error::missing("latest_height"))? + .try_into()?; + + if raw.frozen_height.is_some() { + return Err(Error::invalid("frozen_height is not supported"))?; + } + + let upgrade_path = raw.upgrade_path; + + let tendermint_params = raw + .tendermint_params + .ok_or(Error::missing("tendermint_params"))? + .try_into()?; + + Ok(Self::new( + rollup_id, + latest_height, + upgrade_path, + tendermint_params, + )) + } +} + +impl From for RawClientState { + fn from(value: ClientState) -> Self { + Self { + rollup_id: value.rollup_id.to_string(), + latest_height: Some(value.latest_height.into()), + frozen_height: value.frozen_height.map(|h| h.into()), + upgrade_path: value.upgrade_path, + tendermint_params: Some(value.tendermint_params.into()), + } + } +} + +impl Protobuf for ClientState {} + +impl TryFrom for ClientState { + type Error = ClientError; + + fn try_from(raw: Any) -> Result { + fn decode_client_state(value: &[u8]) -> Result { + let client_state = + Protobuf::::decode(value).map_err(|e| ClientError::Other { + description: e.to_string(), + })?; + + Ok(client_state) + } + + match raw.type_url.as_str() { + SOV_TENDERMINT_CLIENT_STATE_TYPE_URL => decode_client_state(&raw.value), + _ => Err(ClientError::UnknownClientStateType { + client_state_type: raw.type_url, + }), + } + } +} + +impl From for Any { + fn from(client_state: ClientState) -> Self { + Any { + type_url: SOV_TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(client_state), + } + } +} diff --git a/clients/sov-celestia/types/src/client_state/mod.rs b/clients/sov-celestia/types/src/client_state/mod.rs new file mode 100644 index 00000000..d123be76 --- /dev/null +++ b/clients/sov-celestia/types/src/client_state/mod.rs @@ -0,0 +1,15 @@ +mod da_params; +mod definition; + +use alloc::str::FromStr; + +pub use da_params::*; +pub use definition::*; +use ibc_core::host::types::identifiers::ClientType; + +pub const SOV_CELESTIA_CLIENT_TYPE: &str = "100-sov-celestia"; + +/// Returns the `ClientType` for the Sovereign SDK Rollups. +pub fn sov_client_type() -> ClientType { + ClientType::from_str(SOV_CELESTIA_CLIENT_TYPE).expect("Never fails because it's valid") +} diff --git a/clients/sov-celestia/types/src/consensus_state/definition.rs b/clients/sov-celestia/types/src/consensus_state/definition.rs new file mode 100644 index 00000000..7f5b0c65 --- /dev/null +++ b/clients/sov-celestia/types/src/consensus_state/definition.rs @@ -0,0 +1,145 @@ +//! Defines Sovereign's `ConsensusState` type + +use ibc_core::client::types::error::ClientError; +use ibc_core::commitment_types::commitment::CommitmentRoot; +use ibc_core::primitives::proto::{Any, Protobuf}; +use ibc_proto::ibc::lightclients::sovereign::tendermint::v1::ConsensusState as RawConsensusState; +use tendermint::hash::Algorithm; +use tendermint::time::Time; +use tendermint::Hash; +use tendermint_proto::google::protobuf as tpb; + +use crate::client_message::SovTmHeader; + +pub const SOV_TENDERMINT_CONSENSUS_STATE_TYPE_URL: &str = + "/ibc.lightclients.sovereign.tendermint.v1.ConsensusState"; + +/// Defines the Sovereign light client's consensus state +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ConsensusState { + pub timestamp: Time, + pub root: CommitmentRoot, + pub next_validators_hash: Hash, +} + +impl ConsensusState { + pub fn new(root: CommitmentRoot, timestamp: Time, next_validators_hash: Hash) -> Self { + Self { + timestamp, + root, + next_validators_hash, + } + } +} + +impl Protobuf for ConsensusState {} + +impl TryFrom for ConsensusState { + type Error = ClientError; + + fn try_from(raw: RawConsensusState) -> Result { + let proto_root = raw + .root + .ok_or(ClientError::Other { + description: "missing root".to_string(), + })? + .hash; + + let ibc_proto::google::protobuf::Timestamp { seconds, nanos } = + raw.timestamp.ok_or(ClientError::Other { + description: "missing timestamp".to_string(), + })?; + + let proto_timestamp = tpb::Timestamp { seconds, nanos }; + let timestamp = proto_timestamp.try_into().map_err(|_| ClientError::Other { + description: "invalid timestamp".to_string(), + })?; + + let next_validators_hash = Hash::from_bytes(Algorithm::Sha256, &raw.next_validators_hash) + .map_err(|_| ClientError::Other { + description: "invalid next validators hash".to_string(), + })?; + + Ok(Self { + root: proto_root.into(), + timestamp, + next_validators_hash, + }) + } +} + +impl From for RawConsensusState { + fn from(value: ConsensusState) -> Self { + let tpb::Timestamp { seconds, nanos } = value.timestamp.into(); + let timestamp = ibc_proto::google::protobuf::Timestamp { seconds, nanos }; + + RawConsensusState { + timestamp: Some(timestamp), + root: Some(ibc_proto::ibc::core::commitment::v1::MerkleRoot { + hash: value.root.into_vec(), + }), + next_validators_hash: value.next_validators_hash.as_bytes().to_vec(), + } + } +} + +impl Protobuf for ConsensusState {} + +impl TryFrom for ConsensusState { + type Error = ClientError; + + fn try_from(raw: Any) -> Result { + fn decode_consensus_state(value: &[u8]) -> Result { + let consensus_state = + Protobuf::::decode(value).map_err(|e| ClientError::Other { + description: e.to_string(), + })?; + Ok(consensus_state) + } + + match raw.type_url.as_str() { + SOV_TENDERMINT_CONSENSUS_STATE_TYPE_URL => decode_consensus_state(&raw.value), + _ => Err(ClientError::UnknownConsensusStateType { + consensus_state_type: raw.type_url, + }), + } + } +} + +impl From for Any { + fn from(consensus_state: ConsensusState) -> Self { + Any { + type_url: SOV_TENDERMINT_CONSENSUS_STATE_TYPE_URL.to_string(), + value: Protobuf::::encode_vec(consensus_state), + } + } +} + +impl From for ConsensusState { + fn from(header: tendermint::block::Header) -> Self { + Self { + root: CommitmentRoot::from_bytes(header.app_hash.as_ref()), + timestamp: header.time, + next_validators_hash: header.next_validators_hash, + } + } +} + +impl From for ConsensusState { + fn from(header: SovTmHeader) -> Self { + let tm_header = header.da_header.signed_header.header; + + Self { + root: CommitmentRoot::from_bytes( + header + .aggregated_proof_data + .public_input + .final_state_root + .as_ref(), + ), + timestamp: tm_header.time, + next_validators_hash: tm_header.next_validators_hash, + } + } +} diff --git a/clients/sov-celestia/types/src/consensus_state/mod.rs b/clients/sov-celestia/types/src/consensus_state/mod.rs new file mode 100644 index 00000000..23862836 --- /dev/null +++ b/clients/sov-celestia/types/src/consensus_state/mod.rs @@ -0,0 +1,3 @@ +mod definition; + +pub use definition::*; diff --git a/clients/sov-celestia/types/src/error.rs b/clients/sov-celestia/types/src/error.rs new file mode 100644 index 00000000..14602a3d --- /dev/null +++ b/clients/sov-celestia/types/src/error.rs @@ -0,0 +1,202 @@ +use alloc::string::{String, ToString}; + +use ibc_core::client::types::error::ClientError; +use ibc_core::handler::types::error::ContextError; +use ibc_core::host::types::error::IdentifierError; +use tendermint_light_client_verifier::Verdict; + +/// Defines the error type for Sovereign light client. +#[derive(Clone, Debug)] +pub struct Error { + /// Error code. + pub code: Code, + /// Refers to the type or place that error originated from or pertains to. + pub origin: String, + /// (optional) The given value caused the error. + pub given: Option, + /// (optional) The expected value. + pub expected: Option, +} + +impl Error { + /// Constructs a new error instance with the given code and message. + pub fn new(code: Code, origin: impl Into) -> Self { + Self { + code, + origin: origin.into(), + given: None, + expected: None, + } + } + + /// Constructs an `Empty` error with the given message. + pub fn empty(origin: impl Into) -> Self { + Self::new(Code::Empty, origin) + } + + /// Constructs a `Missing` error with the given message. + pub fn missing(origin: impl Into) -> Self { + Self::new(Code::Missing, origin) + } + + /// Constructs an `AlreadyExists` error with the given message. + pub fn already_exists(origin: impl Into) -> Self { + Self::new(Code::AlreadyExists, origin) + } + + /// Constructs an `Invalid` error with the given message. + pub fn invalid(origin: impl Into) -> Self { + Self::new(Code::Invalid, origin) + } + + /// Constructs a `MisMatch` error with the given message. + pub fn mismatch(origin: impl Into) -> Self { + Self::new(Code::Mismatch, origin) + } + + /// Constructs a `NotAllowed` error with the given message. + pub fn not_allowed(origin: impl Into) -> Self { + Self::new(Code::NotAllowed, origin) + } + + /// Constructs a `NotSupported` error with the given message. + pub fn not_supported(origin: impl Into) -> Self { + Self::new(Code::NotSupported, origin) + } + + /// Constructs a `Source` error with the given message. + pub fn source(origin: impl ToString) -> Self { + Self { + code: Code::Source, + origin: origin.to_string(), + expected: None, + given: None, + } + } + + /// Adds an expected value to the error message. + pub fn expected(&self, expected: &impl ToString) -> Self { + Self { + expected: Some(expected.to_string()), + ..self.clone() + } + } + + /// Adds a given value to the error message. + pub fn given(&self, given: &impl ToString) -> Self { + Self { + given: Some(given.to_string()), + ..self.clone() + } + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Code: {} Origin: {}", self.code, self.origin)?; + + if let Some(given) = &self.given { + write!(f, ", Given: {}", given)?; + } + + if let Some(expected) = &self.expected { + write!(f, ", Expected: {}", expected)?; + } + + Ok(()) + } +} + +/// Defines all the possible error types and their corresponding codes +#[derive(Clone, Debug)] +pub enum Code { + /// cannot be empty! + Empty = 0, + + /// missing! + Missing = 1, + + /// already exists! + AlreadyExists = 2, + + /// has invalid state! + Invalid = 3, + + /// state mismatch! + Mismatch = 4, + + /// not allowed! + NotAllowed = 5, + + /// not supported! + NotSupported = 6, + + /// from other source! + Source = 7, +} + +impl Code { + /// Returns a string description of the error code. + pub fn description(&self) -> &'static str { + match self { + Code::Empty => "cannot be empty!", + Code::Missing => "missing!", + Code::AlreadyExists => "already exists!", + Code::Invalid => "invalid state!", + Code::Mismatch => "state mismatch!", + Code::NotAllowed => "not allowed!", + Code::NotSupported => "not supported!", + Code::Source => "from other source!", + } + } +} + +impl core::fmt::Display for Code { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Display::fmt(self.description(), f) + } +} + +impl From for Error { + fn from(err: ContextError) -> Self { + Self::source(err) + } +} + +impl From for Error { + fn from(err: ClientError) -> Self { + Self::source(err) + } +} + +impl From for ClientError { + fn from(err: Error) -> Self { + ClientError::Other { + description: err.to_string(), + } + } +} + +impl From for Error { + fn from(err: IdentifierError) -> Self { + Self::source(err) + } +} + +pub trait IntoResult { + fn into_result(self) -> Result; +} + +impl IntoResult<(), ClientError> for Verdict { + fn into_result(self) -> Result<(), ClientError> { + match self { + Verdict::Success => Ok(()), + Verdict::NotEnoughTrust(reason) => Err(ClientError::Other { + description: reason.to_string(), + }), + Verdict::Invalid(detail) => Err(ClientError::Other { + description: detail.to_string(), + }), + } + } +} diff --git a/clients/sov-celestia/types/src/lib.rs b/clients/sov-celestia/types/src/lib.rs new file mode 100644 index 00000000..385cffb7 --- /dev/null +++ b/clients/sov-celestia/types/src/lib.rs @@ -0,0 +1,24 @@ +#![cfg_attr(not(test), deny(clippy::unwrap_used))] +#![deny( + warnings, + trivial_casts, + trivial_numeric_casts, + unused_import_braces, + unused_qualifications, + rust_2018_idioms +)] +#![forbid(unsafe_code)] + +extern crate alloc; + +pub mod client_message; +pub mod client_state; +pub mod consensus_state; +pub mod error; + +/// Re-exports Sovereign SDK rollup light clients proto types from +/// `ibc_proto-rs` +pub mod proto { + pub use ibc_proto::ibc::lightclients::sovereign::tendermint::*; + pub use ibc_proto::sovereign::*; +} diff --git a/mocks/Cargo.toml b/mocks/Cargo.toml index cba5cdd8..636e7945 100644 --- a/mocks/Cargo.toml +++ b/mocks/Cargo.toml @@ -15,6 +15,7 @@ anyhow = { workspace = true } async-trait = { version = "0.1.74", default-features = false } base64 = { workspace = true } borsh = { workspace = true } +hex = "0.4.3" prost = { workspace = true } sha2 = { version = "0.10.6", default-features = false } serde = { workspace = true } @@ -28,20 +29,22 @@ tracing = "0.1.36" typed-builder = "0.18.0" # internal dependencies -sov-ibc = { path = "../modules/sov-ibc" } -sov-ibc-transfer = { path = "../modules/sov-ibc-transfer" } +sov-ibc = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "b9ac0b1" } +sov-ibc-transfer = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "b9ac0b1" } +sov-celestia-client = { git = "https://github.com/informalsystems/sovereign-ibc.git", rev = "b9ac0b1" } # ibc dependencies ibc-core = { workspace = true } ibc-app-transfer = { workspace = true } ibc-client-tendermint = { workspace = true } +ibc-client-wasm-types = { workspace = true, features = ["cosmwasm"] } ibc-core-host-cosmos = { workspace = true } ibc-query = { workspace = true } ibc-testkit = { workspace = true } # cosmos dependencies -basecoin-app = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "25d86e6" } -basecoin-store = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "25d86e6" } +basecoin-app = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "d093cb1" } +basecoin-store = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "d093cb1" } tendermint = { workspace = true } tendermint-testgen = { workspace = true } @@ -58,8 +61,8 @@ sov-rollup-interface = { workspace = true } jmt = { git = "https://github.com/penumbra-zone/jmt.git", rev = "1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6" } [dev-dependencies] -test-log = { version = "0.2.14", default-features = false, features = ["trace"] } -tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } +test-log = { version = "0.2.14", default-features = false, features = ["trace"] } +tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } [features] default = ["native"] diff --git a/mocks/src/configs.rs b/mocks/src/configs.rs index 0e115ac8..c7ab9246 100644 --- a/mocks/src/configs.rs +++ b/mocks/src/configs.rs @@ -17,14 +17,17 @@ use crate::sovereign::{celestia_da_service, mock_da_service, GenesisConfig, Runt #[derive(TypedBuilder, Clone, Debug)] pub struct TestSetupConfig { + /// The chain Id of the DA chain. + #[builder(default = ChainId::new("mock-celestia-0").unwrap())] + pub da_chain_id: ChainId, + /// The da service. + pub da_service: Da, /// The chain Id of the rollup. #[builder(default = ChainId::new("mock-rollup-0").unwrap())] - pub rollup_chain_id: ChainId, + pub rollup_id: ChainId, /// The runtime configuration. #[builder(default = RuntimeConfig::default())] pub rollup_runtime_config: RuntimeConfig, - /// The da service. - pub da_service: Da, /// Sets whether to use manual IBC TAO or not. #[builder(default = false)] pub with_manual_tao: bool, diff --git a/mocks/src/cosmos/app.rs b/mocks/src/cosmos/app.rs index f5b60ed6..8a521f6b 100644 --- a/mocks/src/cosmos/app.rs +++ b/mocks/src/cosmos/app.rs @@ -17,7 +17,7 @@ use ibc_core::host::types::identifiers::ChainId; use tendermint::abci::request::Query as RequestQuery; use tendermint::abci::response::Query as ResponseQuery; -use super::helpers::convert_tm_to_ics_merkle_proof; +use super::utils::convert_tm_to_ics_merkle_proof; use super::MockTendermint; #[derive(Clone)] diff --git a/mocks/src/cosmos/helpers/dummy.rs b/mocks/src/cosmos/configs.rs similarity index 68% rename from mocks/src/cosmos/helpers/dummy.rs rename to mocks/src/cosmos/configs.rs index dcb74bbf..1214948c 100644 --- a/mocks/src/cosmos/helpers/dummy.rs +++ b/mocks/src/cosmos/configs.rs @@ -1,33 +1,38 @@ -use std::time::Duration; - use basecoin_store::avl::get_proof_spec; -use ibc_client_tendermint::types::{AllowUpdate, ClientState}; +use ibc_client_tendermint::client_state::ClientState; +use ibc_client_tendermint::types::ConsensusState as TmConsensusState; use ibc_core::client::types::Height; use ibc_core::commitment_types::specs::ProofSpecs; use ibc_core::host::types::identifiers::ChainId; use ibc_core::primitives::Signer; +use ibc_testkit::fixtures::clients::tendermint::ClientStateConfig; use ibc_testkit::fixtures::core::signer::dummy_bech32_account; - +use tendermint::{Hash, Time}; pub fn basecoin_proof_specs() -> ProofSpecs { [get_proof_spec(), get_proof_spec()].to_vec().into() } pub fn dummy_tm_client_state(chain_id: ChainId, latest_height: Height) -> ClientState { - ClientState::new( - chain_id, - Default::default(), - Duration::from_secs(64000), - Duration::from_secs(128000), - Duration::from_millis(3000), - latest_height, - basecoin_proof_specs(), - Default::default(), - AllowUpdate { - after_expiry: false, - after_misbehaviour: false, - }, + ClientStateConfig::builder() + .chain_id(chain_id) + .latest_height(latest_height) + .proof_specs(basecoin_proof_specs()) + .build() + .try_into() + .unwrap() +} + +pub fn dummy_tm_consensus_state() -> TmConsensusState { + TmConsensusState::new( + vec![0].into(), + Time::now(), + // Hash for default validator set + Hash::Sha256([ + 0xd6, 0xb9, 0x39, 0x22, 0xc3, 0x3a, 0xae, 0xbe, 0xc9, 0x4, 0x35, 0x66, 0xcb, 0x4b, + 0x1b, 0x48, 0x36, 0x5b, 0x13, 0x58, 0xb6, 0x7c, 0x7d, 0xef, 0x98, 0x6d, 0x9e, 0xe1, + 0x86, 0x1b, 0xc1, 0x43, + ]), ) - .unwrap() } pub fn genesis_app_state() -> serde_json::Value { diff --git a/mocks/src/cosmos/core.rs b/mocks/src/cosmos/core.rs index c3eeca0b..e22b379a 100644 --- a/mocks/src/cosmos/core.rs +++ b/mocks/src/cosmos/core.rs @@ -17,7 +17,7 @@ pub struct MockTendermint { #[builder(default = Arc::new(Runtime::new().unwrap()))] runtime: Arc, /// Chain identifier - #[builder(default = ChainId::from_str("mock-cosmos-chain-0").expect("never fails"))] + #[builder(default = ChainId::from_str("mock-cosmos-0").expect("never fails"))] chain_id: ChainId, /// Chain validators #[builder(default = Arc::new(Mutex::new(vec![ diff --git a/mocks/src/cosmos/helpers/mod.rs b/mocks/src/cosmos/helpers/mod.rs deleted file mode 100644 index 542ce970..00000000 --- a/mocks/src/cosmos/helpers/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod convert; -pub mod dummy; - -pub use convert::convert_tm_to_ics_merkle_proof; -pub use dummy::{dummy_signer, dummy_tm_client_state, genesis_app_state}; diff --git a/mocks/src/cosmos/manual.rs b/mocks/src/cosmos/manual.rs index 40c4d122..584f272a 100644 --- a/mocks/src/cosmos/manual.rs +++ b/mocks/src/cosmos/manual.rs @@ -3,18 +3,12 @@ use core::fmt::Debug; -use basecoin_app::modules::ibc::AnyConsensusState; use basecoin_store::context::ProvableStore; -use ibc_client_tendermint::client_state::ClientState as TmClientState; -use ibc_client_tendermint::types::{ - client_type as tm_client_type, ConsensusState as TmConsensusState, -}; use ibc_core::channel::types::channel::{ ChannelEnd, Counterparty as ChanCounterparty, Order, State as ChannelState, }; use ibc_core::channel::types::Version as ChannelVersion; -use ibc_core::client::context::client_state::ClientStateCommon; -use ibc_core::client::context::ClientExecutionContext; +use ibc_core::client::context::client_state::ClientStateExecution; use ibc_core::commitment_types::commitment::CommitmentPrefix; use ibc_core::connection::types::version::Version as ConnectionVersion; use ibc_core::connection::types::{ @@ -24,65 +18,33 @@ use ibc_core::host::types::identifiers::{ ChainId, ChannelId, ClientId, ConnectionId, PortId, Sequence, }; use ibc_core::host::types::path::{ - ChannelEndPath, ClientConsensusStatePath, ClientStatePath, ConnectionPath, SeqAckPath, - SeqRecvPath, SeqSendPath, + ChannelEndPath, ConnectionPath, SeqAckPath, SeqRecvPath, SeqSendPath, }; use ibc_core::host::{ExecutionContext, ValidationContext}; -use tendermint::{Hash, Time}; +use sov_celestia_client::types::client_state::sov_client_type; -use super::{dummy_tm_client_state, MockCosmosChain}; +use super::MockCosmosChain; +use crate::sovereign::{dummy_sov_client_state, dummy_sov_consensus_state}; impl MockCosmosChain { /// Establishes a tendermint light client on the ibc module pub fn setup_client(&mut self, client_chain_id: &ChainId) -> ClientId { let client_counter = self.ibc_ctx().client_counter().unwrap(); - let client_id = tm_client_type().build_client_id(client_counter); - - let client_state_path = ClientStatePath::new(&client_id); + let client_id = sov_client_type().build_client_id(client_counter); let current_height = self.ibc_ctx().host_height().unwrap(); - let client_state = dummy_tm_client_state(client_chain_id.clone(), current_height); + let client_state = dummy_sov_client_state(client_chain_id.clone(), current_height); - let latest_height = TmClientState::from(client_state.clone()).latest_height(); - - self.ibc_ctx() - .store_update_time( - client_id.clone(), - latest_height, - self.ibc_ctx().host_timestamp().unwrap(), - ) - .unwrap(); + let consensus_state = dummy_sov_consensus_state(); - self.ibc_ctx() - .store_update_height( - client_id.clone(), - latest_height, - self.ibc_ctx().host_height().unwrap(), - ) + client_state + .initialise(&mut self.ibc_ctx(), &client_id, consensus_state.into()) .unwrap(); self.ibc_ctx().increase_client_counter().unwrap(); - self.ibc_ctx() - .store_client_state(client_state_path, client_state.into()) - .unwrap(); - - let consensus_state_path = ClientConsensusStatePath::new( - client_id.clone(), - current_height.revision_number(), - current_height.revision_height(), - ); - - let consensus_state = AnyConsensusState::Tendermint( - TmConsensusState::new(vec![].into(), Time::now(), Hash::None).into(), - ); - - self.ibc_ctx() - .store_consensus_state(consensus_state_path, consensus_state) - .unwrap(); - client_id } diff --git a/mocks/src/cosmos/mod.rs b/mocks/src/cosmos/mod.rs index a123831f..97c64623 100644 --- a/mocks/src/cosmos/mod.rs +++ b/mocks/src/cosmos/mod.rs @@ -1,12 +1,13 @@ mod app; mod builder; +mod configs; mod core; -mod helpers; mod manual; mod runner; +mod utils; pub use core::*; pub use app::*; pub use builder::*; -pub use helpers::*; +pub use configs::*; diff --git a/mocks/src/cosmos/runner.rs b/mocks/src/cosmos/runner.rs index 74a8bc08..e3329ce5 100644 --- a/mocks/src/cosmos/runner.rs +++ b/mocks/src/cosmos/runner.rs @@ -8,7 +8,7 @@ use basecoin_store::utils::SharedRwExt; use tendermint::abci::request::InitChain; use tendermint::block::Height as TmHeight; use tendermint::v0_37::abci::Request as AbciRequest; -use tendermint::{AppHash, Time}; +use tendermint::Time; use tendermint_testgen::consensus::default_consensus_params; use tokio::task::JoinHandle; use tower::Service; @@ -19,8 +19,6 @@ use crate::utils::wait_for_block; impl MockCosmosChain { /// Initialize the chain with the app state. async fn init(&self) { - self.core.grow_blocks(AppHash::default().into()); - let app_state = serde_json::to_vec(&genesis_app_state()).expect("infallible serialization"); let request = InitChain { diff --git a/mocks/src/cosmos/helpers/convert.rs b/mocks/src/cosmos/utils.rs similarity index 100% rename from mocks/src/cosmos/helpers/convert.rs rename to mocks/src/cosmos/utils.rs diff --git a/mocks/src/lib.rs b/mocks/src/lib.rs index 8596b74f..5cf0afc3 100644 --- a/mocks/src/lib.rs +++ b/mocks/src/lib.rs @@ -1,9 +1,7 @@ -pub mod cosmos; - #[cfg(feature = "native")] pub mod configs; +pub mod cosmos; pub mod relayer; -#[cfg(feature = "native")] pub mod sovereign; pub mod utils; diff --git a/mocks/src/relayer/builder.rs b/mocks/src/relayer/builder.rs index d75e8f34..92899325 100644 --- a/mocks/src/relayer/builder.rs +++ b/mocks/src/relayer/builder.rs @@ -1,6 +1,7 @@ use ibc_client_tendermint::types::client_type as tm_client_type; use ibc_core::host::types::identifiers::Sequence; use ibc_core::host::ValidationContext; +use sov_celestia_client::types::client_state::sov_client_type; use sov_mock_da::MockDaService; use sov_modules_api::default_context::DefaultContext; use sov_modules_api::{Context, WorkingSet}; @@ -10,7 +11,7 @@ use tracing::info; use super::DefaultRelayer; use crate::configs::{default_config_with_mock_da, TestSetupConfig}; -use crate::cosmos::{dummy_signer, CosmosBuilder}; +use crate::cosmos::{dummy_signer, CosmosBuilder, MockTendermint}; use crate::relayer::handle::{Handle, QueryReq, QueryResp}; use crate::relayer::relay::MockRelayer; use crate::sovereign::{MockRollup, Runtime, DEFAULT_INIT_HEIGHT}; @@ -70,10 +71,12 @@ where let prover_storage = ProverStorage::with_path(path).unwrap(); let mut rollup = MockRollup::new( - self.setup_cfg.rollup_chain_id.clone(), runtime, prover_storage, rollup_ctx, + MockTendermint::builder() + .chain_id(self.setup_cfg.da_chain_id.clone()) + .build(), self.setup_cfg.da_service.clone(), ); @@ -84,8 +87,7 @@ where _ => panic!("Unexpected response"), }; - // TODO: this should be updated when there is a light client for sovereign chains - let sov_client_id = tm_client_type().build_client_id(sov_client_counter); + let sov_client_id = sov_client_type().build_client_id(sov_client_counter); let mut cos_chain = CosmosBuilder::default().build(); @@ -101,16 +103,16 @@ where let cos_client_id = tm_client_type().build_client_id(cos_client_counter); if self.setup_cfg.with_manual_tao { - let sov_client_id = rollup.setup_client(cos_chain.chain_id()).await; - let cos_client_id = cos_chain.setup_client(rollup.chain_id()); + let cos_client_id = rollup.setup_client(cos_chain.chain_id()).await; + let sov_client_id = cos_chain.setup_client(rollup.chain_id()); let sov_conn_id = rollup - .setup_connection(sov_client_id, cos_chain.ibc_ctx().commitment_prefix()) + .setup_connection(cos_client_id, cos_chain.ibc_ctx().commitment_prefix()) .await; let mut working_set = WorkingSet::new(rollup.prover_storage()); let cos_conn_id = cos_chain.setup_connection( - cos_client_id, + sov_client_id, rollup.ibc_ctx(&mut working_set).commitment_prefix(), ); diff --git a/mocks/src/relayer/handle/rollup.rs b/mocks/src/relayer/handle/rollup.rs index 53d75aba..543ccbf4 100644 --- a/mocks/src/relayer/handle/rollup.rs +++ b/mocks/src/relayer/handle/rollup.rs @@ -1,6 +1,8 @@ use async_trait::async_trait; +use ibc_client_tendermint::types::Header; use ibc_core::channel::types::proto::v1::QueryPacketCommitmentRequest; use ibc_core::client::types::proto::v1::{QueryClientStateRequest, QueryConsensusStateRequest}; +use ibc_core::client::types::Height; use ibc_core::handler::types::events::IbcEvent; use ibc_core::host::types::path::{ClientConsensusStatePath, Path}; use ibc_core::host::ValidationContext; @@ -10,7 +12,7 @@ use sov_state::{MerkleProofSpec, ProverStorage}; use tracing::info; use crate::relayer::handle::{Handle, QueryReq, QueryResp}; -use crate::sovereign::{MockRollup, RuntimeCall}; +use crate::sovereign::{dummy_sov_header, MockRollup, RuntimeCall}; use crate::utils::{wait_for_block, MutexUtil}; #[async_trait] @@ -51,8 +53,31 @@ where .unwrap() .into(), ), - QueryReq::Header(_, _) => { - unimplemented!() + QueryReq::Header(target_height, trusted_height) => { + let blocks = self.da_core.blocks(); + + let revision_height = target_height.revision_height() as usize; + + if revision_height > blocks.len() { + panic!("block index out of bounds"); + } + + let target_block = blocks[revision_height - 1].clone(); + + let header = Header { + signed_header: target_block.signed_header, + validator_set: target_block.validators, + trusted_height, + trusted_next_validator_set: target_block.next_validators, + }; + + let sov_header = dummy_sov_header( + header, + Height::new(0, 1).unwrap(), + Height::new(0, revision_height as u64).unwrap(), + ); + + QueryResp::Header(sov_header.into()) } QueryReq::NextSeqSend(path) => { QueryResp::NextSeqSend(ibc_ctx.get_next_sequence_send(&path).unwrap()) @@ -87,7 +112,6 @@ where QueryResp::ValueWithProof(resp.consensus_state.unwrap().value, resp.proof) } - Path::Commitment(path) => { let req = QueryPacketCommitmentRequest { port_id: path.port_id.to_string(), diff --git a/mocks/src/relayer/msgs/cosmos.rs b/mocks/src/relayer/msgs/cosmos.rs index 30f17f49..92ff8993 100644 --- a/mocks/src/relayer/msgs/cosmos.rs +++ b/mocks/src/relayer/msgs/cosmos.rs @@ -4,10 +4,10 @@ use std::str::FromStr; use base64::engine::general_purpose; use base64::Engine; +use basecoin_app::modules::ibc::AnyClientState; use ibc_app_transfer::types::msgs::transfer::MsgTransfer; use ibc_app_transfer::types::packet::PacketData; use ibc_app_transfer::types::{Coin, Memo, PrefixedDenom}; -use ibc_client_tendermint::types::client_type as tm_client_type; use ibc_core::channel::types::msgs::MsgRecvPacket; use ibc_core::channel::types::packet::Packet; use ibc_core::channel::types::timeout::TimeoutHeight; @@ -15,20 +15,16 @@ use ibc_core::client::context::client_state::ClientStateCommon; use ibc_core::client::types::msgs::{MsgCreateClient, MsgUpdateClient}; use ibc_core::client::types::Height; use ibc_core::commitment_types::commitment::CommitmentProofBytes; -use ibc_core::commitment_types::merkle::MerkleProof; -use ibc_core::commitment_types::proto::ics23::CommitmentProof; use ibc_core::host::types::identifiers::{ChannelId, PortId}; use ibc_core::host::types::path::{CommitmentPath, Path, SeqSendPath}; use ibc_core::primitives::proto::Any; use ibc_core::primitives::{Signer, Timestamp, ToProto}; -use ibc_testkit::testapp::ibc::clients::AnyClientState; -use prost::Message; use sov_ibc::context::HOST_REVISION_NUMBER; use crate::configs::TransferTestConfig; -use crate::cosmos::dummy_tm_client_state; use crate::relayer::handle::{Handle, QueryReq, QueryResp}; use crate::relayer::relay::MockRelayer; +use crate::sovereign::dummy_sov_client_state; impl MockRelayer where @@ -47,7 +43,7 @@ where _ => panic!("unexpected query response"), }; - let tm_client_state = dummy_tm_client_state(chain_id, current_height); + let sov_client_state = dummy_sov_client_state(chain_id, current_height); let consensus_state = match self .src_chain_ctx() @@ -59,7 +55,7 @@ where }; let msg_create_client = MsgCreateClient { - client_state: tm_client_state.into(), + client_state: sov_client_state.into(), consensus_state, signer: self.src_chain_ctx().signer().clone(), }; @@ -69,12 +65,7 @@ where /// Builds an update client message of type `Any` pub async fn build_msg_update_client_for_cos(&self, target_height: Height) -> Any { - let client_counter = match self.dst_chain_ctx().query(QueryReq::ClientCounter).await { - QueryResp::ClientCounter(counter) => counter, - _ => panic!("unexpected query response"), - }; - - let client_id = tm_client_type().build_client_id(client_counter); + let client_id = self.src_client_id().clone(); let any_client_state = match self .dst_chain_ctx() @@ -147,7 +138,8 @@ where proof_height_on_a: Height, msg_transfer: MsgTransfer, ) -> MsgRecvPacket { - let seq_send_path = SeqSendPath::new(&PortId::transfer(), &ChannelId::default()); + let seq_send_path = + SeqSendPath::new(&msg_transfer.port_id_on_a, &msg_transfer.chan_id_on_a); let resp = self .src_chain_ctx() @@ -161,8 +153,11 @@ where let latest_seq_send = (u64::from(next_seq_send) - 1).into(); - let commitment_path = - CommitmentPath::new(&seq_send_path.0, &seq_send_path.1, latest_seq_send); + let commitment_path = CommitmentPath::new( + &msg_transfer.port_id_on_a, + &msg_transfer.chan_id_on_a, + latest_seq_send, + ); let resp = self .src_chain_ctx() @@ -177,28 +172,7 @@ where _ => panic!("unexpected query response"), }; - let commitment_proofs = CommitmentProofBytes::try_from(proof_bytes).unwrap(); - - let merkle_proofs = MerkleProof::try_from(&commitment_proofs).unwrap(); - - let resp = self - .dst_chain_ctx() - .query(QueryReq::ValueWithProof( - Path::Commitment(commitment_path.clone()), - proof_height_on_a, - )) - .await; - - let (_, proof_bytes) = match resp { - QueryResp::ValueWithProof(value, proof) => (value, proof), - _ => panic!("unexpected query response"), - }; - - let proof_commitment_on_a = - CommitmentProof::decode(proof_bytes.as_slice()).expect("no error"); - - assert_eq!(merkle_proofs.proofs[0], proof_commitment_on_a); - assert_eq!(merkle_proofs.proofs.len(), 2); + let proof_commitment_on_a = CommitmentProofBytes::try_from(proof_bytes).unwrap(); let packet = Packet { seq_on_a: latest_seq_send, @@ -213,7 +187,7 @@ where MsgRecvPacket { packet, - proof_commitment_on_a: merkle_proofs.try_into().expect("no error"), + proof_commitment_on_a, proof_height_on_a, signer: self.dst_chain_ctx().signer().clone(), } diff --git a/mocks/src/relayer/msgs/rollup.rs b/mocks/src/relayer/msgs/rollup.rs index b01d6563..2b3840d6 100644 --- a/mocks/src/relayer/msgs/rollup.rs +++ b/mocks/src/relayer/msgs/rollup.rs @@ -6,7 +6,6 @@ use base64::Engine; use ibc_app_transfer::types::msgs::transfer::MsgTransfer; use ibc_app_transfer::types::packet::PacketData; use ibc_app_transfer::types::{Coin, PrefixedDenom}; -use ibc_client_tendermint::types::client_type as tm_client_type; use ibc_core::channel::types::msgs::MsgRecvPacket; use ibc_core::channel::types::packet::Packet; use ibc_core::channel::types::timeout::TimeoutHeight; @@ -67,14 +66,7 @@ where /// Builds an update client message wrapped in a `CallMessage` pub async fn build_msg_update_client_for_sov(&self, target_height: Height) -> CallMessage { - let client_counter = match self.src_chain_ctx().query(QueryReq::ClientCounter).await { - QueryResp::ClientCounter(counter) => counter, - _ => panic!("unexpected query response"), - } - .checked_sub(1) - .unwrap(); - - let client_id = tm_client_type().build_client_id(client_counter); + let client_id = self.dst_client_id().clone(); let any_client_state = match self .src_chain_ctx() @@ -141,7 +133,8 @@ where proof_height_on_a: Height, msg_transfer: MsgTransfer, ) -> CallMessage { - let seq_send_path = SeqSendPath::new(&PortId::transfer(), &ChannelId::default()); + let seq_send_path = + SeqSendPath::new(&msg_transfer.port_id_on_a, &msg_transfer.chan_id_on_a); let next_seq_send = match self .dst_chain_ctx() @@ -154,8 +147,11 @@ where let latest_seq_send = (u64::from(next_seq_send) - 1).into(); - let commitment_path = - CommitmentPath::new(&seq_send_path.0, &seq_send_path.1, latest_seq_send); + let commitment_path = CommitmentPath::new( + &msg_transfer.port_id_on_a, + &msg_transfer.chan_id_on_a, + latest_seq_send, + ); let (_, proof_bytes) = match self .dst_chain_ctx() diff --git a/mocks/src/sovereign/configs.rs b/mocks/src/sovereign/configs.rs new file mode 100644 index 00000000..0f3412e9 --- /dev/null +++ b/mocks/src/sovereign/configs.rs @@ -0,0 +1,224 @@ +use std::time::Duration; + +use ibc_client_tendermint::types::{Header as TmHeader, TrustThreshold}; +use ibc_client_wasm_types::client_state::ClientState as WasmClientState; +use ibc_client_wasm_types::consensus_state::ConsensusState as WasmConsensusState; +use ibc_core::client::types::Height; +use ibc_core::host::types::identifiers::ChainId; +use ibc_core::primitives::proto::Any; +use sov_celestia_client::client_state::ClientState; +use sov_celestia_client::types::client_message::{ + AggregatedProof, AggregatedProofData, ProofDataInfo, PublicInput, SovTmHeader, +}; +use sov_celestia_client::types::client_state::{ClientState as ClientStateType, TendermintParams}; +use sov_celestia_client::types::consensus_state::ConsensusState; +use sov_celestia_client::types::proto::types::v1::AggregatedProof as RawAggregatedProof; +use tendermint::{Hash, Time}; +#[derive(typed_builder::TypedBuilder, Debug)] +#[builder(build_method(into = ClientState))] +pub struct ClientStateConfig { + pub rollup_id: ChainId, + pub latest_height: Height, + #[builder(default)] + pub frozen_height: Option, + #[builder(default)] + pub upgrade_path: Vec, + pub tendermint_params: TendermintParams, +} + +impl From for ClientState { + fn from(config: ClientStateConfig) -> Self { + ClientStateType::new( + config.rollup_id, + config.latest_height, + config.upgrade_path, + config.tendermint_params, + ) + .into() + } +} + +#[derive(typed_builder::TypedBuilder, Debug)] +#[builder(build_method(into = TendermintParams))] +pub struct TendermintParamsConfig { + #[builder(default = ChainId::new("mock-celestia-0").expect("Never fails"))] + pub chain_id: ChainId, + #[builder(default)] + pub trust_level: TrustThreshold, + #[builder(default = Duration::from_secs(64000))] + pub trusting_period: Duration, + #[builder(default = Duration::from_secs(128000))] + pub unbonding_period: Duration, + #[builder(default = Duration::from_millis(3000))] + pub max_clock_drift: Duration, +} + +impl From for TendermintParams { + fn from(config: TendermintParamsConfig) -> Self { + Self::new( + config.chain_id, + config.trust_level, + config.trusting_period, + config.unbonding_period, + config.max_clock_drift, + ) + } +} + +#[derive(typed_builder::TypedBuilder, Debug)] +#[builder(build_method(into = SovTmHeader))] +pub struct HeaderConfig { + pub da_header: TmHeader, + pub aggregated_proof_data: AggregatedProofData, +} + +impl From for SovTmHeader { + fn from(config: HeaderConfig) -> Self { + Self { + da_header: config.da_header, + aggregated_proof_data: config.aggregated_proof_data, + } + } +} + +#[derive(typed_builder::TypedBuilder, Debug)] +#[builder(build_method(into = AggregatedProofData))] +pub struct AggregatedProofDataConfig { + #[builder(default)] + pub public_input: PublicInputConfig, + pub proof_data_info: ProofDataInfoConfig, + #[builder(default)] + pub aggregated_proof: AggregatedProofConfig, +} + +impl From for AggregatedProofData { + fn from(config: AggregatedProofDataConfig) -> Self { + Self { + public_input: config.public_input.into(), + proof_data_info: config.proof_data_info.into(), + aggregated_proof: config.aggregated_proof.into(), + } + } +} + +#[derive(typed_builder::TypedBuilder, Debug, Default)] +pub struct PublicInputConfig { + #[builder(default)] + pub initial_da_block_hash: Vec, + #[builder(default)] + pub final_da_block_hash: Vec, + #[builder(default)] + pub input_state_root: Vec, + #[builder(default)] + pub final_state_root: Vec, +} + +impl From for PublicInput { + fn from(config: PublicInputConfig) -> Self { + Self { + initial_da_block_hash: config.initial_da_block_hash, + final_da_block_hash: config.final_da_block_hash, + input_state_root: config.input_state_root, + final_state_root: config.final_state_root, + } + } +} + +#[derive(typed_builder::TypedBuilder, Debug)] +pub struct ProofDataInfoConfig { + pub initial_state_height: Height, + pub final_state_height: Height, +} + +impl From for ProofDataInfo { + fn from(config: ProofDataInfoConfig) -> Self { + Self { + initial_state_height: config.initial_state_height, + final_state_height: config.final_state_height, + } + } +} + +#[derive(typed_builder::TypedBuilder, Debug, Default)] +pub struct AggregatedProofConfig { + #[builder(default)] + pub proof: Vec, +} + +impl From for AggregatedProof { + fn from(config: AggregatedProofConfig) -> Self { + Self::from(RawAggregatedProof { + proof: config.proof, + }) + } +} + +pub fn dummy_sov_header( + da_header: TmHeader, + initial_state_height: Height, + final_state_height: Height, +) -> SovTmHeader { + let aggregated_proof_data = AggregatedProofDataConfig::builder() + .proof_data_info( + ProofDataInfoConfig::builder() + .initial_state_height(initial_state_height) + .final_state_height(final_state_height) + .build(), + ) + .build(); + + HeaderConfig::builder() + .da_header(da_header) + .aggregated_proof_data(aggregated_proof_data) + .build() +} + +pub fn dummy_sov_client_state(rollup_id: ChainId, latest_height: Height) -> ClientState { + let tendermint_params = TendermintParamsConfig::builder().build(); + + ClientStateConfig::builder() + .rollup_id(rollup_id) + .latest_height(latest_height) + .tendermint_params(tendermint_params) + .build() +} + +pub fn dummy_sov_consensus_state() -> ConsensusState { + ConsensusState::new( + vec![0].into(), + Time::now(), + // Hash of default validator set + Hash::Sha256([ + 0xd6, 0xb9, 0x39, 0x22, 0xc3, 0x3a, 0xae, 0xbe, 0xc9, 0x4, 0x35, 0x66, 0xcb, 0x4b, + 0x1b, 0x48, 0x36, 0x5b, 0x13, 0x58, 0xb6, 0x7c, 0x7d, 0xef, 0x98, 0x6d, 0x9e, 0xe1, + 0x86, 0x1b, 0xc1, 0x43, + ]), + ) +} + +pub fn dummy_wasm_client_state() -> WasmClientState { + let tendermint_params = TendermintParamsConfig::builder() + .chain_id("test-1".parse().unwrap()) + .build(); + + let checksum = + hex::decode("2469f43c3ca20d476442bd3d98cbd97a180776ab37332aa7b02cae5a620acfc6").unwrap(); + + let client_state = ClientStateConfig::builder() + .rollup_id("mock-celestia-0".parse().unwrap()) + .latest_height(Height::new(0, 1).unwrap()) + .tendermint_params(tendermint_params) + .build(); + + WasmClientState { + data: Any::from(client_state.clone()).value, + checksum, + latest_height: client_state.inner().latest_height, + } +} + +pub fn dummy_wasm_consensus_state() -> WasmConsensusState { + WasmConsensusState { + data: Any::from(dummy_sov_consensus_state()).value, + } +} diff --git a/mocks/src/sovereign/manual.rs b/mocks/src/sovereign/manual.rs index 31b3e3ee..e6325d01 100644 --- a/mocks/src/sovereign/manual.rs +++ b/mocks/src/sovereign/manual.rs @@ -1,15 +1,12 @@ //! Contains helper functions to manually setup the ibc module state //! on the mock rollup. -use ibc_client_tendermint::types::{ - client_type as tm_client_type, ConsensusState as TmConsensusState, -}; +use ibc_client_tendermint::types::client_type as tm_client_type; use ibc_core::channel::types::channel::{ ChannelEnd, Counterparty as ChanCounterparty, Order, State as ChannelState, }; use ibc_core::channel::types::Version as ChannelVersion; -use ibc_core::client::context::client_state::ClientStateCommon; -use ibc_core::client::context::ClientExecutionContext; +use ibc_core::client::context::client_state::ClientStateExecution; use ibc_core::commitment_types::commitment::CommitmentPrefix; use ibc_core::connection::types::version::Version as ConnectionVersion; use ibc_core::connection::types::{ @@ -19,19 +16,16 @@ use ibc_core::host::types::identifiers::{ ChainId, ChannelId, ClientId, ConnectionId, PortId, Sequence, }; use ibc_core::host::types::path::{ - ChannelEndPath, ClientConsensusStatePath, ClientStatePath, ConnectionPath, SeqAckPath, - SeqRecvPath, SeqSendPath, + ChannelEndPath, ConnectionPath, SeqAckPath, SeqRecvPath, SeqSendPath, }; use ibc_core::host::{ExecutionContext, ValidationContext}; -use sov_ibc::clients::{AnyClientState, AnyConsensusState}; use sov_ibc::context::IbcContext; use sov_modules_api::{Context, WorkingSet}; use sov_rollup_interface::services::da::DaService; use sov_state::{MerkleProofSpec, ProverStorage}; -use tendermint::{Hash, Time}; use super::MockRollup; -use crate::cosmos::dummy_tm_client_state; +use crate::cosmos::{dummy_tm_client_state, dummy_tm_consensus_state}; impl MockRollup where @@ -51,64 +45,18 @@ where let client_id = tm_client_type().build_client_id(client_counter); - let client_state_path = ClientStatePath::new(&client_id); - let current_height = ibc_ctx.host_height().unwrap(); - let client_state = AnyClientState::Tendermint( - dummy_tm_client_state(client_chain_id.clone(), current_height).into(), - ); + let client_state = dummy_tm_client_state(client_chain_id.clone(), current_height); - let latest_height = client_state.latest_height(); - - ibc_ctx - .store_update_time( - client_id.clone(), - latest_height, - ibc_ctx.host_timestamp().unwrap(), - ) - .unwrap(); + let consensus_state = dummy_tm_consensus_state(); - ibc_ctx - .store_update_height( - client_id.clone(), - latest_height, - ibc_ctx.host_height().unwrap(), - ) + client_state + .initialise(&mut ibc_ctx, &client_id, consensus_state.into()) .unwrap(); ibc_ctx.increase_client_counter().unwrap(); - ibc_ctx - .store_client_state(client_state_path, client_state) - .unwrap(); - - let current_height = ibc_ctx.host_height().unwrap(); - - let consensus_state_path = ClientConsensusStatePath::new( - client_id.clone(), - current_height.revision_number(), - current_height.revision_height(), - ); - - let consensus_state = AnyConsensusState::Tendermint( - TmConsensusState::new( - Vec::new().into(), - Time::now(), - // Hash for default validator set of CosmosBuilder - Hash::Sha256([ - 0xd6, 0xb9, 0x39, 0x22, 0xc3, 0x3a, 0xae, 0xbe, 0xc9, 0x4, 0x35, 0x66, 0xcb, - 0x4b, 0x1b, 0x48, 0x36, 0x5b, 0x13, 0x58, 0xb6, 0x7c, 0x7d, 0xef, 0x98, 0x6d, - 0x9e, 0xe1, 0x86, 0x1b, 0xc1, 0x43, - ]), - ) - .into(), - ); - - ibc_ctx - .store_consensus_state(consensus_state_path, consensus_state) - .unwrap(); - self.commit(working_set.checkpoint()).await; client_id diff --git a/mocks/src/sovereign/mod.rs b/mocks/src/sovereign/mod.rs index 0d73c646..ecf78547 100644 --- a/mocks/src/sovereign/mod.rs +++ b/mocks/src/sovereign/mod.rs @@ -1,9 +1,19 @@ +mod configs; +#[cfg(feature = "native")] mod da_service; +#[cfg(feature = "native")] mod manual; +#[cfg(feature = "native")] mod rollup; +#[cfg(feature = "native")] mod runner; +#[cfg(feature = "native")] mod runtime; +pub use configs::*; +#[cfg(feature = "native")] pub use da_service::*; +#[cfg(feature = "native")] pub use rollup::*; +#[cfg(feature = "native")] pub use runtime::*; diff --git a/mocks/src/sovereign/rollup.rs b/mocks/src/sovereign/rollup.rs index 0508fd7d..a5cac255 100644 --- a/mocks/src/sovereign/rollup.rs +++ b/mocks/src/sovereign/rollup.rs @@ -4,11 +4,11 @@ use std::cell::RefCell; use std::rc::Rc; use std::sync::{Arc, Mutex}; -use ibc_client_tendermint::types::ConsensusState as TmConsensusState; use ibc_core::client::types::Height; use ibc_core::commitment_types::commitment::CommitmentRoot; use ibc_core::host::types::identifiers::ChainId; use sov_bank::CallMessage as BankCallMessage; +use sov_celestia_client::types::consensus_state::ConsensusState; use sov_ibc::call::CallMessage as IbcCallMessage; use sov_ibc::clients::AnyConsensusState; use sov_ibc::context::IbcContext; @@ -17,6 +17,7 @@ use sov_rollup_interface::services::da::DaService; use sov_state::{MerkleProofSpec, ProverStorage, Storage}; use tendermint::{Hash, Time}; +use crate::cosmos::MockTendermint; use crate::sovereign::runtime::RuntimeCall; use crate::sovereign::Runtime; use crate::utils::MutexUtil; @@ -30,10 +31,10 @@ where Da: DaService + Clone, S: MerkleProofSpec, { - chain_id: ChainId, runtime: Runtime, da_service: Da, prover_storage: ProverStorage, + pub(crate) da_core: MockTendermint, pub(crate) rollup_ctx: Arc>, pub(crate) state_root: Arc as Storage>::Root>>, pub(crate) mempool: Arc>>, @@ -70,14 +71,14 @@ where ::Hasher: Send, { pub fn new( - chain_id: ChainId, runtime: Runtime, prover_storage: ProverStorage, rollup_ctx: C, + da_core: MockTendermint, da_service: Da, ) -> Self { Self { - chain_id, + da_core, runtime, da_service, prover_storage, @@ -88,7 +89,7 @@ where } pub fn chain_id(&self) -> &ChainId { - &self.chain_id + self.da_core.chain_id() } pub fn rollup_ctx(&self) -> C { @@ -175,18 +176,18 @@ where let current_height = self.runtime().chain_state.get_slot_height(&mut working_set); - let consensus_state = AnyConsensusState::Tendermint( - TmConsensusState::new( - CommitmentRoot::from_bytes(&root_hash.0), - Time::now(), - Hash::Sha256([ - 0xd6, 0xb9, 0x39, 0x22, 0xc3, 0x3a, 0xae, 0xbe, 0xc9, 0x4, 0x35, 0x66, 0xcb, - 0x4b, 0x1b, 0x48, 0x36, 0x5b, 0x13, 0x58, 0xb6, 0x7c, 0x7d, 0xef, 0x98, 0x6d, - 0x9e, 0xe1, 0x86, 0x1b, 0xc1, 0x43, - ]), - ) - .into(), - ); + let sov_consensus_state = ConsensusState::new( + CommitmentRoot::from_bytes(&root_hash.0), + Time::now(), + Hash::Sha256([ + 0xd6, 0xb9, 0x39, 0x22, 0xc3, 0x3a, 0xae, 0xbe, 0xc9, 0x4, 0x35, 0x66, 0xcb, 0x4b, + 0x1b, 0x48, 0x36, 0x5b, 0x13, 0x58, 0xb6, 0x7c, 0x7d, 0xef, 0x98, 0x6d, 0x9e, 0xe1, + 0x86, 0x1b, 0xc1, 0x43, + ]), + ) + .into(); + + let consensus_state = AnyConsensusState::Sovereign(sov_consensus_state); self.ibc_ctx(&mut working_set) .store_host_consensus_state(Height::new(0, current_height).unwrap(), consensus_state) diff --git a/mocks/src/sovereign/runner.rs b/mocks/src/sovereign/runner.rs index 35d5f7b6..3f65cb8f 100644 --- a/mocks/src/sovereign/runner.rs +++ b/mocks/src/sovereign/runner.rs @@ -47,6 +47,8 @@ where debug!("rollup: processing block at height {current_height}"); let height = loop { + self.da_core + .grow_blocks(self.state_root.lock().unwrap().as_ref().to_vec()); // Dummy transaction to trigger the block generation self.da_service().send_transaction(&[0; 32]).await.unwrap(); sleep(Duration::from_millis(100)).await; @@ -106,8 +108,6 @@ where /// Commits a block by triggering the end slot hook, computing the state /// update and committing it to the prover storage pub async fn commit(&mut self, checkpoint: StateCheckpoint) -> StateCheckpoint { - let checkpoint = self.begin_block(checkpoint).await; - let checkpoint = self.execute_msg(checkpoint).await; let mut working_set = checkpoint.to_revertable(); @@ -157,9 +157,11 @@ where loop { let working_set = WorkingSet::new(chain.prover_storage()); + let checkpoint = chain.begin_block(working_set.checkpoint()).await; + tokio::time::sleep(Duration::from_millis(200)).await; - chain.commit(working_set.checkpoint()).await; + chain.commit(checkpoint).await; } }); diff --git a/mocks/src/tests/client.rs b/mocks/src/tests/client.rs index 902fc35e..61265d6d 100644 --- a/mocks/src/tests/client.rs +++ b/mocks/src/tests/client.rs @@ -1,3 +1,4 @@ +use basecoin_app::modules::ibc::AnyClientState; use borsh::BorshDeserialize; use ibc_client_tendermint::types::proto::v1::{ ClientState as RawClientState, ConsensusState as RawConsensusState, @@ -8,7 +9,6 @@ use ibc_core::host::types::path::{ClientConsensusStatePath, ClientStatePath, Pat use ibc_core::primitives::proto::Protobuf; use jmt::proof::SparseMerkleProof; use sha2::Sha256; -use sov_ibc::clients::AnyClientState; use test_log::test; use crate::relayer::{Handle, QueryReq, QueryResp, RelayerBuilder}; @@ -30,7 +30,7 @@ async fn test_create_client_on_sov() { let any_client_state = match rly .src_chain_ctx() - .query(QueryReq::ClientState(rly.src_client_id().clone())) + .query(QueryReq::ClientState(rly.dst_client_id().clone())) .await { QueryResp::ClientState(state) => state, @@ -44,7 +44,7 @@ async fn test_create_client_on_sov() { match rly .src_chain_ctx() .query(QueryReq::ValueWithProof( - Path::ClientState(ClientStatePath(rly.src_client_id().clone())), + Path::ClientState(ClientStatePath(rly.dst_client_id().clone())), client_state.latest_height(), )) .await @@ -60,7 +60,7 @@ async fn test_create_client_on_sov() { .src_chain_ctx() .query(QueryReq::ValueWithProof( Path::ClientConsensusState(ClientConsensusStatePath { - client_id: rly.src_client_id().clone(), + client_id: rly.dst_client_id().clone(), revision_number: client_state.latest_height().revision_number(), revision_height: client_state.latest_height().revision_height(), }), @@ -100,7 +100,7 @@ async fn test_update_client_on_sov() { let any_client_state = match rly .src_chain_ctx() - .query(QueryReq::ClientState(rly.src_client_id().clone())) + .query(QueryReq::ClientState(rly.dst_client_id().clone())) .await { QueryResp::ClientState(state) => state, @@ -129,7 +129,7 @@ async fn test_create_client_on_cos() { let client_state = match rly .dst_chain_ctx() - .query(QueryReq::ClientState(rly.dst_client_id().clone())) + .query(QueryReq::ClientState(rly.src_client_id().clone())) .await { QueryResp::ClientState(state) => state, @@ -141,7 +141,7 @@ async fn test_create_client_on_cos() { let _consensus_state = match rly .dst_chain_ctx() .query(QueryReq::ConsensusState( - rly.dst_client_id().clone(), + rly.src_client_id().clone(), client_state.latest_height(), )) .await @@ -150,3 +150,43 @@ async fn test_create_client_on_cos() { _ => panic!("unexpected response"), }; } + +#[test(tokio::test)] +async fn test_update_client_on_cos() { + let rly = RelayerBuilder::default().setup().await; + + let msg_create_client = rly.build_msg_create_client_for_cos().await; + + rly.dst_chain_ctx() + .submit_msgs(vec![msg_create_client]) + .await; + + let target_height = match rly.src_chain_ctx().query(QueryReq::HostHeight).await { + QueryResp::HostHeight(height) => height, + _ => panic!("unexpected response"), + }; + + let msg_update_client = rly + .build_msg_update_client_for_cos(target_height.decrement().unwrap()) + .await; + + rly.dst_chain_ctx() + .submit_msgs(vec![msg_update_client]) + .await; + + let any_client_state = match rly + .dst_chain_ctx() + .query(QueryReq::ClientState(rly.src_client_id().clone())) + .await + { + QueryResp::ClientState(state) => state, + _ => panic!("unexpected response"), + }; + + let client_state = AnyClientState::try_from(any_client_state).unwrap(); + + assert_eq!( + client_state.latest_height(), + target_height.decrement().unwrap() + ); +} diff --git a/mocks/src/tests/transfer.rs b/mocks/src/tests/transfer.rs index c9ca9e72..6c090425 100644 --- a/mocks/src/tests/transfer.rs +++ b/mocks/src/tests/transfer.rs @@ -198,7 +198,7 @@ async fn test_mint_burn_on_sov() { // ----------------------------------------------------------------------- let any_client_state = match rly .src_chain_ctx() - .query(QueryReq::ClientState(rly.src_client_id().clone())) + .query(QueryReq::ClientState(rly.dst_client_id().clone())) .await { QueryResp::ClientState(client_state) => client_state, @@ -285,17 +285,20 @@ async fn test_mint_burn_on_sov() { // TODO: Uncomment this part when the rollup header can be queried by the relayer // - // let target_height = match rly.src_chain_ctx().query(QueryReq::HostHeight) { + // let target_height = match rly.src_chain_ctx().query(QueryReq::HostHeight).await { // QueryResp::HostHeight(height) => height, // _ => panic!("unexpected response"), // }; - // let msg_update_client = rly.build_msg_update_client_for_cos(target_height); + // let msg_update_client = rly.build_msg_update_client_for_cos(target_height).await; - // let msg_recv_packet = rly.build_msg_recv_packet_for_cos(target_height, msg_transfer_on_sov); + // let msg_recv_packet = rly + // .build_msg_recv_packet_for_cos(target_height, msg_transfer_on_sov) + // .await; // rly.dst_chain_ctx() - // .send_msg(vec![msg_update_client.to_any(), msg_recv_packet.to_any()]); + // .submit_msgs(vec![msg_update_client, msg_recv_packet.to_any()]) + // .await; // ----------------------------------------------------------------------- // Check the token has been burned on rollup and unescrowed on Cosmos chain diff --git a/modules/sov-ibc/Cargo.toml b/modules/sov-ibc/Cargo.toml index d0c4c5e0..2f79cfab 100644 --- a/modules/sov-ibc/Cargo.toml +++ b/modules/sov-ibc/Cargo.toml @@ -28,7 +28,8 @@ sov-ibc-transfer = { path = "../sov-ibc-transfer" } ibc-core = { workspace = true } ibc-app-transfer = { workspace = true } ibc-client-tendermint = { workspace = true } -ibc-query = { workspace = true } +ibc-query = { workspace = true, optional = true } +sov-celestia-client = { path = "../../clients/sov-celestia" } # `tendermint` required to convert IbcEvent to a domain event type without custom conversion. tendermint = { workspace = true } @@ -51,4 +52,5 @@ native = [ "sov-state/native", "schemars", "jsonrpsee", + "ibc-query", ] diff --git a/modules/sov-ibc/src/clients/context.rs b/modules/sov-ibc/src/clients/context.rs index eb9b9359..f4be0ae5 100644 --- a/modules/sov-ibc/src/clients/context.rs +++ b/modules/sov-ibc/src/clients/context.rs @@ -1,204 +1,23 @@ use ibc_client_tendermint::context::{ CommonContext as TmCommonContext, ValidationContext as TmValidationContext, }; -use ibc_core::client::context::client_state::{ - ClientStateCommon, ClientStateExecution, ClientStateValidation, -}; +use ibc_core::client::context::client_state::ClientStateCommon; use ibc_core::client::context::{ClientExecutionContext, ClientValidationContext}; use ibc_core::client::types::error::ClientError; -use ibc_core::client::types::{Height, Status, UpdateKind}; -use ibc_core::commitment_types::commitment::{ - CommitmentPrefix, CommitmentProofBytes, CommitmentRoot, -}; +use ibc_core::client::types::Height; use ibc_core::handler::types::error::ContextError; -use ibc_core::host::types::identifiers::{ClientId, ClientType}; -use ibc_core::host::types::path::{ClientConsensusStatePath, ClientStatePath, Path}; +use ibc_core::host::types::identifiers::ClientId; +use ibc_core::host::types::path::{ClientConsensusStatePath, ClientStatePath}; use ibc_core::host::ValidationContext; -use ibc_core::primitives::proto::Any; use ibc_core::primitives::Timestamp; +use sov_celestia_client::context::{ + CommonContext as SovCommonContext, ValidationContext as SovValidationContext, +}; use sov_modules_api::{Context, DaSpec, StateMapAccessor, StateVecAccessor}; -use super::{AnyClientState, AnyConsensusState}; +use super::AnyConsensusState; use crate::context::IbcContext; -// Next 3 trait impls are boilerplate -// We have a `ClientState` macro, but unfortunately it doesn't currently support -// the context (`IbcExecutionContext` in this case) to be generic -impl ClientStateCommon for AnyClientState { - fn verify_consensus_state(&self, consensus_state: Any) -> Result<(), ClientError> { - match self { - AnyClientState::Tendermint(cs) => cs.verify_consensus_state(consensus_state), - } - } - - fn client_type(&self) -> ClientType { - match self { - AnyClientState::Tendermint(cs) => cs.client_type(), - } - } - - fn latest_height(&self) -> Height { - match self { - AnyClientState::Tendermint(cs) => cs.latest_height(), - } - } - - fn validate_proof_height(&self, proof_height: Height) -> Result<(), ClientError> { - match self { - AnyClientState::Tendermint(cs) => cs.validate_proof_height(proof_height), - } - } - - fn verify_upgrade_client( - &self, - upgraded_client_state: Any, - upgraded_consensus_state: Any, - proof_upgrade_client: CommitmentProofBytes, - proof_upgrade_consensus_state: CommitmentProofBytes, - root: &CommitmentRoot, - ) -> Result<(), ClientError> { - match self { - AnyClientState::Tendermint(cs) => cs.verify_upgrade_client( - upgraded_client_state, - upgraded_consensus_state, - proof_upgrade_client, - proof_upgrade_consensus_state, - root, - ), - } - } - - fn verify_membership( - &self, - prefix: &CommitmentPrefix, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - path: Path, - value: Vec, - ) -> Result<(), ClientError> { - match self { - AnyClientState::Tendermint(cs) => { - cs.verify_membership(prefix, proof, root, path, value) - } - } - } - - fn verify_non_membership( - &self, - prefix: &CommitmentPrefix, - proof: &CommitmentProofBytes, - root: &CommitmentRoot, - path: Path, - ) -> Result<(), ClientError> { - match self { - AnyClientState::Tendermint(cs) => cs.verify_non_membership(prefix, proof, root, path), - } - } -} - -impl<'a, C, Da> ClientStateExecution> for AnyClientState -where - C: Context, - Da: DaSpec, -{ - fn initialise( - &self, - ctx: &mut IbcContext<'a, C, Da>, - client_id: &ClientId, - consensus_state: Any, - ) -> Result<(), ClientError> { - match self { - AnyClientState::Tendermint(cs) => cs.initialise(ctx, client_id, consensus_state), - } - } - - fn update_state( - &self, - ctx: &mut IbcContext<'a, C, Da>, - client_id: &ClientId, - header: Any, - ) -> Result, ClientError> { - match self { - AnyClientState::Tendermint(cs) => cs.update_state(ctx, client_id, header), - } - } - - fn update_state_on_misbehaviour( - &self, - ctx: &mut IbcContext<'a, C, Da>, - client_id: &ClientId, - client_message: Any, - update_kind: &UpdateKind, - ) -> Result<(), ClientError> { - match self { - AnyClientState::Tendermint(cs) => { - cs.update_state_on_misbehaviour(ctx, client_id, client_message, update_kind) - } - } - } - - fn update_state_on_upgrade( - &self, - ctx: &mut IbcContext<'a, C, Da>, - client_id: &ClientId, - upgraded_client_state: Any, - upgraded_consensus_state: Any, - ) -> Result { - match self { - AnyClientState::Tendermint(cs) => cs.update_state_on_upgrade( - ctx, - client_id, - upgraded_client_state, - upgraded_consensus_state, - ), - } - } -} - -impl<'a, C, Da> ClientStateValidation> for AnyClientState -where - C: Context, - Da: DaSpec, -{ - fn verify_client_message( - &self, - ctx: &IbcContext<'a, C, Da>, - client_id: &ClientId, - client_message: Any, - update_kind: &UpdateKind, - ) -> Result<(), ClientError> { - match self { - AnyClientState::Tendermint(cs) => { - cs.verify_client_message(ctx, client_id, client_message, update_kind) - } - } - } - - fn check_for_misbehaviour( - &self, - ctx: &IbcContext<'a, C, Da>, - client_id: &ClientId, - client_message: Any, - update_kind: &UpdateKind, - ) -> Result { - match self { - AnyClientState::Tendermint(cs) => { - cs.check_for_misbehaviour(ctx, client_id, client_message, update_kind) - } - } - } - - fn status( - &self, - ctx: &IbcContext<'a, C, Da>, - client_id: &ClientId, - ) -> Result { - match self { - AnyClientState::Tendermint(cs) => cs.status(ctx, client_id), - } - } -} - impl<'a, C: Context, Da: DaSpec> ClientValidationContext for IbcContext<'a, C, Da> { fn client_update_time( &self, @@ -373,58 +192,54 @@ impl<'a, C: Context, Da: DaSpec> TmValidationContext for IbcContext<'a, C, Da> { client_id: &ClientId, height: &Height, ) -> Result, ContextError> { - // Searches for the most recent height at which a client has been - // updated and a consensus state has been stored. - let latest_height = self - .ibc - .client_state_map - .get(client_id, *self.working_set.borrow_mut()) - .map(|cs| cs.latest_height()) - .ok_or(ClientError::ClientStateNotFound { - client_id: client_id.clone(), - })?; - - if height.revision_number() != latest_height.revision_number() { - return Err(ClientError::Other { - description: "height revision number must match the chain's revision number" - .to_string(), - })?; - } - - // If the height is greater equal than the latest height, there is no - // next consensus state - if height >= &latest_height { - return Ok(None); - } + next_consensus_state(self, client_id, height) + } - // Otherwise, we iterate over the heights between the given height and - // the latest height, and return the first consensus state we find - // - // NOTE: this is not the efficient way to do this, but no other way at - // the moment as we don't have access to an iterator over the map keys + fn prev_consensus_state( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result, ContextError> { + prev_consensus_state(self, client_id, height) + } +} - let mut target_height = *height; +impl<'a, C: Context, Da: DaSpec> SovCommonContext for IbcContext<'a, C, Da> { + type ConversionError = &'static str; + type AnyConsensusState = AnyConsensusState; - while height.revision_height() < latest_height.revision_height() { - target_height = target_height.increment(); + fn host_timestamp(&self) -> Result { + ::host_timestamp(self) + } - let cons_state_path = ClientConsensusStatePath::new( - client_id.clone(), - target_height.revision_number(), - target_height.revision_height(), - ); + fn host_height(&self) -> Result { + ::host_height(self) + } - let next_cons_state = self - .ibc - .consensus_state_map - .get(&cons_state_path, *self.working_set.borrow_mut()); + fn consensus_state( + &self, + client_cons_state_path: &ClientConsensusStatePath, + ) -> Result { + ::consensus_state(self, client_cons_state_path) + } - if next_cons_state.is_some() { - return Ok(next_cons_state); - } - } + fn consensus_state_heights(&self, _client_id: &ClientId) -> Result, ContextError> { + let heights = self + .ibc + .client_update_heights_vec + .iter(*self.working_set.borrow_mut()) + .collect::>(); + Ok(heights) + } +} - Ok(None) +impl<'a, C: Context, Da: DaSpec> SovValidationContext for IbcContext<'a, C, Da> { + fn next_consensus_state( + &self, + client_id: &ClientId, + height: &Height, + ) -> Result, ContextError> { + next_consensus_state(self, client_id, height) } fn prev_consensus_state( @@ -432,67 +247,134 @@ impl<'a, C: Context, Da: DaSpec> TmValidationContext for IbcContext<'a, C, Da> { client_id: &ClientId, height: &Height, ) -> Result, ContextError> { - // Searches for the most recent height at which a client has been - // updated and a consensus state has been stored. - let latest_height = self + prev_consensus_state(self, client_id, height) + } +} + +fn next_consensus_state( + ctx: &IbcContext<'_, C, D>, + client_id: &ClientId, + height: &Height, +) -> Result, ContextError> { + // Searches for the most recent height at which a client has been + // updated and a consensus state has been stored. + let latest_height = ctx + .ibc + .client_state_map + .get(client_id, *ctx.working_set.borrow_mut()) + .map(|cs| cs.latest_height()) + .ok_or(ClientError::ClientStateNotFound { + client_id: client_id.clone(), + })?; + + if height.revision_number() != latest_height.revision_number() { + Err(ClientError::Other { + description: "height revision number must match the chain's revision number" + .to_string(), + })?; + } + + // If the height is greater equal than the latest height, there is no + // next consensus state + if height >= &latest_height { + return Ok(None); + } + + // Otherwise, we iterate over the heights between the given height and + // the latest height, and return the first consensus state we find + // + // NOTE: this is not the efficient way to do this, but no other way at + // the moment as we don't have access to an iterator over the map keys + + let mut target_height = *height; + + while height.revision_height() < latest_height.revision_height() { + target_height = target_height.increment(); + + let cons_state_path = ClientConsensusStatePath::new( + client_id.clone(), + target_height.revision_number(), + target_height.revision_height(), + ); + + let next_cons_state = ctx .ibc - .client_state_map - .get(client_id, *self.working_set.borrow_mut()) - .map(|cs| cs.latest_height()) - .ok_or(ClientError::ClientStateNotFound { - client_id: client_id.clone(), - })?; - - if height.revision_number() != latest_height.revision_number() { - return Err(ClientError::Other { - description: "height revision number must match the chain's revision number" - .to_string(), - })?; + .consensus_state_map + .get(&cons_state_path, *ctx.working_set.borrow_mut()); + + if next_cons_state.is_some() { + return Ok(next_cons_state); } + } - // If the height is greater equal than the latest height, the previous - // consensus state is the latest consensus state - if height >= &latest_height { - let cons_state_path = ClientConsensusStatePath::new( - client_id.clone(), - latest_height.revision_number(), - latest_height.revision_height(), - ); + Ok(None) +} - let prev_cons_state = self - .ibc - .consensus_state_map - .get(&cons_state_path, *self.working_set.borrow_mut()); +fn prev_consensus_state( + ctx: &IbcContext<'_, C, D>, + client_id: &ClientId, + height: &Height, +) -> Result, ContextError> { + // Searches for the most recent height at which a client has been + // updated and a consensus state has been stored. + let latest_height = ctx + .ibc + .client_state_map + .get(client_id, *ctx.working_set.borrow_mut()) + .map(|cs| cs.latest_height()) + .ok_or(ClientError::ClientStateNotFound { + client_id: client_id.clone(), + })?; + + if height.revision_number() != latest_height.revision_number() { + Err(ClientError::Other { + description: "height revision number must match the chain's revision number" + .to_string(), + })?; + } - return Ok(prev_cons_state); - } + // If the height is greater equal than the latest height, the previous + // consensus state is the latest consensus state + if height >= &latest_height { + let cons_state_path = ClientConsensusStatePath::new( + client_id.clone(), + latest_height.revision_number(), + latest_height.revision_height(), + ); - // Otherwise, we decrement the height until we reach the first consensus - // state we find - // - // NOTE: this is not the efficient way to do this, but no other way at - // the moment as we don't have access to an iterator over the map keys - let mut target_height = *height; - - while target_height.revision_height() > 0 { - let cons_state_path = ClientConsensusStatePath::new( - client_id.clone(), - target_height.revision_number(), - target_height.revision_height(), - ); - - let prev_cons_state = self - .ibc - .consensus_state_map - .get(&cons_state_path, *self.working_set.borrow_mut()); - - if prev_cons_state.is_some() { - return Ok(prev_cons_state); - } - - target_height = target_height.decrement()?; + let prev_cons_state = ctx + .ibc + .consensus_state_map + .get(&cons_state_path, *ctx.working_set.borrow_mut()); + + return Ok(prev_cons_state); + } + + // Otherwise, we decrement the height until we reach the first consensus + // state we find + // + // NOTE: this is not the efficient way to do this, but no other way at + // the moment as we don't have access to an iterator over the map keys + let mut target_height = *height; + + while target_height.revision_height() > 0 { + let cons_state_path = ClientConsensusStatePath::new( + client_id.clone(), + target_height.revision_number(), + target_height.revision_height(), + ); + + let prev_cons_state = ctx + .ibc + .consensus_state_map + .get(&cons_state_path, *ctx.working_set.borrow_mut()); + + if prev_cons_state.is_some() { + return Ok(prev_cons_state); } - Ok(None) + target_height = target_height.decrement()?; } + + Ok(None) } diff --git a/modules/sov-ibc/src/clients/mod.rs b/modules/sov-ibc/src/clients/mod.rs index 7c294724..bd3eb2a5 100644 --- a/modules/sov-ibc/src/clients/mod.rs +++ b/modules/sov-ibc/src/clients/mod.rs @@ -3,80 +3,308 @@ pub mod context; use derive_more::{From, TryInto}; use ibc_client_tendermint::client_state::ClientState as TmClientState; use ibc_client_tendermint::consensus_state::ConsensusState as TmConsensusState; -use ibc_core::client::context::consensus_state::ConsensusState; +use ibc_client_tendermint::types::{ + TENDERMINT_CLIENT_STATE_TYPE_URL, TENDERMINT_CONSENSUS_STATE_TYPE_URL, +}; +use ibc_core::client::context::client_state::{ + ClientStateCommon, ClientStateExecution, ClientStateValidation, +}; use ibc_core::client::types::error::ClientError; -use ibc_core::commitment_types::commitment; -use ibc_core::primitives; +use ibc_core::client::types::{Height, Status, UpdateKind}; +use ibc_core::commitment_types::commitment::{ + CommitmentPrefix, CommitmentProofBytes, CommitmentRoot, +}; +use ibc_core::derive::ConsensusState; +use ibc_core::host::types::identifiers::{ClientId, ClientType}; +use ibc_core::host::types::path::Path; use ibc_core::primitives::proto::{Any, Protobuf}; +use sov_celestia_client::client_state::ClientState as SovClientState; +use sov_celestia_client::consensus_state::ConsensusState as SovConsensusState; +use sov_celestia_client::types::client_state::SOV_TENDERMINT_CLIENT_STATE_TYPE_URL; +use sov_celestia_client::types::consensus_state::SOV_TENDERMINT_CONSENSUS_STATE_TYPE_URL; +use sov_modules_api::{Context, DaSpec}; -#[derive(Clone, From, TryInto)] -pub enum AnyConsensusState { - Tendermint(TmConsensusState), +use crate::context::IbcContext; + +#[derive(Clone, Debug, From, TryInto)] +pub enum AnyClientState { + Tendermint(TmClientState), + Sovereign(SovClientState), } -impl TryFrom for AnyConsensusState { +impl Protobuf for AnyClientState {} + +impl TryFrom for AnyClientState { type Error = ClientError; fn try_from(value: Any) -> Result { - let tm_cs: TmConsensusState = value.try_into()?; - - Ok(Self::Tendermint(tm_cs)) + match value.type_url.as_str() { + TENDERMINT_CLIENT_STATE_TYPE_URL => { + let tm_cs: TmClientState = value.try_into()?; + Ok(Self::Tendermint(tm_cs)) + } + SOV_TENDERMINT_CLIENT_STATE_TYPE_URL => { + let sov_cs: SovClientState = value.try_into()?; + Ok(Self::Sovereign(sov_cs)) + } + _ => Err(ClientError::UnknownClientStateType { + client_state_type: value.type_url, + }), + } } } -impl From for Any { - fn from(any_cs: AnyConsensusState) -> Self { +impl From for Any { + fn from(any_cs: AnyClientState) -> Self { match any_cs { - AnyConsensusState::Tendermint(tm_cs) => tm_cs.into(), + AnyClientState::Tendermint(tm_cs) => tm_cs.into(), + AnyClientState::Sovereign(sov_cs) => sov_cs.into(), } } } -impl Protobuf for AnyConsensusState {} +// Next 3 trait impls are boilerplate +// We have a `ClientState` macro, but unfortunately it doesn't currently support +// the context (`IbcExecutionContext` in this case) to be generic +impl ClientStateCommon for AnyClientState { + fn verify_consensus_state(&self, consensus_state: Any) -> Result<(), ClientError> { + match self { + AnyClientState::Tendermint(cs) => cs.verify_consensus_state(consensus_state), + AnyClientState::Sovereign(cs) => cs.verify_consensus_state(consensus_state), + } + } -#[derive(Clone, From, TryInto)] -pub enum AnyClientState { - Tendermint(TmClientState), -} + fn client_type(&self) -> ClientType { + match self { + AnyClientState::Tendermint(cs) => cs.client_type(), + AnyClientState::Sovereign(cs) => cs.client_type(), + } + } -impl TryFrom for AnyClientState { - type Error = ClientError; + fn latest_height(&self) -> Height { + match self { + AnyClientState::Tendermint(cs) => cs.latest_height(), + AnyClientState::Sovereign(cs) => cs.latest_height(), + } + } - fn try_from(value: Any) -> Result { - let tm_cs: TmClientState = value.try_into()?; + fn validate_proof_height(&self, proof_height: Height) -> Result<(), ClientError> { + match self { + AnyClientState::Tendermint(cs) => cs.validate_proof_height(proof_height), + AnyClientState::Sovereign(cs) => cs.validate_proof_height(proof_height), + } + } - Ok(Self::Tendermint(tm_cs)) + fn verify_upgrade_client( + &self, + upgraded_client_state: Any, + upgraded_consensus_state: Any, + proof_upgrade_client: CommitmentProofBytes, + proof_upgrade_consensus_state: CommitmentProofBytes, + root: &CommitmentRoot, + ) -> Result<(), ClientError> { + match self { + AnyClientState::Tendermint(cs) => cs.verify_upgrade_client( + upgraded_client_state, + upgraded_consensus_state, + proof_upgrade_client, + proof_upgrade_consensus_state, + root, + ), + AnyClientState::Sovereign(cs) => cs.verify_upgrade_client( + upgraded_client_state, + upgraded_consensus_state, + proof_upgrade_client, + proof_upgrade_consensus_state, + root, + ), + } } -} -impl From for Any { - fn from(any_cs: AnyClientState) -> Self { - match any_cs { - AnyClientState::Tendermint(tm_cs) => tm_cs.into(), + fn verify_membership( + &self, + prefix: &CommitmentPrefix, + proof: &CommitmentProofBytes, + root: &CommitmentRoot, + path: Path, + value: Vec, + ) -> Result<(), ClientError> { + match self { + AnyClientState::Tendermint(cs) => { + cs.verify_membership(prefix, proof, root, path, value) + } + AnyClientState::Sovereign(cs) => cs.verify_membership(prefix, proof, root, path, value), + } + } + + fn verify_non_membership( + &self, + prefix: &CommitmentPrefix, + proof: &CommitmentProofBytes, + root: &CommitmentRoot, + path: Path, + ) -> Result<(), ClientError> { + match self { + AnyClientState::Tendermint(cs) => cs.verify_non_membership(prefix, proof, root, path), + AnyClientState::Sovereign(cs) => cs.verify_non_membership(prefix, proof, root, path), } } } -impl Protobuf for AnyClientState {} +impl<'a, C, Da> ClientStateExecution> for AnyClientState +where + C: Context, + Da: DaSpec, +{ + fn initialise( + &self, + ctx: &mut IbcContext<'a, C, Da>, + client_id: &ClientId, + consensus_state: Any, + ) -> Result<(), ClientError> { + match self { + AnyClientState::Tendermint(cs) => cs.initialise(ctx, client_id, consensus_state), + AnyClientState::Sovereign(cs) => cs.initialise(ctx, client_id, consensus_state), + } + } + + fn update_state( + &self, + ctx: &mut IbcContext<'a, C, Da>, + client_id: &ClientId, + header: Any, + ) -> Result, ClientError> { + match self { + AnyClientState::Tendermint(cs) => cs.update_state(ctx, client_id, header), + AnyClientState::Sovereign(cs) => cs.update_state(ctx, client_id, header), + } + } + + fn update_state_on_misbehaviour( + &self, + ctx: &mut IbcContext<'a, C, Da>, + client_id: &ClientId, + client_message: Any, + update_kind: &UpdateKind, + ) -> Result<(), ClientError> { + match self { + AnyClientState::Tendermint(cs) => { + cs.update_state_on_misbehaviour(ctx, client_id, client_message, update_kind) + } + AnyClientState::Sovereign(cs) => { + cs.update_state_on_misbehaviour(ctx, client_id, client_message, update_kind) + } + } + } + + fn update_state_on_upgrade( + &self, + ctx: &mut IbcContext<'a, C, Da>, + client_id: &ClientId, + upgraded_client_state: Any, + upgraded_consensus_state: Any, + ) -> Result { + match self { + AnyClientState::Tendermint(cs) => cs.update_state_on_upgrade( + ctx, + client_id, + upgraded_client_state, + upgraded_consensus_state, + ), + AnyClientState::Sovereign(cs) => cs.update_state_on_upgrade( + ctx, + client_id, + upgraded_client_state, + upgraded_consensus_state, + ), + } + } +} -impl ConsensusState for AnyConsensusState { - fn root(&self) -> &commitment::CommitmentRoot { +impl<'a, C, Da> ClientStateValidation> for AnyClientState +where + C: Context, + Da: DaSpec, +{ + fn verify_client_message( + &self, + ctx: &IbcContext<'a, C, Da>, + client_id: &ClientId, + client_message: Any, + update_kind: &UpdateKind, + ) -> Result<(), ClientError> { match self { - AnyConsensusState::Tendermint(cs) => cs.root(), + AnyClientState::Tendermint(cs) => { + cs.verify_client_message(ctx, client_id, client_message, update_kind) + } + AnyClientState::Sovereign(cs) => { + cs.verify_client_message(ctx, client_id, client_message, update_kind) + } } } - fn timestamp(&self) -> primitives::Timestamp { + fn check_for_misbehaviour( + &self, + ctx: &IbcContext<'a, C, Da>, + client_id: &ClientId, + client_message: Any, + update_kind: &UpdateKind, + ) -> Result { match self { - AnyConsensusState::Tendermint(cs) => cs.timestamp().into(), + AnyClientState::Tendermint(cs) => { + cs.check_for_misbehaviour(ctx, client_id, client_message, update_kind) + } + AnyClientState::Sovereign(cs) => { + cs.check_for_misbehaviour(ctx, client_id, client_message, update_kind) + } } } - fn encode_vec(self) -> Vec { + fn status( + &self, + ctx: &IbcContext<'a, C, Da>, + client_id: &ClientId, + ) -> Result { match self { - AnyConsensusState::Tendermint(cs) => { - ::encode_vec(cs) + AnyClientState::Tendermint(cs) => cs.status(ctx, client_id), + AnyClientState::Sovereign(cs) => cs.status(ctx, client_id), + } + } +} + +#[derive(Clone, From, TryInto, ConsensusState)] +pub enum AnyConsensusState { + Tendermint(TmConsensusState), + Sovereign(SovConsensusState), +} + +impl Protobuf for AnyConsensusState {} + +impl TryFrom for AnyConsensusState { + type Error = ClientError; + + fn try_from(value: Any) -> Result { + match value.type_url.as_str() { + TENDERMINT_CONSENSUS_STATE_TYPE_URL => { + let tm_cs: TmConsensusState = value.try_into()?; + Ok(Self::Tendermint(tm_cs)) } + SOV_TENDERMINT_CONSENSUS_STATE_TYPE_URL => { + let sov_cs: SovConsensusState = value.try_into()?; + Ok(Self::Sovereign(sov_cs)) + } + _ => Err(ClientError::UnknownConsensusStateType { + consensus_state_type: value.type_url, + }), + } + } +} + +impl From for Any { + fn from(any_cs: AnyConsensusState) -> Self { + match any_cs { + AnyConsensusState::Tendermint(tm_cs) => tm_cs.into(), + AnyConsensusState::Sovereign(sov_cs) => sov_cs.into(), } } } diff --git a/modules/sov-ibc/src/query/methods.rs b/modules/sov-ibc/src/query/methods.rs index ad184637..46b64c3a 100644 --- a/modules/sov-ibc/src/query/methods.rs +++ b/modules/sov-ibc/src/query/methods.rs @@ -32,13 +32,13 @@ use ibc_core::connection::types::proto::v1::{ QueryConnectionResponse, QueryConnectionsRequest, QueryConnectionsResponse, }; use ibc_core::host::types::identifiers::ClientId; -use ibc_core::host::types::path::ClientConsensusStatePath; +use ibc_core::host::types::path::{ClientConsensusStatePath, CommitmentPath}; use ibc_core::host::ValidationContext; use ibc_query::core::channel::{ query_channel, query_channel_client_state, query_channel_consensus_state, query_channels, query_connection_channels, query_next_sequence_receive, query_packet_acknowledgement, - query_packet_acknowledgements, query_packet_commitment, query_packet_commitments, - query_packet_receipt, query_unreceived_acks, query_unreceived_packets, + query_packet_acknowledgements, query_packet_commitments, query_packet_receipt, + query_unreceived_acks, query_unreceived_packets, }; use ibc_query::core::client::{ query_client_states, query_client_status, query_consensus_state_heights, query_consensus_states, @@ -375,12 +375,43 @@ where request: QueryPacketCommitmentRequest, working_set: &mut WorkingSet, ) -> RpcResult { + let prefix = self.packet_commitment_map.prefix(); + + let codec = self.packet_commitment_map.codec(); + + let commitment_path = CommitmentPath::new( + &request.port_id.parse().map_err(to_jsonrpsee_error)?, + &request.channel_id.parse().map_err(to_jsonrpsee_error)?, + request.sequence.into(), + ); + + let key = StorageKey::new(prefix, &commitment_path, codec.key_codec()); + + let value_with_proof = working_set.get_with_proof(key); + + let storage_value = value_with_proof.value.ok_or_else(|| { + to_jsonrpsee_error(format!( + "Packet commitment not found for path {commitment_path:?}" + )) + })?; + + let proof = value_with_proof + .proof + .try_to_vec() + .map_err(to_jsonrpsee_error)?; + let ibc_ctx = IbcContext { ibc: self, working_set: Rc::new(RefCell::new(working_set)), }; - query_packet_commitment(&ibc_ctx, &request).map_err(to_jsonrpsee_error) + let current_height = ibc_ctx.host_height().map_err(to_jsonrpsee_error)?; + + Ok(QueryPacketCommitmentResponse { + commitment: storage_value.value().to_vec(), + proof, + proof_height: Some(current_height.into()), + }) } #[rpc_method(name = "packetCommitments")] diff --git a/proto/buf.lock b/proto/buf.lock new file mode 100644 index 00000000..36dc795a --- /dev/null +++ b/proto/buf.lock @@ -0,0 +1,33 @@ +# Generated by buf. DO NOT EDIT. +version: v1 +deps: + - remote: buf.build + owner: cosmos + repository: cosmos-proto + commit: 1935555c206d4afb9e94615dfd0fad31 + digest: shake256:c74d91a3ac7ae07d579e90eee33abf9b29664047ac8816500cf22c081fec0d72d62c89ce0bebafc1f6fec7aa5315be72606717740ca95007248425102c365377 + - remote: buf.build + owner: cosmos + repository: cosmos-sdk + commit: aa25660f4ff746388669ce36b3778442 + digest: shake256:a20eb29eb7284d9d0b76e94324a6e24e3665d13682bed0d5beac647d7109b7b2f22080301276779a91f394c97dab334da36dfc01d4252d9f869b090bfc8248aa + - remote: buf.build + owner: cosmos + repository: gogo-proto + commit: 5e5b9fdd01804356895f8f79a6f1ddc1 + digest: shake256:0b85da49e2e5f9ebc4806eae058e2f56096ff3b1c59d1fb7c190413dd15f45dd456f0b69ced9059341c80795d2b6c943de15b120a9e0308b499e43e4b5fc2952 + - remote: buf.build + owner: cosmos + repository: ibc + commit: c805262eb05540e7a4d8723e8b39108e + digest: shake256:1c90107847d072bcf9de2f56cefe162b01dea4adc10316e7fb506942ee73a0f87ccd5747b2abb749d6c403b48c814cdfeefe570bd981b81778f27684babddf0b + - remote: buf.build + owner: cosmos + repository: ics23 + commit: 55085f7c710a45f58fa09947208eb70b + digest: shake256:9bf0bc495b5a11c88d163d39ef521bc4b00bc1374a05758c91d82821bdc61f09e8c2c51dda8452529bf80137f34d852561eacbe9550a59015d51cecb0dacb628 + - remote: buf.build + owner: googleapis + repository: googleapis + commit: 8d7204855ec14631a499bd7393ce1970 + digest: shake256:40bf4112960cad01281930beed85829910768e32e80e986791596853eccd42c0cbd9d96690b918f658020d2d427e16f8b6514e2ac7f4a10306fd32e77be44329 diff --git a/proto/buf.yaml b/proto/buf.yaml new file mode 100644 index 00000000..6414d354 --- /dev/null +++ b/proto/buf.yaml @@ -0,0 +1,20 @@ +version: v1 +name: buf.build/informalsystems/sovereign-ibc +deps: + - buf.build/cosmos/ibc:c805262eb05540e7a4d8723e8b39108e + - buf.build/cosmos/gogo-proto +breaking: + use: + - FILE +lint: + use: + - DEFAULT + - COMMENTS + - FILE_LOWER_SNAKE_CASE + except: + - UNARY_RPC + - COMMENT_FIELD + - SERVICE_SUFFIX + - PACKAGE_VERSION_SUFFIX + - RPC_REQUEST_STANDARD_NAME + - RPC_RESPONSE_STANDARD_NAME diff --git a/proto/ibc/lightclients/sovereign/tendermint/v1/sov_tendermint.proto b/proto/ibc/lightclients/sovereign/tendermint/v1/sov_tendermint.proto new file mode 100644 index 00000000..a481397a --- /dev/null +++ b/proto/ibc/lightclients/sovereign/tendermint/v1/sov_tendermint.proto @@ -0,0 +1,133 @@ +syntax = "proto3"; + +package ibc.lightclients.sovereign.tendermint.v1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "ibc/core/client/v1/client.proto"; +import "ibc/core/commitment/v1/commitment.proto"; +import "ibc/lightclients/tendermint/v1/tendermint.proto"; +import "sovereign/types/v1/types.proto"; + +// ClientState defines the client state for the Sovereign SDK rollups operating +// on a Tendermint-based data availability layer. +message ClientState { + option (gogoproto.goproto_getters) = false; + + // the rollup identifier + string rollup_id = 1; + // the latest height the client was updated to + ibc.core.client.v1.Height latest_height = 2 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"latest_height\"" + ]; + // the height when the client was frozen due to a misbehaviour + ibc.core.client.v1.Height frozen_height = 3 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"frozen_height\"" + ]; + // the path at which next upgraded client will be committed. Each element + // corresponds to the key for a single CommitmentProof in the chained proof. + // NOTE: ClientState must stored under + // `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored + // under `{upgradepath}/{upgradeHeight}/consensusState` + repeated string upgrade_path = 4 [(gogoproto.moretags) = "yaml:\"upgrade_path\""]; + // the tendermint params + TendermintParams tendermint_params = 5 [(gogoproto.moretags) = "yaml:\"tendermint_params\""]; +} + +// TendermintParams contains the data necessary to verify Tendermint headers +message TendermintParams { + // the identifier of the chain hosting the Tendermint consensus + string chain_id = 1; + // the trust level of the chain + Fraction trust_level = 2 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"trust_level\"" + ]; + // the duration of the period since the LastestTimestamp during which the + // submitted headers are valid for upgrade + google.protobuf.Duration trusting_period = 3 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.moretags) = "yaml:\"trusting_period\"" + ]; + // the duration of the staking unbonding period + google.protobuf.Duration unbonding_period = 4 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.moretags) = "yaml:\"unbonding_period\"" + ]; + // the duration of new (untrusted) header's Time can drift into the future. + google.protobuf.Duration max_clock_drift = 5 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.moretags) = "yaml:\"max_clock_drift\"" + ]; +} + +// Fraction defines the protobuf message type for tmmath.Fraction that only +// supports positive values. +message Fraction { + // the numerator + uint64 numerator = 1; + // the denominator + uint64 denominator = 2; +} + +// ConsensusState defines the consensus state for the Sovereign SDK rollups +// operating on a Tendermint-based data availability layer. +message ConsensusState { + option (gogoproto.goproto_getters) = false; + + // the timestamp that corresponds to the rollup height in which the + // ConsensusState was stored. + google.protobuf.Timestamp timestamp = 1 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + // the root of rollup state at the ConsensusState height + ibc.core.commitment.v1.MerkleRoot root = 2 [(gogoproto.nullable) = false]; + // the hash of the next validator set + bytes next_validators_hash = 3 [ + (gogoproto.casttype) = "github.com/cometbft/cometbft/libs/bytes.HexBytes", + (gogoproto.moretags) = "yaml:\"next_validators_hash\"" + ]; +} + +// Header defines the structure of the header for the Sovereign SDK light +// clients operating on a Tendermint-based data availability layer. +// It encapsulates all the information necessary to update client from a trusted +// rollup ConsensusState. +// The TrustedHeight is the height of a stored ConsensusState on the client that +// will be used to verify the new untrusted header. The Trusted ConsensusState +// must be within the unbonding period of current time in order to correctly +// verify, and the TrustedValidators must hash to +// TrustedConsensusState.NextValidatorsHash since that is the last trusted +// validator set at the TrustedHeight. +message Header { + // the Tendermint header + ibc.lightclients.tendermint.v1.Header da_header = 1 [(gogoproto.moretags) = "yaml:\"da_header\""]; + // the rollup header + .sovereign.types.v1.AggregatedProofData aggregated_proof_data = 2 [(gogoproto.moretags) = "yaml:\"aggregated_proof_data\""]; +} + +// SovTendermintMisbehaviour defines the misbehaviour for the Sovereign SDK +// rollups with Tendermint-based data availability layer. +message Misbehaviour { + option (gogoproto.goproto_getters) = false; + + // the client identifier + string client_id = 1; + // the header_1 of the Sovereign SDK rollup with Tendermint-based DA layer + Header header_1 = 2 [ + (gogoproto.customname) = "Header1", + (gogoproto.moretags) = "yaml:\"header_1\"" + ]; + // the header_2 of the Sovereign SDK rollup with Tendermint-based DA layer + Header header_2 = 3 [ + (gogoproto.customname) = "Header2", + (gogoproto.moretags) = "yaml:\"header_2\"" + ]; +} diff --git a/proto/sovereign/types/v1/types.proto b/proto/sovereign/types/v1/types.proto new file mode 100644 index 00000000..d69529cb --- /dev/null +++ b/proto/sovereign/types/v1/types.proto @@ -0,0 +1,44 @@ +syntax = "proto3"; + +package sovereign.types.v1; + +// AggregatedProofData is the overarching structure, encompassing public input, +// proof data information, and aggregated proof bytes. +message AggregatedProofData { + // the public input + PublicInput public_input = 1; + // the proof data info + ProofDataInfo proof_data_info = 2; + // the aggregated proof bytes + AggregatedProof aggregated_proof = 3; +} + +// PublicInput defines the public properties of the AggregatedProof for the +// Sovereign SDK rollups, utilized for verifying the proof. +message PublicInput { + // the initial DA block hash + bytes initial_da_block_hash = 1; + // the final DA block hash + bytes final_da_block_hash = 2; + // the initial state root + bytes initial_state_root = 3; + // the final state root + bytes final_state_root = 4; +} + +// ProofDataInfo contains additional information about the proof. +message ProofDataInfo { + // the initial height of the DA block from which the proof covers the updating + // of the initial state root. + uint64 initial_state_height = 1; + // the last height of the DA block, up to which the proof captures the + // rollup's transition to the final state root. + uint64 final_state_height = 2; +} + +// AggregatedProof defines the aggregated proof structure for the Sovereign SDK +// rollups. +message AggregatedProof { + // the rollup aggregated proof bytes covering a range of DA blocks + bytes proof = 1; +}