diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index acab25b5..d1431e50 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -91,3 +91,13 @@ jobs: - uses: actions-rs/cargo@v1 with: command: doc + + cargo-toml-fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + - uses: baptiste0928/cargo-install@v3 + with: + crate: taplo-cli + - run: taplo fmt --check diff --git a/Cargo.lock b/Cargo.lock index d5a81f5f..24212a44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,7 +102,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -113,7 +113,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -194,6 +194,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "base64ct" version = "1.6.0" @@ -207,14 +213,25 @@ dependencies = [ "basecoin-app", "basecoin-modules", "basecoin-store", + "bech32 0.11.0", + "bitcoin", "clap", + "digest 0.10.7", + "generic-array", + "hdpath", + "ibc", "ibc-proto", + "prost", + "secp256k1", "serde", "serde_derive", + "serde_json", + "sha2 0.10.8", "tendermint-abci", "tendermint-rpc", + "tiny-bip39", "tokio", - "toml 0.8.12", + "toml", "tonic", "tonic-reflection", "tower-abci", @@ -232,9 +249,9 @@ dependencies = [ "ibc-proto", "prost", "serde_json", - "tendermint", + "tendermint 0.35.0", "tendermint-abci", - "tendermint-proto", + "tendermint-proto 0.35.0", "tonic", "tower", "tower-abci", @@ -245,7 +262,7 @@ dependencies = [ name = "basecoin-modules" version = "0.1.0" dependencies = [ - "base64", + "base64 0.21.7", "basecoin-store", "cosmrs", "derive_more", @@ -260,7 +277,7 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.10.8", - "tendermint", + "tendermint 0.35.0", "tendermint-rpc", "tonic", "tracing", @@ -276,10 +293,22 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.8", - "tendermint", + "tendermint 0.35.0", "tracing", ] +[[package]] +name = "bech32" +version = "0.10.0-beta" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + [[package]] name = "bip32" version = "0.5.1" @@ -296,6 +325,36 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bitcoin" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c85783c2fe40083ea54a33aa2f0ba58831d90fcd190f5bdc47e74e84d2a96ae" +dependencies = [ + "bech32 0.10.0-beta", + "bitcoin-internals", + "bitcoin_hashes", + "hex-conservative", + "hex_lit", + "secp256k1", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -380,9 +439,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.92" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -422,7 +481,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -473,7 +532,7 @@ checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" dependencies = [ "prost", "prost-types", - "tendermint-proto", + "tendermint-proto 0.34.1", ] [[package]] @@ -492,7 +551,7 @@ dependencies = [ "serde_json", "signature", "subtle-encoding", - "tendermint", + "tendermint 0.34.1", "thiserror", ] @@ -605,7 +664,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -647,9 +706,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "elliptic-curve" @@ -805,7 +864,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -910,6 +969,15 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +[[package]] +name = "hdpath" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa5bc9db2c17d2660f53ce217b778d06d68de13d1cd01c0f4e5de4b7918935f" +dependencies = [ + "byteorder", +] + [[package]] name = "hdrhistogram" version = "7.5.4" @@ -938,6 +1006,18 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + [[package]] name = "hmac" version = "0.12.1" @@ -1034,7 +1114,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "ibc-apps", "ibc-clients", @@ -1047,7 +1127,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -1057,7 +1137,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1071,7 +1151,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "ibc-app-transfer", ] @@ -1079,7 +1159,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -1089,14 +1169,14 @@ dependencies = [ "ibc-core-host", "ibc-primitives", "serde", - "tendermint", + "tendermint 0.35.0", "tendermint-light-client-verifier", ] [[package]] name = "ibc-client-tendermint-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -1105,17 +1185,17 @@ dependencies = [ "ibc-primitives", "ibc-proto", "serde", - "tendermint", + "tendermint 0.35.0", "tendermint-light-client-verifier", - "tendermint-proto", + "tendermint-proto 0.35.0", ] [[package]] name = "ibc-client-wasm-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ - "base64", + "base64 0.21.7", "displaydoc", "ibc-core-client", "ibc-core-host-types", @@ -1127,7 +1207,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -1136,7 +1216,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -1152,7 +1232,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -1167,7 +1247,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1180,13 +1260,13 @@ dependencies = [ "serde", "sha2 0.10.8", "subtle-encoding", - "tendermint", + "tendermint 0.35.0", ] [[package]] name = "ibc-core-client" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -1199,7 +1279,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1209,13 +1289,13 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "subtle-encoding", - "tendermint", + "tendermint 0.35.0", ] [[package]] name = "ibc-core-client-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1225,13 +1305,13 @@ dependencies = [ "ibc-proto", "serde", "subtle-encoding", - "tendermint", + "tendermint 0.35.0", ] [[package]] name = "ibc-core-commitment-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1245,7 +1325,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "ibc-core-client", "ibc-core-connection-types", @@ -1257,7 +1337,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1268,13 +1348,13 @@ dependencies = [ "ibc-proto", "serde", "subtle-encoding", - "tendermint", + "tendermint 0.35.0", ] [[package]] name = "ibc-core-handler" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -1289,7 +1369,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1303,13 +1383,13 @@ dependencies = [ "ibc-proto", "serde", "subtle-encoding", - "tendermint", + "tendermint 0.35.0", ] [[package]] name = "ibc-core-host" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1327,7 +1407,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1344,13 +1424,13 @@ dependencies = [ "serde", "sha2 0.10.8", "subtle-encoding", - "tendermint", + "tendermint 0.35.0", ] [[package]] name = "ibc-core-host-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1361,7 +1441,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1375,7 +1455,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", @@ -1384,40 +1464,40 @@ dependencies = [ "ibc-proto", "serde", "subtle-encoding", - "tendermint", + "tendermint 0.35.0", ] [[package]] name = "ibc-derive" version = "0.6.1" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "ibc-primitives" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "derive_more", "displaydoc", "ibc-proto", "prost", "serde", - "tendermint", + "tendermint 0.35.0", "time", ] [[package]] name = "ibc-proto" -version = "0.42.2" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a6f2bbf7e1d12f98d8d54d9114231b865418d0f8b619c0873180eafdee07fd" +checksum = "af781637b107aa33042426c9d17b181ced05ae97b1d88dba50f40f19ad44e36f" dependencies = [ - "base64", + "base64 0.22.0", "bytes", "flex-error", "ics23", @@ -1425,14 +1505,14 @@ dependencies = [ "prost", "serde", "subtle-encoding", - "tendermint-proto", + "tendermint-proto 0.35.0", "tonic", ] [[package]] name = "ibc-query" version = "0.51.0" -source = "git+https://github.com/cosmos/ibc-rs.git?rev=c659e210d2#c659e210d202490b69719bc5aa4138aaeb8d82be" +source = "git+https://github.com/cosmos/ibc-rs.git?rev=e5c626f#e5c626f2f78c8c6d08b4c4c2755af5dfa16436a2" dependencies = [ "displaydoc", "ibc", @@ -1510,7 +1590,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aa4a0980c8379295100d70854354e78df2ee1c6ca0f96ffe89afeb3140e3a3d" dependencies = [ - "base64", + "base64 0.21.7", "serde", ] @@ -1585,9 +1665,9 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1664,6 +1744,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "num-traits" version = "0.2.18" @@ -1718,9 +1809,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core", @@ -1728,15 +1819,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -1745,6 +1836,15 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "peg" version = "0.8.2" @@ -1795,7 +1895,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1845,9 +1945,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -1872,7 +1972,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1925,11 +2025,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] @@ -1938,7 +2038,7 @@ version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -2013,11 +2113,17 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -2028,9 +2134,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", @@ -2056,7 +2162,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.7", ] [[package]] @@ -2129,6 +2235,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "bitcoin_hashes", + "rand", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + [[package]] name = "security-framework" version = "2.10.0" @@ -2160,9 +2287,9 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] @@ -2187,20 +2314,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -2215,7 +2342,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2284,9 +2411,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2388,9 +2515,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -2450,48 +2577,77 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto", + "tendermint-proto 0.34.1", + "time", + "zeroize", +] + +[[package]] +name = "tendermint" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f8a10105d0a7c4af0a242e23ed5a12519afe5cc0e68419da441bb5981a6802" +dependencies = [ + "bytes", + "digest 0.10.7", + "ed25519", + "ed25519-consensus", + "flex-error", + "futures", + "num-traits", + "once_cell", + "prost", + "prost-types", + "serde", + "serde_bytes", + "serde_json", + "serde_repr", + "sha2 0.10.8", + "signature", + "subtle", + "subtle-encoding", + "tendermint-proto 0.35.0", "time", "zeroize", ] [[package]] name = "tendermint-abci" -version = "0.34.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715c41dec864b693237ff73edc0698bd4f53dd779e13f2180702234f609c144d" +checksum = "6b524fb05f6a8afd6a332fb139f784d19e1343f115b736b0978238489baf7a89" dependencies = [ "bytes", "flex-error", "prost", - "tendermint-proto", + "tendermint-proto 0.35.0", "tracing", ] [[package]] name = "tendermint-config" -version = "0.34.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1a02da769166e2052cd537b1a97c78017632c2d9e19266367b27e73910434fc" +checksum = "ac6bf36c613bb113737c333e3c1d6dfd3c99f8ac679e84feb58dd6456d77fb2e" dependencies = [ "flex-error", "serde", "serde_json", - "tendermint", - "toml 0.5.11", + "tendermint 0.35.0", + "toml", "url", ] [[package]] name = "tendermint-light-client-verifier" -version = "0.34.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b8090d0eef9ad57b1b913b5e358e26145c86017e87338136509b94383a4af25" +checksum = "35678b66e819659617c2e83f9662b8544425694441990c07137904a07872d871" dependencies = [ "derive_more", "flex-error", "serde", - "tendermint", + "tendermint 0.35.0", "time", ] @@ -2503,7 +2659,25 @@ checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" dependencies = [ "bytes", "flex-error", - "num-derive", + "num-derive 0.3.3", + "num-traits", + "prost", + "prost-types", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-proto" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff525d5540a9fc535c38dc0d92a98da3ee36fcdfbda99cecb9f3cce5cd4d41d7" +dependencies = [ + "bytes", + "flex-error", + "num-derive 0.4.2", "num-traits", "prost", "prost-types", @@ -2515,9 +2689,9 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.34.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71afae8bb5f6b14ed48d4e1316a643b6c2c3cbad114f510be77b4ed20b7b3e42" +checksum = "2d8fe61b1772cd50038bdeeadf53773bb37a09e639dd8e6d996668fd220ddb29" dependencies = [ "async-trait", "bytes", @@ -2534,9 +2708,9 @@ dependencies = [ "serde_json", "subtle", "subtle-encoding", - "tendermint", + "tendermint 0.35.0", "tendermint-config", - "tendermint-proto", + "tendermint-proto 0.35.0", "thiserror", "time", "tokio", @@ -2558,22 +2732,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2616,6 +2790,25 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac", + "once_cell", + "pbkdf2", + "rand", + "rustc-hash", + "sha2 0.10.8", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2668,7 +2861,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2720,15 +2913,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml" version = "0.8.12" @@ -2752,9 +2936,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap 2.2.6", "serde", @@ -2765,14 +2949,14 @@ dependencies = [ [[package]] name = "tonic" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" dependencies = [ "async-stream", "async-trait", "axum", - "base64", + "base64 0.21.7", "bytes", "h2", "http", @@ -2792,9 +2976,9 @@ dependencies = [ [[package]] name = "tonic-reflection" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa37c513df1339d197f4ba21d28c918b9ef1ac1768265f11ecb6b7f1cba1b76" +checksum = "548c227bd5c0fae5925812c4ec6c66ffcfced23ea370cb823f4d18f0fc1cb6a7" dependencies = [ "prost", "prost-types", @@ -2826,16 +3010,15 @@ dependencies = [ [[package]] name = "tower-abci" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4826f3df3e9a37083d978cae73f020bcdf6143956b7dfc1bd6050b4e16367c" +version = "0.12.0" +source = "git+https://github.com/informalsystems/tower-abci.git?rev=a4c021b#a4c021bae3e77a22fe2af802ad53f2bd3fd792db" dependencies = [ "bytes", "futures", "pin-project", "prost", - "tendermint", - "tendermint-proto", + "tendermint 0.35.0", + "tendermint-proto 0.35.0", "tokio", "tokio-stream", "tokio-util 0.6.10", @@ -2875,7 +3058,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3045,7 +3228,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -3079,7 +3262,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3118,11 +3301,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -3272,9 +3455,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578" dependencies = [ "memchr", ] @@ -3306,5 +3489,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] diff --git a/Cargo.toml b/Cargo.toml index c02afa5d..2883da4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,12 +2,7 @@ resolver = "2" -members = [ - "basecoin", - "basecoin/app", - "basecoin/modules", - "basecoin/store", -] +members = [ "basecoin", "basecoin/app", "basecoin/modules", "basecoin/store" ] [workspace.package] version = "0.1.0" @@ -16,37 +11,40 @@ edition = "2021" rust-version = "1.64" readme = "README.md" repository = "https://github.com/informalsystems/basecoin-rs" -authors = ["Informal Systems "] +authors = [ "Informal Systems " ] [workspace.dependencies] # external dependencies -base64 = { version = "0.21.6", default-features = false, features = ["alloc"] } +base64 = { version = "0.21.6", default-features = false, features = [ "alloc" ] } cosmrs = { version = "0.15.0" } displaydoc = { version = "0.2", default-features = false } -derive_more = { version = "0.99.17", default-features = false, features = ["from", "into", "display"] } +derive_more = { version = "0.99.17", default-features = false, features = [ "from", "into", "display" ] } ed25519 = { version = "2.1.0", default-features = false } prost = { version = "0.12", default-features = false } serde = "1.0" serde_json = "1.0" sha2 = "0.10.2" -tonic = "0.10" -tonic-reflection = "0.10" +tonic = "0.11" +tonic-reflection = "0.11" tracing = "0.1.26" tracing-subscriber = "0.3.16" # ibc dependencies -ibc = { version = "0.51.0", default-features = false, features = ["serde"] } -ibc-query = { version = "0.51.0", default-features = false } -ibc-proto = { version = "0.42.2", default-features = false } -ics23 = { version = "0.11", default-features = false } +ibc = { version = "0.51.0", default-features = false, features = [ "serde" ] } +ibc-query = { version = "0.51.0", default-features = false } +ibc-proto = { version = "0.43.0", default-features = false } +ics23 = { version = "0.11", default-features = false } # tendermint dependencies -tendermint = { version = "0.34", default-features = false } -tendermint-abci = { version = "0.34", default-features = false } -tendermint-proto = { version = "0.34", default-features = false } -tendermint-rpc = { version = "0.34", default-features = false } +tendermint = { version = "0.35", default-features = false } +tendermint-abci = { version = "0.35", default-features = false } +tendermint-proto = { version = "0.35", default-features = false } +tendermint-rpc = { version = "0.35", default-features = false } -[patch.crates-io] -ibc = { git = "https://github.com/cosmos/ibc-rs.git", rev = "c659e210d2" } -ibc-query = { git = "https://github.com/cosmos/ibc-rs.git", rev = "c659e210d2" } +# tower abci +tower-abci = { version = "0.12" } +[patch.crates-io] +ibc = { git = "https://github.com/cosmos/ibc-rs.git", rev = "e5c626f" } +ibc-query = { git = "https://github.com/cosmos/ibc-rs.git", rev = "e5c626f" } +tower-abci = { git = "https://github.com/informalsystems/tower-abci.git", rev = "a4c021b" } diff --git a/basecoin/Cargo.toml b/basecoin/Cargo.toml index f7d6911e..cc443790 100644 --- a/basecoin/Cargo.toml +++ b/basecoin/Cargo.toml @@ -1,40 +1,52 @@ [package] -name = "basecoin" +name = "basecoin" version = { workspace = true } edition = { workspace = true } license = { workspace = true } readme = { workspace = true } repository = { workspace = true } authors = { workspace = true } -description = """ - Contains the basecoin daemon and CLI that integrates with ibc-rs, making - use of tendermint-rs. -""" +description = "Contains the basecoin daemon and CLI that integrates with ibc-rs, making use of tendermint-rs." [features] -default = ["v0_37"] -v0_37 = ["basecoin-app/v0_37", "dep:tower-abci"] -v0_38 = ["basecoin-app/v0_38", "dep:tendermint-abci"] +default = [ "v0_37" ] +v0_37 = [ "basecoin-app/v0_37", "dep:tower-abci" ] +v0_38 = [ "basecoin-app/v0_38", "dep:tendermint-abci" ] [dependencies] # external dependencies -clap = { version = "4.3.0", features = ["derive", "wrap_help"] } -ibc-proto = { workspace = true, features = ["server", "proto-descriptor", "serde"] } +bech32 = { version = "0.11.0" } +tiny-bip39 = { version = "1" } +digest = { version = "0.10.7" } +bitcoin = { version = "0.31.2" } +hdpath = { version = "0.6.3" } +clap = { version = "4.5.0", features = [ "derive", "wrap_help" ] } +generic-array = { version = "0.14.7" } +prost = { workspace = true } serde = { workspace = true } serde_derive = { version = "1.0.104", default-features = false } -tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +serde_json = { workspace = true } +secp256k1 = { version = "0.28.2", features = [ "serde", "rand-std" ] } +sha2 = { workspace = true } +tokio = { version = "1.0", features = [ "macros", "rt-multi-thread" ] } tonic = { workspace = true } tonic-reflection = { workspace = true } toml = { version = "0.8" } tracing = { workspace = true } tracing-subscriber = { workspace = true } -tower-abci = { version = "0.11", optional = true } + +# ibc dependencies +ibc = { workspace = true } +ibc-proto = { workspace = true, features = [ "server", "proto-descriptor", "serde" ] } # tendermint dependencies -tendermint-abci = { workspace = true, optional = true } -tendermint-rpc = { workspace = true , features = ["http-client"] } +tendermint-abci = { workspace = true, optional = true } +tendermint-rpc = { workspace = true, features = [ "http-client" ] } + +# tower abci +tower-abci = { workspace = true, optional = true } # internal dependencies -basecoin-store = { path = "./store" } -basecoin-modules = { path = "./modules" } -basecoin-app = { path = "./app", default-features = false } +basecoin-store = { path = "./store" } +basecoin-modules = { path = "./modules" } +basecoin-app = { path = "./app", default-features = false } diff --git a/basecoin/app/Cargo.toml b/basecoin/app/Cargo.toml index ee4c5278..fb353108 100644 --- a/basecoin/app/Cargo.toml +++ b/basecoin/app/Cargo.toml @@ -1,41 +1,41 @@ [package] -name = "basecoin-app" +name = "basecoin-app" version = { workspace = true } edition = { workspace = true } license = { workspace = true } readme = { workspace = true } repository = { workspace = true } authors = { workspace = true } -description = """ - Contains a simple implementation of the Tendermint ABCI application. -""" +description = "Contains a simple implementation of the Tendermint ABCI application." [features] -default = ["v0_37"] +default = [ "v0_37" ] # Makes the application compatible with CometBFT v0.37 -v0_37 = ["dep:tower-abci", "dep:tower"] +v0_37 = [ "dep:tower-abci", "dep:tower" ] # Makes the application compatible with CometBFT v0.38 # (WIP) methods are not yet implemented -v0_38 = ["dep:tendermint-abci"] +v0_38 = [ "dep:tendermint-abci" ] [dependencies] # external dependencies -cosmrs = { workspace = true } -ibc-proto = { workspace = true, features = ["server", "proto-descriptor", "serde"] } -prost = { workspace = true } -serde_json = { workspace = true } -tonic = { workspace = true } -tracing = { workspace = true } -tower-abci = { version = "0.11", optional = true } -tower = { version = "0.4", features = ["full"], optional = true } +cosmrs = { workspace = true } +ibc-proto = { workspace = true, features = [ "server", "proto-descriptor", "serde" ] } +prost = { workspace = true } +serde_json = { workspace = true } +tonic = { workspace = true } +tracing = { workspace = true } +tower = { version = "0.4", features = [ "full" ], optional = true } # tedermint dependencies -tendermint = { workspace = true } -tendermint-abci = { workspace = true, optional = true } -tendermint-proto = { workspace = true } +tendermint = { workspace = true } +tendermint-abci = { workspace = true, optional = true } +tendermint-proto = { workspace = true } # internal dependencies -basecoin-store = { path = "../store" } -basecoin-modules = { path = "../modules" } +basecoin-store = { path = "../store" } +basecoin-modules = { path = "../modules" } + +# tower abci +tower-abci = { workspace = true, optional = true } diff --git a/basecoin/modules/Cargo.toml b/basecoin/modules/Cargo.toml index 775a6de8..9682c46a 100644 --- a/basecoin/modules/Cargo.toml +++ b/basecoin/modules/Cargo.toml @@ -1,40 +1,37 @@ [package] -name = "basecoin-modules" +name = "basecoin-modules" version = { workspace = true } edition = { workspace = true } license = { workspace = true } readme = { workspace = true } repository = { workspace = true } authors = { workspace = true } -description = """ - Contains simple implementations of various modules for the Basecoin application. -""" +description = "Contains simple implementations of various modules for the Basecoin application." [dependencies] # external dependencies -base64 = { workspace = true } -cosmrs = { workspace = true } -displaydoc = { workspace = true } -derive_more = { workspace = true } -primitive-types = { version = "0.12.0", default-features = false, features = ["serde_no_std"] } -prost = { workspace = true } -serde = { workspace = true } -serde_derive = { version = "1.0.104", default-features = false } -serde_json = { workspace = true } -sha2 = { workspace = true } -tonic = { workspace = true } -tracing = { workspace = true } +base64 = { workspace = true } +cosmrs = { workspace = true } +displaydoc = { workspace = true } +derive_more = { workspace = true } +primitive-types = { version = "0.12.0", default-features = false, features = [ "serde_no_std" ] } +prost = { workspace = true } +serde = { workspace = true } +serde_derive = { version = "1.0.104", default-features = false } +serde_json = { workspace = true } +sha2 = { workspace = true } +tonic = { workspace = true } +tracing = { workspace = true } # ibc dependencies -ibc = { workspace = true } -ibc-proto = { workspace = true, features = ["server", "proto-descriptor", "serde"] } -ibc-query = { workspace = true } -ics23 = { workspace = true, features = ["host-functions"] } +ibc = { workspace = true } +ibc-proto = { workspace = true, features = [ "client", "server", "proto-descriptor", "serde" ] } +ibc-query = { workspace = true } +ics23 = { workspace = true, features = [ "host-functions" ] } # tendermint dependencies -tendermint = { workspace = true } -tendermint-rpc = { workspace = true , features = ["http-client"] } +tendermint = { workspace = true } +tendermint-rpc = { workspace = true, features = [ "http-client" ] } # internal dependencies -basecoin-store = { path = "../store" } - +basecoin-store = { path = "../store" } diff --git a/basecoin/modules/src/bank/util.rs b/basecoin/modules/src/bank/util.rs index c266a460..238de634 100644 --- a/basecoin/modules/src/bank/util.rs +++ b/basecoin/modules/src/bank/util.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use basecoin_store::types::Path; use cosmrs::{AccountId, Coin as MsgCoin}; use ibc_proto::cosmos::base::v1beta1::Coin as ProtoCoin; @@ -26,6 +28,37 @@ impl Coin { } } +impl FromStr for Coin { + type Err = Error; + + /// Parses a coin string in the format "10basecoin", + /// i.e. amount followed by denom + fn from_str(s: &str) -> Result { + let mut split = s.splitn(2, |c: char| c.is_alphabetic()); + + let amount = split + .next() + .ok_or_else(|| Error::Custom { + reason: "missing amount".to_owned(), + })? + .parse() + .map_err(|e| Error::Custom { + reason: format!("failed to parse amount: {e:?}"), + })?; + + let denom = Denom( + split + .next() + .ok_or_else(|| Error::Custom { + reason: "missing denom".to_owned(), + })? + .to_owned(), + ); + + Ok(Self { denom, amount }) + } +} + impl Protobuf for Coin {} impl TryFrom for Coin { diff --git a/basecoin/modules/src/gov/impls.rs b/basecoin/modules/src/gov/impls.rs index 41faadd8..f46a03b4 100644 --- a/basecoin/modules/src/gov/impls.rs +++ b/basecoin/modules/src/gov/impls.rs @@ -8,7 +8,11 @@ use basecoin_store::impls::SharedStore; use basecoin_store::types::{Height, Path, ProtobufStore, TypedStore}; use basecoin_store::utils::{SharedRw, SharedRwExt}; use cosmrs::AccountId; -use ibc::cosmos_host::upgrade_proposal::{execute_upgrade_client_proposal, UpgradeProposal}; +use ibc::core::client::handler::recover_client; +use ibc::core::client::types::msgs::{MsgRecoverClient, RECOVER_CLIENT_TYPE_URL}; +use ibc::cosmos_host::upgrade_proposal::{ + execute_upgrade_client_proposal, UpgradeProposal, UPGRADE_PROPOSAL_TYPE_URL, +}; use ibc_proto::cosmos::gov::v1beta1::query_server::QueryServer; use ibc_proto::google::protobuf::Any; use ibc_proto::Protobuf; @@ -21,6 +25,7 @@ use super::service::GovernanceService; use crate::context::Module; pub use crate::error::Error as AppError; use crate::gov::msg::MsgSubmitProposal; +use crate::ibc::Ibc; use crate::types::QueryResult; use crate::upgrade::Upgrade; @@ -33,13 +38,14 @@ where pub proposal_counter: u64, pub proposal: ProtobufStore, ProposalPath, Proposal, Any>, pub upgrade_ctx: SharedRw>, + pub ibc_ctx: SharedRw>, } impl Governance where S: Store + Debug, { - pub fn new(store: SharedStore, upgrade_ctx: Upgrade) -> Self + pub fn new(store: SharedStore, upgrade_ctx: Upgrade, ibc_ctx: Ibc) -> Self where S: Store, { @@ -47,6 +53,7 @@ where proposal_counter: 0, proposal: TypedStore::new(store.clone()), upgrade_ctx: Arc::new(RwLock::new(upgrade_ctx)), + ibc_ctx: Arc::new(RwLock::new(ibc_ctx)), store, } } @@ -64,27 +71,48 @@ where fn deliver(&mut self, message: Any, _signer: &AccountId) -> Result, AppError> { if let Ok(message) = MsgSubmitProposal::try_from(message) { - debug!("Delivering proposal message: {:?}", message); + match message.content.type_url.as_str() { + UPGRADE_PROPOSAL_TYPE_URL => { + debug!("Delivering proposal message: {:?}", message); - let upgrade_proposal = - UpgradeProposal::decode_vec(message.content.value.as_slice()).unwrap(); + let upgrade_proposal = + UpgradeProposal::decode_vec(message.content.value.as_slice()).unwrap(); - let mut upgrade_ctx = self.upgrade_ctx.write_access(); + let mut upgrade_ctx = self.upgrade_ctx.write_access(); - let event = execute_upgrade_client_proposal(upgrade_ctx.deref_mut(), upgrade_proposal) - .map_err(|e| AppError::Custom { - reason: format!("Error handling upgrade proposal: {:?}", e), - })?; + let event = + execute_upgrade_client_proposal(upgrade_ctx.deref_mut(), upgrade_proposal) + .map_err(|e| AppError::Custom { + reason: format!("Error handling upgrade proposal: {:?}", e), + })?; - let proposal = message.proposal(self.proposal_counter); + let proposal = message.proposal(self.proposal_counter); - self.proposal - .set(ProposalPath::sdk_path(), proposal) - .unwrap(); + self.proposal + .set(ProposalPath::sdk_path(), proposal) + .unwrap(); - self.proposal_counter += 1; + self.proposal_counter += 1; - Ok(vec![event]) + Ok(vec![event]) + } + RECOVER_CLIENT_TYPE_URL => { + debug!("Delivering client recovery message: {:?}", message); + + let msg_recover_client = + MsgRecoverClient::decode_vec(message.content.value.as_slice()).unwrap(); + + let mut ibc_ctx = self.ibc_ctx.write_access(); + + recover_client::validate(&ibc_ctx.ctx, msg_recover_client.clone())?; + recover_client::execute(&mut ibc_ctx.ctx, msg_recover_client)?; + + // client recovery operation does not return an event + // https://github.com/cosmos/ibc-go/blob/4c1aae32/modules/light-clients/07-tendermint/light_client_module.go#L249 + Ok(vec![]) + } + _ => Err(AppError::NotHandled), + } } else { Err(AppError::NotHandled) } diff --git a/basecoin/modules/src/ibc/client_contexts.rs b/basecoin/modules/src/ibc/client_contexts.rs index 19cf7bbb..9d1d58c9 100644 --- a/basecoin/modules/src/ibc/client_contexts.rs +++ b/basecoin/modules/src/ibc/client_contexts.rs @@ -2,12 +2,9 @@ use std::fmt::Debug; use basecoin_store::context::Store; use basecoin_store::types::Height; -use ibc::clients::tendermint::client_state::ClientState as TmClientState; -use ibc::clients::tendermint::consensus_state::ConsensusState as TmConsensusState; -use ibc::clients::tendermint::context::{ - ConsensusStateConverter, ValidationContext as TmValidationContext, +use ibc::core::client::context::{ + ClientExecutionContext, ClientValidationContext, ExtClientValidationContext, }; -use ibc::core::client::context::{ClientExecutionContext, ClientValidationContext}; use ibc::core::client::types::error::ClientError; use ibc::core::client::types::Height as IbcHeight; use ibc::core::handler::types::error::ContextError; @@ -19,12 +16,13 @@ use ibc::core::host::ValidationContext; use ibc::primitives::Timestamp; use super::impls::{AnyConsensusState, IbcContext}; +use super::AnyClientState; impl ClientValidationContext for IbcContext where S: Store + Debug, { - type ClientStateRef = TmClientState; + type ClientStateRef = AnyClientState; type ConsensusStateRef = AnyConsensusState; fn client_state(&self, client_id: &ClientId) -> Result { @@ -53,7 +51,7 @@ where height, })?; - Ok(consensus_state.into()) + Ok(consensus_state) } /// Returns the time and height when the client state for the given @@ -96,7 +94,7 @@ impl ClientExecutionContext for IbcContext where S: Store + Debug, { - type ClientStateMut = TmClientState; + type ClientStateMut = AnyClientState; /// Called upon successful client creation and update fn store_client_state( @@ -119,12 +117,8 @@ where consensus_state_path: ClientConsensusStatePath, consensus_state: Self::ConsensusStateRef, ) -> Result<(), ContextError> { - let tm_consensus_state: TmConsensusState = - consensus_state.try_into().map_err(|_| ClientError::Other { - description: "Consensus state type mismatch".to_string(), - })?; self.consensus_state_store - .set(consensus_state_path, tm_consensus_state) + .set(consensus_state_path, consensus_state) .map_err(|_| ClientError::Other { description: "Consensus state store error".to_string(), })?; @@ -196,10 +190,9 @@ where } } -impl TmValidationContext for IbcContext +impl ExtClientValidationContext for IbcContext where S: Store + Debug, - Self::ConsensusStateRef: ConsensusStateConverter, { fn host_timestamp(&self) -> Result { ValidationContext::host_timestamp(self) @@ -267,7 +260,7 @@ where height: *height, })?; - Ok(Some(consensus_state.into())) + Ok(Some(consensus_state)) } else { Ok(None) } @@ -304,7 +297,7 @@ where client_id: client_id.clone(), height: *height, })?; - return Ok(Some(consensus_state.into())); + return Ok(Some(consensus_state)); } } Ok(None) diff --git a/basecoin/modules/src/ibc/impls.rs b/basecoin/modules/src/ibc/impls.rs index d1b18962..083f0cc4 100644 --- a/basecoin/modules/src/ibc/impls.rs +++ b/basecoin/modules/src/ibc/impls.rs @@ -15,7 +15,10 @@ use ibc::apps::transfer::handler::send_transfer; use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; use ibc::clients::tendermint::client_state::ClientState as TmClientState; use ibc::clients::tendermint::consensus_state::ConsensusState as TmConsensusState; -use ibc::clients::tendermint::types::ConsensusState as ConsensusStateType; +use ibc::clients::tendermint::types::{ + ClientState as ClientStateType, ConsensusState as ConsensusStateType, + TENDERMINT_CLIENT_STATE_TYPE_URL, TENDERMINT_CONSENSUS_STATE_TYPE_URL, +}; use ibc::core::channel::types::channel::{ChannelEnd, IdentifiedChannelEnd}; use ibc::core::channel::types::commitment::{AcknowledgementCommitment, PacketCommitment}; use ibc::core::channel::types::error::{ChannelError, PacketError}; @@ -39,7 +42,7 @@ use ibc::core::host::types::path::{ }; use ibc::core::host::{ClientStateRef, ConsensusStateRef, ExecutionContext, ValidationContext}; use ibc::cosmos_host::IBC_QUERY_PATH; -use ibc::derive::ConsensusState; +use ibc::derive::{ClientState, ConsensusState}; use ibc::primitives::{Signer, Timestamp}; use ibc_proto::google::protobuf::Any; use ibc_proto::ibc::core::channel::v1::query_server::QueryServer as ChannelQueryServer; @@ -67,10 +70,54 @@ use crate::types::QueryResult; use crate::upgrade::Upgrade; use crate::CHAIN_REVISION_NUMBER; +#[derive(ClientState, Clone, From, TryInto)] +#[validation(IbcContext)] +#[execution(IbcContext)] +pub enum AnyClientState { + Tendermint(TmClientState), +} + +impl From for AnyClientState { + fn from(value: ClientStateType) -> Self { + AnyClientState::Tendermint(value.into()) + } +} + +impl TryFrom for ClientStateType { + type Error = ClientError; + + fn try_from(value: AnyClientState) -> Result { + match value { + AnyClientState::Tendermint(tm_client_state) => Ok(tm_client_state.inner().clone()), + } + } +} + +impl From for Any { + fn from(value: AnyClientState) -> Self { + match value { + AnyClientState::Tendermint(tm_client_state) => tm_client_state.into(), + } + } +} + +impl TryFrom for AnyClientState { + type Error = ClientError; + + fn try_from(value: Any) -> Result { + match value.type_url.as_str() { + TENDERMINT_CLIENT_STATE_TYPE_URL => Ok(AnyClientState::Tendermint(value.try_into()?)), + _ => Err(ClientError::Other { + description: "Unknown client state type".into(), + }), + } + } +} + // Note: We define `AnyConsensusState` just to showcase the use of the // derive macro. Technically, we could just use `TmConsensusState` // as the `AnyConsensusState`, since we only support this one variant. -#[derive(ConsensusState, From, TryInto)] +#[derive(ConsensusState, Clone, From, TryInto)] pub enum AnyConsensusState { Tendermint(TmConsensusState), } @@ -101,12 +148,27 @@ impl From for Any { } } +impl TryFrom for AnyConsensusState { + type Error = ClientError; + + fn try_from(value: Any) -> Result { + match value.type_url.as_str() { + TENDERMINT_CONSENSUS_STATE_TYPE_URL => { + Ok(AnyConsensusState::Tendermint(value.try_into()?)) + } + _ => Err(ClientError::Other { + description: "Unknown consensus state type".into(), + }), + } + } +} + #[derive(Clone)] pub struct Ibc where S: Store + Debug, { - ctx: IbcContext, + pub(crate) ctx: IbcContext, router: Arc>, } @@ -314,10 +376,10 @@ where pub(crate) consensus_states: Arc>>, /// A typed-store for AnyClientState pub(crate) client_state_store: - ProtobufStore, ClientStatePath, TmClientState, Any>, + ProtobufStore, ClientStatePath, AnyClientState, Any>, /// A typed-store for AnyConsensusState pub(crate) consensus_state_store: - ProtobufStore, ClientConsensusStatePath, TmConsensusState, Any>, + ProtobufStore, ClientConsensusStatePath, AnyConsensusState, Any>, /// A typed-store for ConnectionEnd connection_end_store: ProtobufStore, ConnectionPath, ConnectionEnd, RawConnectionEnd>, @@ -683,7 +745,7 @@ where height, } })?; - Ok((height, client_state.into())) + Ok((height, client_state)) }) .collect() } diff --git a/basecoin/modules/src/upgrade/impls.rs b/basecoin/modules/src/upgrade/impls.rs index 4464407d..9f5e7809 100644 --- a/basecoin/modules/src/upgrade/impls.rs +++ b/basecoin/modules/src/upgrade/impls.rs @@ -4,7 +4,6 @@ use basecoin_store::context::{ProvableStore, Store}; use basecoin_store::impls::SharedStore; use basecoin_store::types::{Height, Path, ProtobufStore, TypedStore}; use cosmrs::AccountId; -use ibc::clients::tendermint::client_state::ClientState as TmClientState; use ibc::clients::tendermint::consensus_state::ConsensusState as TmConsensusState; use ibc::clients::tendermint::types::ConsensusState as ConsensusStateType; use ibc::core::client::types::error::UpgradeClientError; @@ -29,7 +28,7 @@ use super::query::UPGRADE_PLAN_QUERY_PATH; use super::service::UpgradeService; use crate::context::Module; use crate::error::Error as AppError; -use crate::ibc::{AnyConsensusState, IbcContext}; +use crate::ibc::{AnyClientState, AnyConsensusState, IbcContext}; use crate::types::QueryResult; #[derive(Clone)] @@ -42,10 +41,10 @@ where upgrade_plan: ProtobufStore, UpgradePlanPath, Plan, Any>, /// A typed-store for upgraded ClientState upgraded_client_state_store: - ProtobufStore, UpgradeClientPath, TmClientState, Any>, + ProtobufStore, UpgradeClientPath, AnyClientState, Any>, /// A typed-store for upgraded ConsensusState upgraded_consensus_state_store: - ProtobufStore, UpgradeClientPath, TmConsensusState, Any>, + ProtobufStore, UpgradeClientPath, AnyConsensusState, Any>, } /// Trait to provide proofs in gRPC service blanket implementations. @@ -239,7 +238,7 @@ where fn upgraded_client_state( &self, upgrade_path: &UpgradeClientPath, - ) -> Result { + ) -> Result { let upgraded_tm_client_state = self .upgraded_client_state_store .get(Height::Pending, upgrade_path) @@ -259,7 +258,7 @@ where .ok_or(UpgradeClientError::Other { reason: "No upgraded consensus state set".to_string(), })?; - Ok(upgraded_tm_consensus_state.into()) + Ok(upgraded_tm_consensus_state) } } @@ -317,7 +316,7 @@ where fn store_upgraded_client_state( &mut self, upgrade_path: UpgradeClientPath, - client_state: TmClientState, + client_state: AnyClientState, ) -> Result<(), UpgradeClientError> { self.upgraded_client_state_store .set(upgrade_path, client_state) @@ -333,15 +332,8 @@ where upgrade_path: UpgradeClientPath, consensus_state: AnyConsensusState, ) -> Result<(), UpgradeClientError> { - let tm_consensus_state: TmConsensusState = - consensus_state - .try_into() - .map_err(|err: &str| UpgradeClientError::Other { - reason: err.to_string(), - })?; - self.upgraded_consensus_state_store - .set(upgrade_path, tm_consensus_state) + .set(upgrade_path, consensus_state) .map_err(|e| UpgradeClientError::Other { reason: format!("Error storing upgraded consensus state: {e:?}"), })?; diff --git a/basecoin/src/bin/basecoin.rs b/basecoin/src/bin/basecoin.rs index 10a44efb..b7fdba40 100644 --- a/basecoin/src/bin/basecoin.rs +++ b/basecoin/src/bin/basecoin.rs @@ -4,12 +4,21 @@ #![forbid(unsafe_code)] use std::io::Write; +use std::str::FromStr; -use basecoin::cli::command::{BasecoinCli, Commands, QueryCmd, UpgradeCmd}; +use basecoin::cli::command::{BasecoinCli, Commands, QueryCmd, RecoverCmd, TxCmds, UpgradeCmd}; use basecoin::config::load_config; use basecoin::default_app_runner; +use basecoin::tx::{self, KeyPair}; +use basecoin_modules::bank::{Coin, Denom}; +use basecoin_modules::gov::MsgSubmitProposal; use basecoin_modules::upgrade::query_upgrade_plan; use clap::Parser; +use hdpath::StandardHDPath; +use ibc::core::client::types::msgs::MsgRecoverClient; +use ibc::core::host::types::identifiers::ClientId; +use ibc::primitives::{Signer, ToProto}; +use ibc_proto::cosmos::tx::v1beta1::Fee; use tracing::metadata::LevelFilter; #[tokio::main] @@ -40,5 +49,88 @@ async fn main() { }; let _ = write!(std::io::stdout(), "{:#?}", query_res); } + Commands::Tx(c) => { + let hdpath = StandardHDPath::from_str(&c.derivation_path).unwrap(); + + let key_pair = match KeyPair::from_seed_file(&c.seed_file, &hdpath) { + Ok(key_pair) => key_pair, + Err(e) => { + tracing::error!("{e}"); + std::process::exit(1); + } + }; + + let signer = Signer::from(key_pair.account.clone()); + + let msg = match &c.command { + TxCmds::Recover(cmd) => { + let RecoverCmd { + subject_client_id, + substitute_client_id, + } = cmd; + + let subject_client_id = + ClientId::from_str(subject_client_id).expect("valid client ID"); + let substitute_client_id = + ClientId::from_str(substitute_client_id).expect("valid client ID"); + + // Create the MsgRecoverClient + let msg = MsgRecoverClient { + subject_client_id, + substitute_client_id, + signer, + }; + + // MsgRecoverClient can only be executed via Gov module + MsgSubmitProposal { + content: msg.to_any(), + initial_deposit: Coin::new_empty(Denom("basecoin".into())), + proposer: key_pair.account.clone(), + } + .to_any() + } + }; + + let chain_id = c.chain_id.parse().unwrap(); + let fee = Fee { + amount: vec![Coin::from_str(&c.fee).unwrap().into()], + gas_limit: c.gas, + granter: "".into(), + payer: "".into(), + }; + + let rpc_addr = cfg.cometbft.rpc_addr.clone(); + let grpc_addr = format!("http://{}:{}", cfg.server.host, cfg.server.grpc_port) + .parse() + .expect("valid grpc endpoint"); + + let account_info = match tx::query_account(grpc_addr, key_pair.account.clone()).await { + Ok(account) => account, + Err(e) => { + tracing::error!("{e}"); + std::process::exit(1); + } + }; + + let signed_tx = match tx::sign_tx( + &key_pair, + &chain_id, + &account_info, + vec![msg], + fee, + c.memo.to_owned(), + ) { + Ok(signed_tx) => signed_tx, + Err(e) => { + tracing::error!("{e}"); + std::process::exit(1); + } + }; + + if let Err(e) = tx::send_tx(rpc_addr, signed_tx).await { + tracing::error!("{e}"); + std::process::exit(1); + } + } }; } diff --git a/basecoin/src/cli/command.rs b/basecoin/src/cli/command.rs index 7d28fb22..e31aeee8 100644 --- a/basecoin/src/cli/command.rs +++ b/basecoin/src/cli/command.rs @@ -32,6 +32,7 @@ pub enum Commands { Start, #[command(subcommand)] Query(QueryCmd), + Tx(TxCmd), } #[derive(Clone, Debug, Parser)] @@ -46,3 +47,51 @@ pub enum QueryCmd { pub enum UpgradeCmd { Plan, } + +#[derive(Clone, Debug, Parser)] +#[command(about = "Send a transaction to be processed by Basecoin")] +pub struct TxCmd { + #[command(subcommand)] + pub command: TxCmds, + + /// Chain ID of the blockchain. + #[arg(long, default_value = "basecoin-0")] + pub chain_id: String, + + /// Fee amount to be paid for the transaction. + #[arg(long, default_value = "4000basecoin")] + pub fee: String, + + /// Gas limit for the transaction. + #[arg(long, default_value_t = 400000_u64)] + pub gas: u64, + + /// Memo to be included in the transaction. + #[arg(long, default_value = "")] + pub memo: String, + + /// The derivation path for the key pair. + #[arg(long, default_value = "m/44'/118'/0'/0/0")] + pub derivation_path: String, + + /// The path to the file containing the seed phrase. + #[arg(long)] + pub seed_file: PathBuf, +} + +#[derive(Clone, Debug, Parser)] +pub enum TxCmds { + Recover(RecoverCmd), +} + +#[derive(Clone, Debug, Parser)] +#[command(about = "Recover an inactive client using a substitute client")] +pub struct RecoverCmd { + /// Identifier of the client to be recovered. + #[arg(long)] + pub subject_client_id: String, + + /// Identifier of the client whose state the recovered client will emulate. + #[arg(long)] + pub substitute_client_id: String, +} diff --git a/basecoin/src/lib.rs b/basecoin/src/lib.rs index a8ab9134..f8c8b5c0 100644 --- a/basecoin/src/lib.rs +++ b/basecoin/src/lib.rs @@ -11,6 +11,7 @@ pub mod cli; pub mod config; pub mod helper; mod runner; +pub mod tx; pub use runner::default_app_runner; diff --git a/basecoin/src/runner.rs b/basecoin/src/runner.rs index 54454130..2448566f 100644 --- a/basecoin/src/runner.rs +++ b/basecoin/src/runner.rs @@ -33,9 +33,11 @@ pub async fn default_app_runner(server_cfg: ServerConfig) { bank.bank_keeper().clone(), ); let upgrade = Upgrade::new(app_builder.module_store(&prefix::Upgrade {}.identifier())); + let governance = Governance::new( app_builder.module_store(&prefix::Governance {}.identifier()), upgrade.clone(), + ibc.clone(), ); // instantiate gRPC services for each module diff --git a/basecoin/src/tx/key_pair.rs b/basecoin/src/tx/key_pair.rs new file mode 100644 index 00000000..2ce44abf --- /dev/null +++ b/basecoin/src/tx/key_pair.rs @@ -0,0 +1,136 @@ +use std::path::Path; + +use basecoin_modules::error::Error; +use bip39::{Language, Mnemonic, Seed}; +use bitcoin::bip32::{ChildNumber, DerivationPath, Xpriv, Xpub}; +use bitcoin::network::Network; +use digest::Digest; +use generic_array::typenum::U32; +use generic_array::GenericArray; +use hdpath::StandardHDPath; +use secp256k1::{Message, PublicKey, Secp256k1, SecretKey}; +use serde::{Deserialize, Serialize}; +use sha2::Sha256; + +/// Represents a JSON seed file. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct KeyFile { + name: String, + r#type: String, + address: String, + pubkey: String, + mnemonic: String, +} + +/// Holds account information and keys needed for signing +/// transactions. +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct KeyPair { + pub public_key: PublicKey, + pub private_key: SecretKey, + pub account: String, + pub address: Vec, +} + +impl KeyPair { + pub fn new( + public_key: PublicKey, + private_key: SecretKey, + account: String, + address: Vec, + ) -> Self { + Self { + public_key, + private_key, + account, + address, + } + } + + /// Reads in a JSON seed file and extracts the KeyPair from it. + pub fn from_seed_file(path: impl AsRef, hd_path: &StandardHDPath) -> Result { + let seed_json = std::fs::read_to_string(&path).map_err(|e| Error::Custom { + reason: format!("failed to read JSON seed file: {e}"), + })?; + + let key_file: KeyFile = serde_json::from_str(&seed_json).map_err(|e| Error::Custom { + reason: format!("failed to deserialize JSON seed file: {e}"), + })?; + + let account = key_file.address.clone(); + + let address = decode_bech32(&key_file.address).map_err(|e| Error::Custom { + reason: format!("failed to decode key file address: {e}"), + })?; + + let private_key = + private_key_from_mnemonic(&key_file.mnemonic, hd_path).map_err(|e| Error::Custom { + reason: format!("failed to derive private key from mnemonic: {e}"), + })?; + + let derived_pubkey = Xpub::from_priv(&Secp256k1::signing_only(), &private_key); + let public_key = derived_pubkey.public_key; + let private_key = private_key.private_key; + + Ok(KeyPair::new(public_key, private_key, account, address)) + } + + pub fn sign(&self, message: &[u8]) -> Result, Error> { + let hashed_message: GenericArray = Sha256::digest(message); + + let message = Message::from_digest_slice(&hashed_message).map_err(|_| Error::Custom { + reason: "attempted to sign a malformed message".to_string(), + })?; + + Ok(Secp256k1::signing_only() + .sign_ecdsa(&message, &self.private_key) + .serialize_compact() + .to_vec()) + } +} + +pub fn private_key_from_mnemonic(mnemonic: &str, hd_path: &StandardHDPath) -> Result { + let mnemonic = + Mnemonic::from_phrase(mnemonic, Language::English).map_err(|e| Error::Custom { + reason: format!("failed to parse mnemonic: {e}"), + })?; + + let seed = Seed::new(&mnemonic, ""); + + let base_key = + Xpriv::new_master(Network::Bitcoin, seed.as_bytes()).map_err(|e| Error::Custom { + reason: format!("failed to generate bip32 key: {e}"), + })?; + + let private_key = base_key + .derive_priv( + &Secp256k1::new(), + &standard_path_to_derivation_path(hd_path), + ) + .map_err(|e| Error::Custom { + reason: format!("failed to generate private key from bip32 key: {e}"), + })?; + + Ok(private_key) +} + +pub fn decode_bech32(input: &str) -> Result, Error> { + let (_, data) = bech32::decode(input).map_err(|e| Error::Custom { + reason: format!("failed to decode bech32 string {input:?}: {e}"), + })?; + + Ok(data) +} + +fn standard_path_to_derivation_path(path: &StandardHDPath) -> DerivationPath { + let child_numbers = vec![ + ChildNumber::from_hardened_idx(path.purpose().as_value().as_number()) + .expect("Purpose is not Hardened"), + ChildNumber::from_hardened_idx(path.coin_type()).expect("Coin Type is not Hardened"), + ChildNumber::from_hardened_idx(path.account()).expect("Account is not Hardened"), + ChildNumber::from_normal_idx(path.change()).expect("Change is Hardened"), + ChildNumber::from_normal_idx(path.index()).expect("Index is Hardened"), + ]; + + DerivationPath::from(child_numbers) +} diff --git a/basecoin/src/tx/mod.rs b/basecoin/src/tx/mod.rs new file mode 100644 index 00000000..6d6723ee --- /dev/null +++ b/basecoin/src/tx/mod.rs @@ -0,0 +1,177 @@ +//! Utilities and logic for sending transactions from basecoin. +//! +//! These exist in order to test certain proposals and message +//! types that Hermes does not support. Note that this logic +//! is not meant to be as robust and production-ready as the +//! transaction-sending logic in Hermes. + +use basecoin_modules::error::Error; +use ibc::core::host::types::identifiers::ChainId; +use ibc_proto::cosmos::auth::v1beta1::query_client::QueryClient; +use ibc_proto::cosmos::auth::v1beta1::{BaseAccount, QueryAccountRequest}; +use ibc_proto::cosmos::tx::v1beta1::mode_info::{Single, Sum}; +use ibc_proto::cosmos::tx::v1beta1::{AuthInfo, Fee, ModeInfo, SignDoc, SignerInfo, TxBody, TxRaw}; +use ibc_proto::google::protobuf::Any; +use prost::Message; +use tendermint_rpc::{Client, HttpClient, Url}; + +mod key_pair; +pub use key_pair::*; + +pub async fn send_tx(rpc_addr: Url, signed_tx: Vec) -> Result<(), Error> { + let rpc_client = HttpClient::new(rpc_addr.clone()).unwrap(); + + rpc_client + .broadcast_tx_sync(signed_tx) + .await + .map_err(|e| Error::Custom { + reason: format!("failed to broadcast tx: {e}"), + })?; + + Ok(()) +} + +/// Signs and encodes the given messages. +/// +/// Returns a raw ready-to-send transaction. +pub fn sign_tx( + key: &KeyPair, + chain_id: &ChainId, + account_info: &BaseAccount, + messages: Vec, + fee: Fee, + memo: String, +) -> Result, Error> { + let pk_bytes = encode_key_bytes(key)?; + + let signer_info = encode_signer_info(account_info.sequence, pk_bytes)?; + let (_, auth_info_bytes) = encode_auth_info(signer_info, fee)?; + let (_, body_bytes) = encode_tx_body(messages, memo)?; + + let signature_bytes = encode_sign_doc( + key.clone(), + body_bytes.clone(), + auth_info_bytes.clone(), + chain_id.clone(), + account_info.account_number, + )?; + + let (_, tx_bytes) = encode_tx(body_bytes, auth_info_bytes, signature_bytes.clone())?; + + Ok(tx_bytes) +} + +pub fn encode_key_bytes(key: &KeyPair) -> Result, Error> { + let serialized_key = &key.public_key.serialize().to_vec(); + let pk = Message::encode_to_vec(serialized_key); + Ok(pk) +} + +pub fn encode_signer_info(sequence: u64, key_bytes: Vec) -> Result { + let pk_any = Any { + type_url: "/cosmos.crypto.secp256k1.PubKey".to_string(), + value: key_bytes, + }; + + let single = Single { mode: 1 }; + let sum_single = Some(Sum::Single(single)); + let mode = Some(ModeInfo { sum: sum_single }); + let signer_info = SignerInfo { + public_key: Some(pk_any), + mode_info: mode, + sequence, + }; + + Ok(signer_info) +} + +pub fn encode_auth_info(signer_info: SignerInfo, fee: Fee) -> Result<(AuthInfo, Vec), Error> { + let auth_info = AuthInfo { + signer_infos: vec![signer_info], + fee: Some(fee), + tip: None, + }; + + let auth_info_bytes = Message::encode_to_vec(&auth_info); + + Ok((auth_info, auth_info_bytes)) +} + +pub fn encode_sign_doc( + key_pair: KeyPair, + body_bytes: Vec, + auth_info_bytes: Vec, + chain_id: ChainId, + account_number: u64, +) -> Result, Error> { + let sign_doc = SignDoc { + body_bytes, + auth_info_bytes, + chain_id: chain_id.to_string(), + account_number, + }; + + let signdoc_buf = Message::encode_to_vec(&sign_doc); + + let signed = key_pair.sign(&signdoc_buf).map_err(|e| Error::Custom { + reason: format!("failed to create signature: {e}"), + })?; + + Ok(signed) +} + +pub fn encode_tx_body(messages: Vec, memo: String) -> Result<(TxBody, Vec), Error> { + let body = TxBody { + messages, + memo, + timeout_height: 0_u64, + extension_options: vec![], + non_critical_extension_options: vec![], + }; + + let body_bytes = Message::encode_to_vec(&body); + + Ok((body, body_bytes)) +} + +pub fn encode_tx( + body_bytes: Vec, + auth_info_bytes: Vec, + signature_bytes: Vec, +) -> Result<(TxRaw, Vec), Error> { + let tx_raw = TxRaw { + body_bytes, + auth_info_bytes, + signatures: vec![signature_bytes], + }; + + let tx_bytes = Message::encode_to_vec(&tx_raw); + + Ok((tx_raw, tx_bytes)) +} + +/// Retrieves the account sequence via gRPC client. +pub async fn query_account(grpc_addr: Url, address: String) -> Result { + let mut client = QueryClient::connect(grpc_addr.to_string()) + .await + .map_err(|e| Error::Custom { + reason: format!("failed to connect to gRPC client: {e}"), + })?; + + let request = tonic::Request::new(QueryAccountRequest { address }); + let response = client.account(request).await; + + let resp_account = response + .map_err(|e| Error::Custom { + reason: format!("failed to query account: {e}"), + })? + .into_inner() + .account + .ok_or_else(|| Error::Custom { + reason: "failed to find account".into(), + })?; + + BaseAccount::decode(resp_account.value.as_slice()).map_err(|e| Error::Custom { + reason: format!("failed to decode account: {e}"), + }) +} diff --git a/basecoin/store/Cargo.toml b/basecoin/store/Cargo.toml index 7bab0e5c..c913cd20 100644 --- a/basecoin/store/Cargo.toml +++ b/basecoin/store/Cargo.toml @@ -6,16 +6,14 @@ license = { workspace = true } readme = { workspace = true } repository = { workspace = true } authors = { workspace = true } -description = """ - A simple implementation of an AVL store tailored for the basecoin application. -""" +description = "A simple implementation of an AVL store tailored for the basecoin application." [dependencies] -displaydoc = { workspace = true } -ics23 = { workspace = true, features = ["host-functions"] } -prost = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -sha2 = { workspace = true } -tendermint = { workspace = true } -tracing = { workspace = true } +displaydoc = { workspace = true } +ics23 = { workspace = true, features = [ "host-functions" ] } +prost = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +sha2 = { workspace = true } +tendermint = { workspace = true } +tracing = { workspace = true } diff --git a/ci/Makefile b/ci/Makefile index b7433047..142c80ac 100644 --- a/ci/Makefile +++ b/ci/Makefile @@ -1,6 +1,6 @@ -.PHONY: test create-channel token-transfer upgrade-client grpc-service +.PHONY: test create-channel token-transfer upgrade-client grpc-service recover-client -test: create-channel token-transfer upgrade-client grpc-service +test: create-channel token-transfer upgrade-client grpc-service recover-client @echo "All tests passed" create-channel: @@ -8,7 +8,12 @@ create-channel: bash ~/tests/create-channel.sh @echo "Channel created" -token-transfer: create-channel +recover-client: create-channel + @echo "Recovering client..." + bash ~/tests/recover-client.sh + @echo "Client recovered" + +token-transfer: create-channel recover-client @echo "Transferring tokens..." bash ~/tests/token-transfer.sh @echo "Tokens transferred" diff --git a/ci/tests/create-channel.sh b/ci/tests/create-channel.sh old mode 100755 new mode 100644 diff --git a/ci/tests/recover-client.sh b/ci/tests/recover-client.sh new file mode 100644 index 00000000..20f84ddd --- /dev/null +++ b/ci/tests/recover-client.sh @@ -0,0 +1,71 @@ +#!/bin/bash +set -euo pipefail + +BASECOIN_BIN=${BASECOIN_BIN:-${HOME}/build/basecoin-rs/debug/basecoin} + +HERMES_CONFIG="${HOME}/.hermes/config.toml" +HERMES_RECOVERY_CONFIG="recovery-config.toml" +cp ${HERMES_CONFIG} ${HERMES_RECOVERY_CONFIG} + +# install tomlq (part of yq) if not already installed +command -v tomlq || pip install yq + +# update ibc-0's trusting period: 10s +tomlq -it '.chains[0].trusting_period = "10s"' ${HERMES_RECOVERY_CONFIG} + +# In order to test client recovery of a client running on a basecoin chain, this +# test exhibits the following setup: +# Two chains: a gaiad chain and a basecoin chain (backed by a cometbft node) +# Two clients per chain (four total) +# Two Hermes instances, each relaying between a gaiad client and a basecoin client +# +# The two gaiad clients are configured identically +# The two basecoin clients are configured almost identically, except that one of the +# clients has a much shorter trusting period than the other client. This is so that +# one client will be in an expired state after the process sleeps for the length of +# its trusting period, while the other client will still be in an active state. At +# this point, the client recovery process is initiated with the expired client +# specified as the subject client and the active client specified as the substitute +# client. + +# this is not necessary for the test, as we are not creating a connection. +echo "creating the active client on ibc-0" +hermes --config "${HERMES_RECOVERY_CONFIG}" \ + create client --host-chain ibc-0 --reference-chain basecoin-0 + +# old client-id: 07-tendermint-0 +# creates new client-id: 07-tendermint-1 with short trusting period: 10s. +echo "creating the expiring client on basecoin-0" +hermes --config "${HERMES_RECOVERY_CONFIG}" \ + create client --host-chain basecoin-0 --reference-chain ibc-0 + +# wait for more than the trusting period +sleep 10s + +# need to update the substitute client +# substitute client height must be greater than the subject client height +hermes --config "${HERMES_CONFIG}" update client --host-chain basecoin-0 --client 07-tendermint-0 + +# substitute client is active +grpcurl -plaintext -d '{"client_id":"07-tendermint-0"}' localhost:9093 ibc.core.client.v1.Query/ClientStatus \ + | jq -e '.status == "Active"' + +# subject client is expired +grpcurl -plaintext -d '{"client_id":"07-tendermint-1"}' localhost:9093 ibc.core.client.v1.Query/ClientStatus \ + | jq -e '.status == "Expired"' + +echo "initiating client recovery" +# recovering 07-tendermint-1 with 07-tendermint-0 +${BASECOIN_BIN} tx --seed-file "./ci/user_seed.json" \ + recover --subject-client-id 07-tendermint-1 --substitute-client-id 07-tendermint-0 + +# wait for the client to recover +sleep 3s + +# substitute client is active +grpcurl -plaintext -d '{"client_id":"07-tendermint-0"}' localhost:9093 ibc.core.client.v1.Query/ClientStatus \ + | jq -e '.status == "Active"' + +# subject client is recovered and now active +grpcurl -plaintext -d '{"client_id":"07-tendermint-1"}' localhost:9093 ibc.core.client.v1.Query/ClientStatus \ + | jq -e '.status == "Active"' diff --git a/ci/tests/token-transfer.sh b/ci/tests/token-transfer.sh old mode 100755 new mode 100644 diff --git a/taplo.toml b/taplo.toml new file mode 100644 index 00000000..edaa7882 --- /dev/null +++ b/taplo.toml @@ -0,0 +1,7 @@ +include = [ "taplo.toml", "**/Cargo.toml" ] + +[formatting] +align_entries = true +compact_arrays = false +array_auto_expand = false +array_auto_collapse = false