diff --git a/.changelog/unreleased/improvements/3405-phase-1-shielded-sync-refactor.md b/.changelog/unreleased/improvements/3405-phase-1-shielded-sync-refactor.md new file mode 100644 index 0000000000..44f51930d7 --- /dev/null +++ b/.changelog/unreleased/improvements/3405-phase-1-shielded-sync-refactor.md @@ -0,0 +1,7 @@ + - Implements phase 1 of Issue [\#3385](https://github.com/anoma/namada/issues/3385) + - When fetching notes, connections and related failures should not halt shielded sync. Instead, the process + should be restarted + - If fetching is interrupted, the data fetched should be persisted locally so that progress isn't lost. + - A trait for fetching behavior should be added to provide modularity + + ([\#3498](https://github.com/anoma/namada/pull/3498)) diff --git a/.changelog/unreleased/improvements/3428-better-gas-interface.md b/.changelog/unreleased/improvements/3428-better-gas-interface.md new file mode 100644 index 0000000000..fbc0d58202 --- /dev/null +++ b/.changelog/unreleased/improvements/3428-better-gas-interface.md @@ -0,0 +1,2 @@ +- Improved the interface of the gas type. Removed the duplicated gas used from + events. ([\#3428](https://github.com/anoma/namada/pull/3428)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3456-masp-ss-phase-2.md b/.changelog/unreleased/improvements/3456-masp-ss-phase-2.md new file mode 100644 index 0000000000..51a2c4760a --- /dev/null +++ b/.changelog/unreleased/improvements/3456-masp-ss-phase-2.md @@ -0,0 +1,4 @@ +- Implement the phase 2 masp shielded sync client. This client uses + a [`namada-masp-indexer`](https://github.com/anoma/namada-masp- + indexer) instance to query the state of the shielded context. + ([\#3456](https://github.com/anoma/namada/pull/3456)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3473-opt-validation-calls.md b/.changelog/unreleased/improvements/3473-opt-validation-calls.md new file mode 100644 index 0000000000..3331f6b71a --- /dev/null +++ b/.changelog/unreleased/improvements/3473-opt-validation-calls.md @@ -0,0 +1,4 @@ +- Modified rechecks of process proposal to actually use `process_proposal` + instead of `process_txs`. Added a caching mechanism to avoid + running the check for a given proposed block more than once. + ([\#3473](https://github.com/anoma/namada/pull/3473)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3494-expand-correct-test-vectors.md b/.changelog/unreleased/improvements/3494-expand-correct-test-vectors.md new file mode 100644 index 0000000000..181aed4cc8 --- /dev/null +++ b/.changelog/unreleased/improvements/3494-expand-correct-test-vectors.md @@ -0,0 +1,2 @@ +- Expanded the scope of test vector generation and updated outdated components + of the test vector code. ([\#3494](https://github.com/anoma/namada/pull/3494)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3502-without-pow.md b/.changelog/unreleased/improvements/3502-without-pow.md new file mode 100644 index 0000000000..86226a0913 --- /dev/null +++ b/.changelog/unreleased/improvements/3502-without-pow.md @@ -0,0 +1,2 @@ +- Removes redundant function. + ([\#3502](https://github.com/anoma/namada/pull/3502)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3506-tendermint-0.37.md b/.changelog/unreleased/improvements/3506-tendermint-0.37.md new file mode 100644 index 0000000000..eaaefa6e55 --- /dev/null +++ b/.changelog/unreleased/improvements/3506-tendermint-0.37.md @@ -0,0 +1,2 @@ +- Bump tendermint-rs to 0.37 + ([\#3506](https://github.com/anoma/namada/issues/3506)) \ No newline at end of file diff --git a/.changelog/v0.40.0/bug-fixes/3488-fix-ibc-masp-tx-extraction.md b/.changelog/v0.40.0/bug-fixes/3488-fix-ibc-masp-tx-extraction.md new file mode 100644 index 0000000000..413db843d5 --- /dev/null +++ b/.changelog/v0.40.0/bug-fixes/3488-fix-ibc-masp-tx-extraction.md @@ -0,0 +1,2 @@ +- Fix to extract MASP transaction when IBC shielding transfer + ([\#3488](https://github.com/anoma/namada/issues/3488)) \ No newline at end of file diff --git a/.github/workflows/scripts/e2e.json b/.github/workflows/scripts/e2e.json index 12c8278cc0..562949dc87 100644 --- a/.github/workflows/scripts/e2e.json +++ b/.github/workflows/scripts/e2e.json @@ -28,5 +28,6 @@ "e2e::wallet_tests::wallet_address_cmds": 1, "e2e::wallet_tests::wallet_encrypted_key_cmds": 1, "e2e::wallet_tests::wallet_encrypted_key_cmds_env_var": 1, - "e2e::wallet_tests::wallet_unencrypted_key_cmds": 1 -} + "e2e::wallet_tests::wallet_unencrypted_key_cmds": 1, + "e2e::ledger_tests::masp_txs_and_queries": 82 +} \ No newline at end of file diff --git a/.github/workflows/scripts/hermes.txt b/.github/workflows/scripts/hermes.txt index 7669eaf98a..27439ea78e 100644 --- a/.github/workflows/scripts/hermes.txt +++ b/.github/workflows/scripts/hermes.txt @@ -1 +1 @@ -1.9.0-namada-beta13-rc2 +1.9.0-namada-beta14-rc diff --git a/Cargo.lock b/Cargo.lock index 1018527284..7983570a74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -671,45 +671,16 @@ dependencies = [ "subtle", ] -[[package]] -name = "bnum" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" - -[[package]] -name = "borsh" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" -dependencies = [ - "borsh-derive 0.10.3", - "hashbrown 0.12.3", -] - [[package]] name = "borsh" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9897ef0f1bd2362169de6d7e436ea2237dc1085d7d1e4db75f4be34d86f309d1" dependencies = [ - "borsh-derive 1.2.1", + "borsh-derive", "cfg_aliases", ] -[[package]] -name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "borsh-derive" version = "1.2.1" @@ -717,41 +688,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478b41ff04256c5c8330f3dfdaaae2a5cc976a8e75088bafa4625b0d0208de8c" dependencies = [ "once_cell", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 2.0.52", "syn_derive", ] -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "borsh-ext" version = "1.2.0" source = "git+https://github.com/heliaxdev/borsh-ext?tag=v1.2.0#a62fee3e847e512cad9ac0f1fd5a900e5db9ba37" dependencies = [ - "borsh 1.2.1", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "borsh", ] [[package]] @@ -1314,75 +1263,6 @@ dependencies = [ "windows-sys 0.33.0", ] -[[package]] -name = "cosmwasm-crypto" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd50718a2b6830ce9eb5d465de5a018a12e71729d66b70807ce97e6dd14f931d" -dependencies = [ - "digest 0.10.7", - "ecdsa", - "ed25519-zebra", - "k256", - "rand_core 0.6.4", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "242e98e7a231c122e08f300d9db3262d1007b51758a8732cd6210b3e9faa4f3a" -dependencies = [ - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-schema" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7879036156092ad1c22fe0d7316efc5a5eceec2bc3906462a2560215f2a2f929" -dependencies = [ - "cosmwasm-schema-derive", - "schemars", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "cosmwasm-schema-derive" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb57855fbfc83327f8445ae0d413b1a05ac0d68c396ab4d122b2abd7bb82cb6" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-std" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" -dependencies = [ - "base64 0.21.7", - "bech32 0.9.1", - "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 = "cpufeatures" version = "0.2.11" @@ -1633,19 +1513,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" -[[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.2" @@ -1687,17 +1554,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "cw-storage-plus" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - [[package]] name = "darling" version = "0.14.4" @@ -1872,13 +1728,13 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -1936,9 +1792,9 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", @@ -2079,7 +1935,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek", "ed25519", "serde", "sha2 0.10.8", @@ -2087,21 +1943,6 @@ dependencies = [ "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", -] - [[package]] name = "either" version = "1.12.0" @@ -2663,6 +2504,18 @@ dependencies = [ "paste", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2693,12 +2546,6 @@ 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 = "fpe" version = "0.6.1" @@ -3311,8 +3158,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9298a8de81eea8d496672e47f13ab1ae5145b3b554ec3951222197697e1cf82" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-apps", "ibc-clients", @@ -3325,22 +3171,20 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e4d7728ae132ecb49286f225d0ab6ad56b2a15af47e019da45ad23fd789d76f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", - "serde-json-wasm 1.0.1", + "serde-json-wasm", ] [[package]] name = "ibc-app-nft-transfer-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333b2fcc0226d150e996fddd3fd2041460c7ed7e7594b65077026c7e38587329" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "base64 0.21.7", - "borsh 0.10.3", + "base64 0.22.1", + "borsh", "derive_more", "displaydoc", "http 1.1.0", @@ -3352,27 +3196,25 @@ dependencies = [ "scale-info", "schemars", "serde", - "serde-json-wasm 1.0.1", + "serde-json-wasm", ] [[package]] name = "ibc-app-transfer" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf138e322daa7b757b66a8c9a5bcac00773136f4b939b6cfb43bb95576ba59d" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-app-transfer-types", "ibc-core", - "serde-json-wasm 1.0.1", + "serde-json-wasm", ] [[package]] name = "ibc-app-transfer-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8777875777e43f3c18a340ac5ea2223dc87a67b60d99e451142eac3b7b7a46" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core", @@ -3388,34 +3230,16 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac849a9d4f6097cc81405b00428fd73b04ce5290d806ce7f5c8afd42fbfb9bd" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", ] -[[package]] -name = "ibc-client-cw" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14bf49f8f43c3fea593d7c2413e061f8df607de45e6f7d76de5346a456f6addd" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "derive_more", - "ibc-client-wasm-types", - "ibc-core", - "prost 0.12.3", - "serde", -] - [[package]] name = "ibc-client-tendermint" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804dcd81f62608c453e72f669b2df986eb49d4b4381deac2a70bd33ee94cef7f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -3425,27 +3249,14 @@ dependencies = [ "ibc-core-host", "ibc-primitives", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-light-client-verifier", ] -[[package]] -name = "ibc-client-tendermint-cw" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d6d96b221fb6b68dc89c49150f83110928aeac146f90a434dfa5e354fbf8ca7" -dependencies = [ - "cosmwasm-std", - "ibc-client-cw", - "ibc-client-tendermint", - "ibc-core", -] - [[package]] name = "ibc-client-tendermint-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b41444137be02cabc484079443f447d23e746fabd9ac6fd5d99faac0b30a5f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -3454,19 +3265,17 @@ dependencies = [ "ibc-primitives", "ibc-proto", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-light-client-verifier", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", ] [[package]] name = "ibc-client-wasm-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc05b707ee957b1272877606379647ae1e5897316a3406b6a93e1885ee99e68" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "base64 0.21.7", - "cosmwasm-schema", + "base64 0.22.1", "displaydoc", "ibc-core-client", "ibc-core-host-types", @@ -3478,8 +3287,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675754a0a5f2f70f71445338fa4d8b49d3c84ce1cf4748ca6c98bf6ede9c4bfc" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -3488,8 +3296,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cb69c4ee05d367fa321acf67ec00d3e9f8ecfef013accdb05889db32ff2de3f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -3505,8 +3312,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5dcc1c14a92f01e556d72d834f842bb655043a7e122ebb8aabdb5e9df600aa8" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -3521,10 +3327,9 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2744ad32ae7360caefb80f495800f883f5e5687cfbd74ff82a444b59a47af7" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-client-types", @@ -3539,14 +3344,13 @@ dependencies = [ "serde", "sha2 0.10.8", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-client" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80071ac73dd4f3436bf1aef03c9b1715a4db0914f738904c281449dc05a0a9cf" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -3559,8 +3363,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9f751b62cad4195be5347646151020fd27c2924f10d82d6301a675fac544dd" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -3570,16 +3373,15 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-client-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "423e9e9a70b78fabc94c51dae76800459e126f891ae0987e88ac5e12c36e24de" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-commitment-types", @@ -3591,16 +3393,15 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-commitment-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b323c91e58ea7b573e01b8e76d13f146c97c245ada0aab3070576d54288f30" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-primitives", @@ -3616,23 +3417,23 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31271364789ccfc12c25afa21b47274d7e07bf49b1f728fd66cfa6c29daaf4a" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ + "ibc-client-wasm-types", "ibc-core-client", "ibc-core-connection-types", "ibc-core-handler-types", "ibc-core-host", "ibc-primitives", + "prost 0.12.3", ] [[package]] name = "ibc-core-connection-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d302a36925469589a911dab66654f390b87e98608d07515e47f5c7e51dffe7" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-client-types", @@ -3645,14 +3446,13 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-handler" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4523b9f77d3a1a391a3d63737760be44b23bc9b09ed297883a34654383b9b0e2" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -3667,10 +3467,9 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b229a92aa8b06ab9ccde6e1b3dad597deb97cb40e3bb6a631799b4cd2ad124" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-channel-types", @@ -3686,14 +3485,13 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-host" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ed7421f285225b78f3d020df6126b61f94b9eb370a83e42fbd4e9c8b04162fa" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -3711,8 +3509,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b25b5b45cf47b1e73211a83adf3a753f1acdba887cd3bc5357d6f547d4a3e8c" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -3729,16 +3526,15 @@ dependencies = [ "serde", "sha2 0.10.8", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-host-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939178939d33e5af1aca19608b019233d753f3734b828d66f40152b382f3db53" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-primitives", @@ -3751,8 +3547,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328e6db6d3aa7126278c46c3dff779aa961952a63d031d3ddf4c202f4a3faad4" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -3766,10 +3561,9 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4175b57087b28759364572683b335ec4fe63a6f938f1a5d0c383a6297a032155" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-host-types", @@ -3780,14 +3574,13 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-derive" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d961d2194fd5229961835d2eb78091906ef8afbaaa55bce7ad41bf3ead8aa9" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "proc-macro2", "quote", @@ -3797,10 +3590,9 @@ dependencies = [ [[package]] name = "ibc-primitives" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3340c4908f1a1a36863270ac976e0295fbd1911cbc4609ab406967fd8ccc04" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-proto", @@ -3809,18 +3601,18 @@ dependencies = [ "scale-info", "schemars", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "time", ] [[package]] name = "ibc-proto" -version = "0.44.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66080040d5a4800d52966d55b055400f86b79c34b854b935bef03c87aacda62a" +checksum = "6cb09e0b52b8a16e98ce98845e7c15b018440f3c56defa12fa44782cd66bab65" dependencies = [ "base64 0.22.1", - "borsh 0.10.3", + "borsh", "bytes", "flex-error", "ics23", @@ -3831,15 +3623,14 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", "tonic", ] [[package]] name = "ibc-query" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a0a3c4ea045cb0971253508c9b074d2b80271f8e57d3716b67bc0b6c8365c6c" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "displaydoc", "ibc", @@ -3850,22 +3641,18 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28f040bb9654b2e618dc75a43d101f69678eeb665fdbef5e5755750ab72625a" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "basecoin-store", "derive_more", "displaydoc", "ibc", - "ibc-client-cw", - "ibc-client-tendermint-cw", "ibc-proto", "ibc-query", "parking_lot", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-testgen", - "tracing", "typed-builder", ] @@ -3971,7 +3758,7 @@ name = "index-set" version = "0.8.0" source = "git+https://github.com/heliaxdev/index-set?tag=v0.8.1#b0d928f83cf0d465ccda299d131e8df2859b5184" dependencies = [ - "borsh 1.2.1", + "borsh", "serde", ] @@ -3991,7 +3778,7 @@ name = "indexmap" version = "2.2.4" source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" dependencies = [ - "borsh 1.2.1", + "borsh", "equivalent", "hashbrown 0.14.3", "serde", @@ -4453,7 +4240,7 @@ name = "masp_note_encryption" version = "1.0.0" source = "git+https://github.com/anoma/masp?rev=8d83b172698098fba393006016072bc201ed9ab7#8d83b172698098fba393006016072bc201ed9ab7" dependencies = [ - "borsh 1.2.1", + "borsh", "chacha20", "chacha20poly1305", "cipher", @@ -4472,7 +4259,7 @@ dependencies = [ "blake2b_simd", "blake2s_simd", "bls12_381", - "borsh 1.2.1", + "borsh", "byteorder", "ff", "fpe", @@ -4675,7 +4462,7 @@ dependencies = [ "assert_matches", "async-trait", "base58", - "borsh 1.2.1", + "borsh", "borsh-ext", "byte-unit", "clru", @@ -4739,7 +4526,7 @@ dependencies = [ name = "namada_account" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "linkme", "namada_core", "namada_macros", @@ -4782,7 +4569,7 @@ dependencies = [ "async-trait", "base64 0.13.1", "bit-set", - "borsh 1.2.1", + "borsh", "borsh-ext", "clap", "color-eyre", @@ -4838,7 +4625,7 @@ dependencies = [ name = "namada_benchmarks" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "borsh-ext", "criterion", "lazy_static", @@ -4872,7 +4659,7 @@ version = "0.40.0" dependencies = [ "assert_matches", "bech32 0.8.1", - "borsh 1.2.1", + "borsh", "borsh-ext", "chrono", "data-encoding", @@ -4907,8 +4694,8 @@ dependencies = [ "sha2 0.9.9", "smooth-operator", "sparse-merkle-tree", - "tendermint 0.36.0", - "tendermint-proto 0.36.0", + "tendermint 0.37.0", + "tendermint-proto 0.37.0", "test-log", "thiserror", "tiny-keccak", @@ -4923,7 +4710,7 @@ dependencies = [ name = "namada_encoding_spec" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "itertools 0.12.1", "lazy_static", "madato", @@ -4935,7 +4722,7 @@ name = "namada_ethereum_bridge" version = "0.40.0" dependencies = [ "assert_matches", - "borsh 1.2.1", + "borsh", "data-encoding", "ethabi", "ethers", @@ -4965,7 +4752,7 @@ dependencies = [ name = "namada_events" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "linkme", "namada_core", "namada_macros", @@ -4980,7 +4767,7 @@ dependencies = [ name = "namada_examples" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "data-encoding", "masp_primitives", "masp_proofs", @@ -5001,7 +4788,7 @@ name = "namada_gas" version = "0.40.0" dependencies = [ "assert_matches", - "borsh 1.2.1", + "borsh", "linkme", "namada_core", "namada_events", @@ -5016,7 +4803,7 @@ dependencies = [ name = "namada_governance" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "itertools 0.12.1", "konst", "linkme", @@ -5039,7 +4826,7 @@ dependencies = [ name = "namada_ibc" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "data-encoding", "ibc", "ibc-derive", @@ -5072,7 +4859,7 @@ dependencies = [ name = "namada_light_sdk" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "borsh-ext", "namada_sdk", "prost 0.12.3", @@ -5099,7 +4886,7 @@ name = "namada_merkle_tree" version = "0.40.0" dependencies = [ "assert_matches", - "borsh 1.2.1", + "borsh", "eyre", "ics23", "itertools 0.12.1", @@ -5130,7 +4917,7 @@ dependencies = [ "async-trait", "base64 0.13.1", "blake2b-rs", - "borsh 1.2.1", + "borsh", "borsh-ext", "byte-unit", "bytes", @@ -5201,7 +4988,7 @@ name = "namada_proof_of_stake" version = "0.40.0" dependencies = [ "assert_matches", - "borsh 1.2.1", + "borsh", "derivative", "itertools 0.12.1", "konst", @@ -5245,7 +5032,7 @@ dependencies = [ "async-trait", "base58", "bimap", - "borsh 1.2.1", + "borsh", "borsh-ext", "circular-queue", "clap", @@ -5257,6 +5044,7 @@ dependencies = [ "ethers", "eyre", "fd-lock", + "flume", "futures", "itertools 0.12.1", "jubjub", @@ -5292,6 +5080,7 @@ dependencies = [ "rand 0.8.5", "rand_core 0.6.4", "regex", + "reqwest", "serde", "serde_json", "sha2 0.9.9", @@ -5313,7 +5102,7 @@ dependencies = [ name = "namada_shielded_token" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "lazy_static", "masp_primitives", "masp_proofs", @@ -5337,8 +5126,9 @@ name = "namada_state" version = "0.40.0" dependencies = [ "assert_matches", - "borsh 1.2.1", + "borsh", "chrono", + "clru", "itertools 0.12.1", "linkme", "namada_core", @@ -5364,7 +5154,7 @@ dependencies = [ name = "namada_storage" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "itertools 0.12.1", "linkme", "namada_core", @@ -5383,7 +5173,7 @@ dependencies = [ name = "namada_test_utils" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_core", "strum 0.24.1", ] @@ -5394,7 +5184,7 @@ version = "0.40.0" dependencies = [ "assert_cmd", "assert_matches", - "borsh 1.2.1", + "borsh", "borsh-ext", "color-eyre", "concat-idents", @@ -5440,7 +5230,7 @@ dependencies = [ name = "namada_token" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_core", "namada_events", "namada_macros", @@ -5469,7 +5259,7 @@ dependencies = [ "ark-bls12-381", "assert_matches", "bitflags 2.5.0", - "borsh 1.2.1", + "borsh", "data-encoding", "either", "konst", @@ -5507,7 +5297,7 @@ dependencies = [ name = "namada_tx_prelude" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "masp_primitives", "namada_account", "namada_core", @@ -5528,7 +5318,7 @@ dependencies = [ name = "namada_vm_env" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "masp_primitives", "namada_core", ] @@ -5537,7 +5327,7 @@ dependencies = [ name = "namada_vote_ext" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "data-encoding", "linkme", "namada_core", @@ -5565,7 +5355,7 @@ dependencies = [ name = "namada_vp_prelude" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_account", "namada_core", "namada_events", @@ -5582,6 +5372,15 @@ dependencies = [ "sha2 0.9.9", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.15", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -5800,7 +5599,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 2.0.52", @@ -5947,9 +5746,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec", @@ -5961,11 +5760,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -5979,9 +5778,9 @@ checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -6361,31 +6160,20 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml 0.5.11", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "toml_edit 0.20.2", ] [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.21.1", ] [[package]] @@ -6824,9 +6612,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", @@ -6853,6 +6641,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -7160,9 +6949,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "cfg-if", "derive_more", @@ -7172,11 +6961,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -7193,9 +6982,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "schemars_derive", @@ -7206,14 +6995,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -7348,15 +7137,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-json-wasm" -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" @@ -7409,13 +7189,13 @@ dependencies = [ [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -7711,7 +7491,7 @@ version = "0.3.1-pre" source = "git+https://github.com/heliaxdev/sparse-merkle-tree?rev=bab8cb96872db22cc9a139b2d3dfc4e00521d097#bab8cb96872db22cc9a139b2d3dfc4e00521d097" dependencies = [ "blake2b-rs", - "borsh 1.2.1", + "borsh", "cfg-if", "ics23", "itertools 0.12.1", @@ -7972,9 +7752,9 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b50aae6ec24c3429149ad59b5b8d3374d7804d4c7d6125ceb97cb53907fb68d" +checksum = "954496fbc9716eb4446cdd6d00c071a3e2f22578d62aa03b40c7e5b4fda3ed42" dependencies = [ "bytes", "digest 0.10.7", @@ -7996,30 +7776,30 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", "time", "zeroize", ] [[package]] name = "tendermint-config" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e07b383dc8780ebbec04cfb603f3fdaba6ea6663d8dd861425b1ffa7761fe90d" +checksum = "f84b11b57d20ee4492a1452faff85f5c520adc36ca9fe5e701066935255bb89f" dependencies = [ "flex-error", "serde", "serde_json", - "tendermint 0.36.0", + "tendermint 0.37.0", "toml 0.8.2", "url", ] [[package]] name = "tendermint-light-client" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331544139bbcf353acb5f56e733093d8e4bf2522cda0491b4bba7039ef0b944e" +checksum = "4faf208913acf562b8703e8e1e5eabdc57efa88c1404f9df20338a9969f08d6b" dependencies = [ "contracts", "crossbeam-channel", @@ -8032,7 +7812,7 @@ dependencies = [ "serde_derive", "serde_json", "static_assertions", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-light-client-verifier", "tendermint-rpc", "time", @@ -8042,14 +7822,14 @@ dependencies = [ [[package]] name = "tendermint-light-client-verifier" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4216e487165e5dbd7af79952eaa0d5f06c5bde861eb76c690acd7f2d2a19395c" +checksum = "3848090df4502a09ee27cb1a00f1835e1111c8993b22c5e1e41ffb7f6f09d57e" dependencies = [ "derive_more", "flex-error", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "time", ] @@ -8073,9 +7853,9 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f193d04afde6592c20fd70788a10b8cb3823091c07456db70d8a93f5fb99c1" +checksum = "dc87024548c7f3da479885201e3da20ef29e85a3b13d04606b380ac4c7120d87" dependencies = [ "bytes", "flex-error", @@ -8089,9 +7869,9 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e3c231a3632cab53f92ad4161c730c468c08cfe4f0aa5a6735b53b390aecbd" +checksum = "dfdc2281e271277fda184d96d874a6fe59f569b130b634289257baacfc95aa85" dependencies = [ "async-trait", "bytes", @@ -8108,9 +7888,9 @@ dependencies = [ "serde_json", "subtle", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-config", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", "thiserror", "time", "tokio", @@ -8122,9 +7902,9 @@ dependencies = [ [[package]] name = "tendermint-testgen" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b233cec83c56c413ccc346af866cb9206a14d468fcecf0255080107bc9b103c0" +checksum = "318a0e38b3b7b36b4078d78446d4284088aa9b173d519fc804c3ee4683972934" dependencies = [ "ed25519-consensus", "gumdrop", @@ -8132,7 +7912,7 @@ dependencies = [ "serde_json", "simple-error", "tempfile", - "tendermint 0.36.0", + "tendermint 0.37.0", "time", ] @@ -8488,9 +8268,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -8521,6 +8301,17 @@ dependencies = [ "winnow 0.5.25", ] +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.25", +] + [[package]] name = "tonic" version = "0.11.0" @@ -8584,16 +8375,16 @@ dependencies = [ [[package]] name = "tower-abci" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74290cdda37842bf92c7deb4e7742d087af864fe4f4953446156d72a7778a626" +checksum = "33b3ff634b4d50f220d9dd8bc21ca086d978ae327bb31ef4fd1c6682c897b0f0" dependencies = [ "bytes", "futures", "pin-project", "prost 0.12.3", - "tendermint 0.36.0", - "tendermint-proto 0.36.0", + "tendermint 0.37.0", + "tendermint-proto 0.37.0", "tokio", "tokio-stream", "tokio-util 0.6.10", @@ -8746,18 +8537,18 @@ dependencies = [ [[package]] name = "typed-builder" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47c0496149861b7c95198088cbf36645016b1a0734cf350c50e2a38e070f38a" +checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982ee4197351b5c9782847ef5ec1fdcaf50503fb19d68f9771adae314e72b492" +checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 6bb9135495..21c4bcc698 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,9 +110,9 @@ flate2 = "1.0.22" fs_extra = "1.2.0" futures = "0.3" git2 = { version = "0.18.1", default-features = false } -ibc = { version = "0.53.0", features = ["serde"] } -ibc-derive = "0.7.0" -ibc-testkit = { version = "0.53.0", default-features = false } +ibc = { git = "https://github.com/cosmos/ibc-rs", rev = "7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b", features = ["serde"] } +ibc-derive = { git = "https://github.com/cosmos/ibc-rs", rev = "7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" } +ibc-testkit = { git = "https://github.com/cosmos/ibc-rs", rev = "7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b", default-features = false } ics23 = "0.11.0" index-set = { git = "https://github.com/heliaxdev/index-set", tag = "v0.8.1", features = ["serialize-borsh", "serialize-serde"] } indexmap = { git = "https://github.com/heliaxdev/indexmap", tag = "2.2.4-heliax-1", features = ["borsh-schema", "serde"] } @@ -168,11 +168,11 @@ smooth-operator = {git = "https://github.com/heliaxdev/smooth-operator", tag = " sysinfo = {version = "0.27.8", default-features = false} tar = "0.4.37" tempfile = {version = "3.2.0"} -tendermint = {version = "0.36.0", features = ["secp256k1"]} -tendermint-config = "0.36.0" -tendermint-light-client = "0.36.0" -tendermint-proto = "0.36.0" -tendermint-rpc = {version = "0.36.0", default-features = false} +tendermint = {version = "0.37.0", features = ["secp256k1"]} +tendermint-config = "0.37.0" +tendermint-light-client = "0.37.0" +tendermint-proto = "0.37.0" +tendermint-rpc = {version = "0.37.0", default-features = false} test-log = {version = "0.2.14", default-features = false, features = ["trace"]} tiny-bip39 = {git = "https://github.com/anoma/tiny-bip39.git", rev = "bf0f6d8713589b83af7a917366ec31f5275c0e57"} tiny-hderive = {git = "https://github.com/heliaxdev/tiny-hderive.git", rev = "173ae03abed0cd25d88a5a13efac00af96b75b87"} @@ -184,7 +184,7 @@ toml = "0.5.8" tonic = "0.8.3" tonic-build = "0.11.0" tower = "0.4" -tower-abci = "0.14.0" +tower-abci = "0.15.0" tracing = "0.1.30" tracing-appender = "0.2.2" tracing-log = "0.2.0" diff --git a/crates/apps_lib/src/cli.rs b/crates/apps_lib/src/cli.rs index 2ddab6dfb4..74b387db14 100644 --- a/crates/apps_lib/src/cli.rs +++ b/crates/apps_lib/src/cli.rs @@ -3213,8 +3213,6 @@ pub mod args { Err(_) => config::get_default_namada_folder(), }), ); - pub const BATCH_SIZE_OPT: ArgDefault = - arg_default("batch-size", DefaultFn(|| 1)); pub const BLOCK_HEIGHT: Arg = arg("block-height"); pub const BLOCK_HEIGHT_OPT: ArgOpt = arg_opt("height"); pub const BLOCK_HEIGHT_FROM_OPT: ArgOpt = @@ -3468,6 +3466,7 @@ pub mod args { pub const WASM_CHECKSUMS_PATH: Arg = arg("wasm-checksums-path"); pub const WASM_DIR: ArgOpt = arg_opt("wasm-dir"); pub const WEBSITE_OPT: ArgOpt = arg_opt("website"); + pub const WITH_INDEXER: ArgOpt = arg_opt("with-indexer"); pub const TX_PATH: Arg = arg("tx-path"); pub const TX_PATH_OPT: ArgOpt = TX_PATH.opt(); @@ -6575,27 +6574,23 @@ pub mod args { impl Args for ShieldedSync { fn parse(matches: &ArgMatches) -> Self { let ledger_address = CONFIG_RPC_LEDGER_ADDRESS.parse(matches); - let batch_size = BATCH_SIZE_OPT.parse(matches); let start_query_height = BLOCK_HEIGHT_FROM_OPT.parse(matches); let last_query_height = BLOCK_HEIGHT_TO_OPT.parse(matches); let spending_keys = SPENDING_KEYS.parse(matches); let viewing_keys = VIEWING_KEYS.parse(matches); + let with_indexer = WITH_INDEXER.parse(matches); Self { ledger_address, - batch_size, start_query_height, last_query_height, spending_keys, viewing_keys, + with_indexer, } } fn def(app: App) -> App { app.arg(CONFIG_RPC_LEDGER_ADDRESS.def().help(LEDGER_ADDRESS_ABOUT)) - .arg(BATCH_SIZE_OPT.def().help(wrap!( - "Optional batch size which determines how many txs to \ - fetch before caching locally. Default is 1." - ))) .arg(BLOCK_HEIGHT_TO_OPT.def().help(wrap!( "Option block height to sync up to. Default is latest." ))) @@ -6612,6 +6607,11 @@ pub mod args { "List of new viewing keys with which to check note \ ownership. These will be added to the shielded context." ))) + .arg(WITH_INDEXER.def().help(wrap!( + "Address of a `namada-masp-indexer` live instance. If \ + present, the shielded sync will be performed using data \ + retrieved from the given indexer." + ))) } } @@ -6626,7 +6626,6 @@ pub mod args { Ok(ShieldedSync { ledger_address: chain_ctx.get(&self.ledger_address), - batch_size: self.batch_size, start_query_height: self.start_query_height, last_query_height: self.last_query_height, spending_keys: self @@ -6639,6 +6638,7 @@ pub mod args { .iter() .map(|vk| chain_ctx.get_cached(vk)) .collect(), + with_indexer: self.with_indexer.map(|_| ()), }) } } @@ -6962,6 +6962,7 @@ pub mod args { type Data = PathBuf; type EthereumAddress = String; type Keypair = WalletKeypair; + type MaspIndexerAddress = String; type PaymentAddress = WalletPaymentAddr; type PublicKey = WalletPublicKey; type SpendingKey = WalletSpendingKey; diff --git a/crates/apps_lib/src/cli/client.rs b/crates/apps_lib/src/cli/client.rs index 24ed0981ff..00120acf97 100644 --- a/crates/apps_lib/src/cli/client.rs +++ b/crates/apps_lib/src/cli/client.rs @@ -12,7 +12,7 @@ use crate::cli::cmds::*; use crate::client::{rpc, tx, utils}; impl CliApi { - pub async fn handle_client_command( + pub async fn handle_client_command( client: Option, cmd: cli::NamadaClient, io: IO, @@ -336,13 +336,16 @@ impl CliApi { tx::submit_validator_metadata_change(&namada, args) .await?; } - Sub::ShieldedSync(ShieldedSync(args)) => { + Sub::ShieldedSync(ShieldedSync(mut args)) => { + let indexer_addr = args.with_indexer.take(); let args = args.to_sdk(&mut ctx)?; let chain_ctx = ctx.take_chain_or_exit(); let client = client.unwrap_or_else(|| { C::from_tendermint_address(&args.ledger_address) }); - client.wait_until_node_is_synced(&io).await?; + if indexer_addr.is_none() { + client.wait_until_node_is_synced(&io).await?; + } let vks = chain_ctx .wallet .get_viewing_keys() @@ -361,8 +364,8 @@ impl CliApi { crate::client::masp::syncing( chain_ctx.shielded, &client, + indexer_addr.as_ref().map(|s| s.as_ref()), &io, - args.batch_size, args.start_query_height, args.last_query_height, &sks, diff --git a/crates/apps_lib/src/client/masp.rs b/crates/apps_lib/src/client/masp.rs index 983be6d718..29e30ee246 100644 --- a/crates/apps_lib/src/client/masp.rs +++ b/crates/apps_lib/src/client/masp.rs @@ -1,14 +1,17 @@ use std::fmt::Debug; +use std::sync::{Arc, Mutex}; +use std::time::Duration; use color_eyre::owo_colors::OwoColorize; use masp_primitives::sapling::ViewingKey; use masp_primitives::zip32::ExtendedSpendingKey; use namada_sdk::error::Error; use namada_sdk::io::Io; -use namada_sdk::masp::{ - IndexedNoteEntry, ProgressLogger, ProgressType, ShieldedContext, - ShieldedUtils, +use namada_sdk::masp::utils::{ + IndexerMaspClient, LedgerMaspClient, PeekableIter, ProgressTracker, + ProgressType, RetryStrategy, }; +use namada_sdk::masp::{IndexedNoteEntry, ShieldedContext, ShieldedUtils}; use namada_sdk::queries::Client; use namada_sdk::storage::BlockHeight; use namada_sdk::{display, display_line, MaybeSend, MaybeSync}; @@ -17,148 +20,281 @@ use namada_sdk::{display, display_line, MaybeSend, MaybeSync}; pub async fn syncing< U: ShieldedUtils + MaybeSend + MaybeSync, C: Client + Sync, - IO: Io, + IO: Io + Send + Sync, >( mut shielded: ShieldedContext, client: &C, + indexer_addr: Option<&str>, io: &IO, - batch_size: u64, start_query_height: Option, last_query_height: Option, sks: &[ExtendedSpendingKey], fvks: &[ViewingKey], ) -> Result, Error> { - let shutdown_signal = async { - let (tx, rx) = tokio::sync::oneshot::channel(); - namada_sdk::control_flow::shutdown_send(tx).await; - rx.await - }; - - display_line!(io, "{}", "==== Shielded sync started ====".on_white()); + if indexer_addr.is_some() { + display_line!( + io, + "{}", + "==== Shielded sync started using indexer client ====".bold() + ); + } else { + display_line!( + io, + "{}", + "==== Shielded sync started using ledger client ====".bold() + ); + } display_line!(io, "\n\n"); - let logger = CliLogger::new(io); - let sync = async move { - shielded - .fetch( - client, - &logger, - start_query_height, - last_query_height, - batch_size, - sks, - fvks, - ) - .await - .map(|_| shielded) - }; - tokio::select! { - sync = sync => { - let shielded = sync?; - display!(io, "Syncing finished\n"); - Ok(shielded) - }, - sig = shutdown_signal => { - sig.map_err(|e| Error::Other(e.to_string()))?; - display!(io, "\n"); - Ok(ShieldedContext::default()) - }, + let tracker = CliProgressTracker::new(io); + + macro_rules! dispatch_client { + ($client:expr) => { + shielded + .fetch( + $client, + &tracker, + start_query_height, + last_query_height, + RetryStrategy::Forever, + sks, + fvks, + ) + .await + .map(|_| shielded) + }; } + + let shielded = if let Some(endpoint) = indexer_addr { + let client = reqwest::Client::builder() + .connect_timeout(Duration::from_secs(60)) + .build() + .map_err(|err| { + Error::Other(format!("Failed to build http client: {err}")) + })?; + let url = endpoint.try_into().map_err(|err| { + Error::Other(format!( + "Failed to parse API endpoint {endpoint:?}: {err}" + )) + })?; + dispatch_client!(IndexerMaspClient::new(client, url))? + } else { + dispatch_client!(LedgerMaspClient::new(client))? + }; + + display!(io, "Syncing finished\n"); + Ok(shielded) } -pub struct CliLogging<'io, T, IO: Io> { - items: Vec, +/// The amount of progress a shielded sync sub-process has made +#[derive(Default, Copy, Clone, Debug)] +struct IterProgress { index: usize, length: usize, +} + +pub struct LoggingIterator<'io, T, I, IO> +where + T: Debug, + I: Iterator, + IO: Io, +{ + items: I, + progress: Arc>, io: &'io IO, r#type: ProgressType, + peeked: Option, + #[cfg(not(unix))] + num_logs_counter: usize, } -impl<'io, T: Debug, IO: Io> CliLogging<'io, T, IO> { - fn new(items: I, io: &'io IO, r#type: ProgressType) -> Self - where - I: IntoIterator, - { - let items: Vec<_> = items.into_iter().collect(); +impl<'io, T, I, IO> LoggingIterator<'io, T, I, IO> +where + T: Debug, + I: Iterator, + IO: Io, +{ + fn new( + items: I, + io: &'io IO, + r#type: ProgressType, + progress: Arc>, + ) -> Self { + let (size, _) = items.size_hint(); + { + let mut locked = progress.lock().unwrap(); + locked.length = size; + } Self { - length: items.len(), items, - index: 0, + progress, io, r#type, + peeked: None, + #[cfg(not(unix))] + num_logs_counter: 0, } } -} -impl<'io, T: Debug, IO: Io> Iterator for CliLogging<'io, T, IO> { - type Item = T; + fn advance_index(&mut self) { + let mut locked = self.progress.lock().unwrap(); + locked.index += 1; + if let ProgressType::Scan = self.r#type { + locked.length = self.items.size_hint().0; + } + } +} - fn next(&mut self) -> Option { - if self.index == 0 { - self.items = { - let mut new_items = vec![]; - std::mem::swap(&mut new_items, &mut self.items); - new_items.into_iter().rev().collect() - }; +impl<'io, T, I, IO> PeekableIter for LoggingIterator<'io, T, I, IO> +where + T: Debug, + I: Iterator, + IO: Io, +{ + fn peek(&mut self) -> Option<&T> { + if self.peeked.is_none() { + self.peeked = self.items.next(); } - if self.items.is_empty() { - return None; + self.peeked.as_ref() + } + + fn next(&mut self) -> Option { + self.peek(); + let next_item = self.peeked.take()?; + self.advance_index(); + + #[cfg(not(unix))] + { + if self.num_logs_counter % 20 != 0 { + return Some(next_item); + } } - self.index += 1; - let percent = (100 * self.index) / self.length; + + let (index, length) = { + let locked = self.progress.lock().unwrap(); + (locked.length, locked.index) + }; + + let percent = std::cmp::min(100, (100 * index) / length); let completed: String = vec!['#'; percent].iter().collect(); let incomplete: String = vec!['.'; 100 - percent].iter().collect(); - display_line!(self.io, "\x1b[2A\x1b[J"); + + #[cfg(unix)] + { + clear_last_lines(self.io, 2); + } + match self.r#type { ProgressType::Fetch => display_line!( self.io, "Fetched block {:?} of {:?}", - self.items.last().unwrap(), - self.items[0] - ), - ProgressType::Scan => display_line!( - self.io, - "Scanning {} of {}", - self.index, - self.length + index, + length ), + ProgressType::Scan => { + display_line!(self.io, "Scanning {} of {}", index, length) + } } display!(self.io, "[{}{}] ~~ {} %", completed, incomplete, percent); + + #[cfg(not(unix))] + { + self.num_logs_counter += 1; + display_line!(self.io, "\n"); + } + self.io.flush(); - self.items.pop() + Some(next_item) + } +} + +#[cfg(unix)] +fn clear_last_lines(io: &IO, num_lines: usize) { + display_line!(io, "\x1b[{num_lines}A\x1b[J"); +} + +impl<'io, T, I, IO> Drop for LoggingIterator<'io, T, I, IO> +where + T: Debug, + I: Iterator, + IO: Io, +{ + fn drop(&mut self) { + display_line!(self.io, "\x1b[2A\x1b[J"); + } +} + +impl<'io, T, I, IO> Iterator for LoggingIterator<'io, T, I, IO> +where + T: Debug, + I: Iterator, + IO: Io, +{ + type Item = T; + + fn next(&mut self) -> Option { + >::next(self) } } /// A progress logger for the CLI #[derive(Debug, Clone)] -pub struct CliLogger<'io, IO: Io> { +pub struct CliProgressTracker<'io, IO: Io> { io: &'io IO, + fetch: Arc>, + scan: Arc>, } -impl<'io, IO: Io> CliLogger<'io, IO> { +impl<'io, IO: Io> CliProgressTracker<'io, IO> { pub fn new(io: &'io IO) -> Self { - Self { io } + Self { + io, + fetch: Arc::new(Mutex::new(IterProgress::default())), + scan: Arc::new(Mutex::new(IterProgress::default())), + } } } -impl<'io, IO: Io> ProgressLogger for CliLogger<'io, IO> { - type Fetch = CliLogging<'io, u64, IO>; - type Scan = CliLogging<'io, IndexedNoteEntry, IO>; - +impl<'io, IO: Io + Send + Sync> ProgressTracker + for CliProgressTracker<'io, IO> +{ fn io(&self) -> &IO { self.io } - fn fetch(&self, items: I) -> Self::Fetch + fn fetch(&self, items: I) -> impl PeekableIter where - I: IntoIterator, + I: Iterator, { - CliLogging::new(items, self.io, ProgressType::Fetch) + LoggingIterator::new( + items, + self.io, + ProgressType::Fetch, + self.fetch.clone(), + ) } - fn scan(&self, items: I) -> Self::Scan + fn scan(&self, items: I) -> impl Iterator + Send where - I: IntoIterator, + I: Iterator + Send, { - CliLogging::new(items, self.io, ProgressType::Scan) + { + let mut locked = self.scan.lock().unwrap(); + *locked = IterProgress::default(); + } + LoggingIterator::new( + items, + self.io, + ProgressType::Scan, + self.scan.clone(), + ) + } + + fn left_to_fetch(&self) -> usize { + let locked = self.fetch.lock().unwrap(); + if locked.index > locked.length { + 0 + } else { + locked.length - locked.index + } } } diff --git a/crates/core/src/hash.rs b/crates/core/src/hash.rs index 99905167c7..8caea1bc4b 100644 --- a/crates/core/src/hash.rs +++ b/crates/core/src/hash.rs @@ -29,6 +29,8 @@ pub enum Error { ConversionFailed(std::array::TryFromSliceError), #[error("Failed to convert string into a hash: {0}")] FromStringError(data_encoding::DecodeError), + #[error("Cannot convert an empty CometBFT hash")] + FromCometError, } /// Result for functions that may fail @@ -178,6 +180,17 @@ impl From for crate::tendermint::Hash { } } +impl TryFrom for Hash { + type Error = self::Error; + + fn try_from(value: crate::tendermint::Hash) -> Result { + match value { + crate::tendermint::Hash::Sha256(hash) => Ok(Self(hash)), + crate::tendermint::Hash::None => Err(Error::FromCometError), + } + } +} + impl From for H256 { fn from(hash: Hash) -> Self { hash.0.into() diff --git a/crates/core/src/ibc.rs b/crates/core/src/ibc.rs index fe29f61fe7..4f88c57c89 100644 --- a/crates/core/src/ibc.rs +++ b/crates/core/src/ibc.rs @@ -1,5 +1,6 @@ //! IBC-related data types +use std::fmt::Display; use std::str::FromStr; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; @@ -11,6 +12,7 @@ use namada_migrations::*; use serde::{Deserialize, Serialize}; use super::address::HASH_LEN; +use crate::hash::Hash; /// IBC token hash derived from a denomination. #[derive( @@ -47,3 +49,24 @@ impl FromStr for IbcTokenHash { Ok(IbcTokenHash(output)) } } + +/// IBC transaction data section hash +pub type IbcTxDataHash = Hash; + +/// IBC transaction data references to retrieve IBC messages +#[derive(Default, Clone, Serialize, Deserialize)] +pub struct IbcTxDataRefs(pub Vec); + +impl Display for IbcTxDataRefs { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", serde_json::to_string(self).unwrap()) + } +} + +impl FromStr for IbcTxDataRefs { + type Err = serde_json::Error; + + fn from_str(s: &str) -> Result { + serde_json::from_str(s) + } +} diff --git a/crates/events/src/extend.rs b/crates/events/src/extend.rs index 2ebf5ed5e3..5e68fd8126 100644 --- a/crates/events/src/extend.rs +++ b/crates/events/src/extend.rs @@ -8,6 +8,7 @@ use std::str::FromStr; use namada_core::address::Address; use namada_core::collections::HashMap; use namada_core::hash::Hash; +use namada_core::ibc::IbcTxDataRefs; use namada_core::masp::MaspTxRefs; use namada_core::storage::{BlockHeight, TxIndex}; use serde::Deserializer; @@ -517,6 +518,20 @@ impl EventAttributeEntry<'static> for MaspTxBatchRefs { } } +/// Extend an [`Event`] with data sections for IBC shielding transfer. +pub struct IbcMaspTxBatchRefs(pub IbcTxDataRefs); + +impl EventAttributeEntry<'static> for IbcMaspTxBatchRefs { + type Value = IbcTxDataRefs; + type ValueOwned = Self::Value; + + const KEY: &'static str = "ibc_masp_tx_batch_refs"; + + fn into_value(self) -> Self::Value { + self.0 + } +} + /// Extend an [`Event`] with success data. pub struct Success(pub bool); diff --git a/crates/gas/src/event.rs b/crates/gas/src/event.rs index d76889fece..340e59a9a0 100644 --- a/crates/gas/src/event.rs +++ b/crates/gas/src/event.rs @@ -2,13 +2,13 @@ use namada_events::extend::EventAttributeEntry; -use super::Gas; +use crate::WholeGas; /// Extend an [`namada_events::Event`] with gas used data. -pub struct GasUsed(pub Gas); +pub struct GasUsed(pub WholeGas); impl EventAttributeEntry<'static> for GasUsed { - type Value = Gas; + type Value = WholeGas; type ValueOwned = Self::Value; const KEY: &'static str = "gas_used"; diff --git a/crates/gas/src/lib.rs b/crates/gas/src/lib.rs index 57468a2e8e..f404df7ee8 100644 --- a/crates/gas/src/lib.rs +++ b/crates/gas/src/lib.rs @@ -116,9 +116,10 @@ pub const MASP_PARALLEL_GAS_DIVIDER: u64 = PARALLEL_GAS_DIVIDER / 2; /// Gas module result for functions that may fail pub type Result = std::result::Result; -/// Representation of gas in sub-units. This effectively decouples gas metering -/// from fee payment, allowing higher resolution when accounting for gas while, -/// at the same time, providing a contained gas value when paying fees. +/// Representation of tracking gas in sub-units. This effectively decouples gas +/// metering from fee payment, allowing higher resolution when accounting for +/// gas while, at the same time, providing a contained gas value when paying +/// fees. #[derive( Clone, Copy, @@ -154,8 +155,8 @@ impl Gas { } /// Converts the sub gas units to whole ones. If the sub units are not a - /// multiple of the `SCALE` than ceil the quotient - pub fn get_whole_gas_units(&self, scale: u64) -> u64 { + /// multiple of the scale than ceil the quotient + pub fn get_whole_gas_units(&self, scale: u64) -> WholeGas { let quotient = self .sub .checked_div(scale) @@ -166,18 +167,18 @@ impl Gas { .expect("Gas quotient remainder should not overflow") == 0 { - quotient + quotient.into() } else { quotient .checked_add(1) .expect("Cannot overflow as the quotient is scaled down u64") + .into() } } - /// Generates a `Gas` instance from a whole amount - pub fn from_whole_units(whole: u64, scale: u64) -> Option { - let sub = whole.checked_mul(scale)?; - Some(Self { sub }) + /// Generates a `Gas` instance from a `WholeGas` amount + pub fn from_whole_units(whole: WholeGas, scale: u64) -> Option { + scale.checked_mul(whole.into()).map(|sub| Self { sub }) } } @@ -193,20 +194,46 @@ impl From for u64 { } } -impl Display for Gas { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - // Need to do this now that the gas scale is a parameter. Should - // manually scale gas first before calling this - write!(f, "{}", self.sub) +/// Gas represented in whole units. Used for fee payment and to display +/// information to the user. +#[derive( + Debug, + Clone, + Copy, + PartialEq, + BorshSerialize, + BorshDeserialize, + BorshDeserializer, + BorshSchema, + Serialize, + Deserialize, + Eq, +)] +pub struct WholeGas(u64); + +impl From for WholeGas { + fn from(amount: u64) -> WholeGas { + Self(amount) } } -impl FromStr for Gas { +impl From for u64 { + fn from(whole: WholeGas) -> u64 { + whole.0 + } +} + +impl FromStr for WholeGas { type Err = GasParseError; fn from_str(s: &str) -> std::result::Result { - let raw: u64 = s.parse().map_err(GasParseError::Parse)?; - Ok(Self { sub: raw }) + Ok(Self(s.parse().map_err(GasParseError::Parse)?)) + } +} + +impl Display for WholeGas { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) } } diff --git a/crates/governance/src/storage/proposal.rs b/crates/governance/src/storage/proposal.rs index 3ee6113088..3cdf7c65e7 100644 --- a/crates/governance/src/storage/proposal.rs +++ b/crates/governance/src/storage/proposal.rs @@ -1,7 +1,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::fmt::Display; -use borsh::{BorshDeserialize, BorshSerialize}; +use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use itertools::Itertools; use namada_core::address::Address; use namada_core::hash::Hash; @@ -33,6 +33,7 @@ pub enum ProposalError { Debug, Clone, PartialEq, + BorshSchema, BorshSerialize, BorshDeserialize, BorshDeserializer, @@ -69,6 +70,7 @@ impl InitProposalData { Debug, Clone, PartialEq, + BorshSchema, BorshSerialize, BorshDeserialize, BorshDeserializer, @@ -191,6 +193,7 @@ impl StoragePgfFunding { Debug, Clone, PartialEq, + BorshSchema, BorshSerialize, BorshDeserialize, BorshDeserializer, @@ -221,6 +224,7 @@ pub enum ProposalType { Eq, PartialOrd, Ord, + BorshSchema, BorshSerialize, BorshDeserialize, Serialize, @@ -250,6 +254,7 @@ where Debug, Clone, PartialEq, + BorshSchema, BorshSerialize, BorshDeserialize, BorshDeserializer, @@ -303,6 +308,7 @@ impl Display for PGFTarget { Debug, Clone, PartialEq, + BorshSchema, BorshSerialize, BorshDeserialize, BorshDeserializer, @@ -413,6 +419,7 @@ impl borsh::BorshSchema for PGFIbcTarget { Debug, Clone, PartialEq, + BorshSchema, BorshSerialize, BorshDeserialize, BorshDeserializer, diff --git a/crates/governance/src/storage/vote.rs b/crates/governance/src/storage/vote.rs index 01327a3960..ef0129011f 100644 --- a/crates/governance/src/storage/vote.rs +++ b/crates/governance/src/storage/vote.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use borsh::{BorshDeserialize, BorshSerialize}; +use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use namada_macros::BorshDeserializer; #[cfg(feature = "migrations")] use namada_migrations::*; @@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize}; Debug, Clone, PartialEq, + BorshSchema, BorshSerialize, BorshDeserialize, BorshDeserializer, diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index 9037d70f22..72a9101792 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -443,6 +443,12 @@ pub fn received_ibc_token( pub mod testing { use std::str::FromStr; + use ibc::apps::nft_transfer::types::msgs::transfer::MsgTransfer as MsgNftTransfer; + use ibc::apps::nft_transfer::types::packet::PacketData as NftPacketData; + use ibc::apps::nft_transfer::types::{ + ClassData, ClassId, ClassUri, Memo as NftMemo, PrefixedClassId, + TokenData, TokenId, TokenIds, TokenUri, + }; use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; use ibc::apps::transfer::types::packet::PacketData; use ibc::apps::transfer::types::{ @@ -456,7 +462,7 @@ pub mod testing { use ibc::primitives::proto::Any; use ibc::primitives::{Timestamp, ToProto}; use proptest::prelude::{Just, Strategy}; - use proptest::{collection, prop_compose, prop_oneof}; + use proptest::{collection, option, prop_compose, prop_oneof}; prop_compose! { /// Generate an arbitrary port ID @@ -505,6 +511,13 @@ pub mod testing { } } + prop_compose! { + /// Generate an arbitrary IBC NFT memo + pub fn arb_ibc_nft_memo()(memo in "[a-zA-Z0-9_]*") -> NftMemo { + memo.into() + } + } + prop_compose! { /// Generate an arbitrary IBC memo pub fn arb_ibc_signer()(signer in "[a-zA-Z0-9_]*") -> Signer { @@ -605,10 +618,116 @@ pub mod testing { } } + prop_compose! { + /// Generate an arbitrary IBC token ID + pub fn arb_ibc_token_id()(token_id in "[a-zA-Z0-9_]+") -> TokenId { + TokenId::from_str(&token_id).expect("generated invalid IBC token ID") + } + } + + prop_compose! { + /// Generate an arbitrary IBC token ID vector + pub fn arb_ibc_token_ids()(token_ids in collection::vec(arb_ibc_token_id(), 1..10)) -> TokenIds { + TokenIds(token_ids) + } + } + + prop_compose! { + /// Generate arbitrary IBC class data + pub fn arb_ibc_class_data()(class_data in "[a-zA-Z0-9_]*") -> ClassData { + ClassData::from_str(&class_data).expect("generated invalid IBC class data") + } + } + + prop_compose! { + /// Generate an arbitrary IBC class ID + pub fn arb_ibc_class_id()(token_id in "[a-zA-Z0-9_]+") -> ClassId { + ClassId::from_str(&token_id).expect("generated invalid IBC class ID") + } + } + + prop_compose! { + /// Generate an arbitrary IBC prefixed class ID + pub fn arb_ibc_prefixed_class_id()( + trace_path in arb_ibc_trace_path(), + base_class_id in arb_ibc_class_id(), + ) -> PrefixedClassId { + PrefixedClassId { + trace_path, + base_class_id, + } + } + } + + prop_compose! { + /// Generate arbitrary IBC token data + pub fn arb_ibc_token_data()( + token_data in "[a-zA-Z0-9_]*", + ) -> TokenData { + TokenData::from_str(&token_data).expect("generated invalid IBC token data") + } + } + + // An arbitrary URI for the tests. Generating random URIs would not increase + // test coverage since they are encoded as length-prefixed strings. + const ARBITRARY_URI: &str = "https://namada.net/#ibc-interoperability"; + + prop_compose! { + /// Generate arbitrary NFT packet data + pub fn arb_ibc_nft_packet_data()( + token_ids in arb_ibc_token_ids(), + token_uri in Just(TokenUri::from_str(ARBITRARY_URI).unwrap()), + )( + sender in arb_ibc_signer(), + receiver in arb_ibc_signer(), + memo in option::of(arb_ibc_nft_memo()), + class_data in option::of(arb_ibc_class_data()), + class_id in arb_ibc_prefixed_class_id(), + class_uri in option::of(Just(ClassUri::from_str(ARBITRARY_URI).unwrap())), + token_uris in option::of(collection::vec(Just(token_uri), token_ids.0.len())), + token_data in option::of(collection::vec(arb_ibc_token_data(), token_ids.0.len())), + token_ids in Just(token_ids), + ) -> NftPacketData { + NftPacketData { + token_ids, + sender, + receiver, + memo, + class_data, + class_id, + class_uri, + token_uris, + token_data, + } + } + } + + prop_compose! { + /// Generate an arbitrary IBC NFT transfer message + pub fn arb_ibc_msg_nft_transfer()( + port_id_on_a in arb_ibc_port_id(), + chan_id_on_a in arb_ibc_channel_id(), + packet_data in arb_ibc_nft_packet_data(), + timeout_height_on_b in arb_ibc_timeout_data(), + timeout_timestamp_on_b in arb_ibc_timestamp(), + ) -> MsgNftTransfer { + MsgNftTransfer { + port_id_on_a, + chan_id_on_a, + packet_data, + timeout_height_on_b, + timeout_timestamp_on_b, + } + } + } + prop_compose! { /// Generate an arbitrary IBC any object - pub fn arb_ibc_any()(msg_transfer in arb_ibc_msg_transfer()) -> Any { - msg_transfer.to_any() + pub fn arb_ibc_any()(any in prop_oneof![ + arb_ibc_msg_transfer().prop_map(|x| x.to_any()), + arb_ibc_msg_nft_transfer().prop_map(|x| x.to_any()), + ]) -> Any { + any } } } diff --git a/crates/ibc/src/msg.rs b/crates/ibc/src/msg.rs index d3a32330f1..38705213c7 100644 --- a/crates/ibc/src/msg.rs +++ b/crates/ibc/src/msg.rs @@ -1,4 +1,7 @@ -use borsh::{BorshDeserialize, BorshSerialize}; +use std::collections::BTreeMap; + +use borsh::schema::{Declaration, Definition, Fields}; +use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use data_encoding::HEXUPPER; use ibc::apps::nft_transfer::types::msgs::transfer::MsgTransfer as IbcMsgNftTransfer; use ibc::apps::nft_transfer::types::packet::PacketData as NftPacketData; @@ -59,6 +62,22 @@ impl BorshDeserialize for MsgTransfer { } } +impl BorshSchema for MsgTransfer { + fn add_definitions_recursively( + definitions: &mut BTreeMap, + ) { + <(Vec, Option)>::add_definitions_recursively(definitions); + let fields = Fields::UnnamedFields(vec![ + <(Vec, Option)>::declaration(), + ]); + definitions.insert(Self::declaration(), Definition::Struct { fields }); + } + + fn declaration() -> Declaration { + "MsgTransfer".into() + } +} + /// IBC NFT transfer message with `Transfer` #[derive(Debug, Clone)] pub struct MsgNftTransfer { @@ -92,6 +111,22 @@ impl BorshDeserialize for MsgNftTransfer { } } +impl BorshSchema for MsgNftTransfer { + fn add_definitions_recursively( + definitions: &mut BTreeMap, + ) { + <(Vec, Option)>::add_definitions_recursively(definitions); + let fields = Fields::UnnamedFields(vec![ + <(Vec, Option)>::declaration(), + ]); + definitions.insert(Self::declaration(), Definition::Struct { fields }); + } + + fn declaration() -> Declaration { + "MsgNftTransfer".into() + } +} + /// Shielding data in IBC packet memo #[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] pub struct IbcShieldingData { diff --git a/crates/light_sdk/src/reading/asynchronous/tx.rs b/crates/light_sdk/src/reading/asynchronous/tx.rs index 57e79ea49b..c14d674644 100644 --- a/crates/light_sdk/src/reading/asynchronous/tx.rs +++ b/crates/light_sdk/src/reading/asynchronous/tx.rs @@ -1,6 +1,6 @@ use namada_sdk::events::Event; use namada_sdk::rpc::{TxEventQuery, TxResponse}; -use namada_sdk::tx::data::TxResult; +use namada_sdk::tx::data::DryRunResult; use super::*; @@ -25,7 +25,7 @@ pub async fn query_tx_events( pub async fn dry_run_tx( tendermint_addr: &str, tx_bytes: Vec, -) -> Result, Error> { +) -> Result { let client = HttpClient::new( TendermintAddress::from_str(tendermint_addr) .map_err(|e| Error::Other(e.to_string()))?, diff --git a/crates/light_sdk/src/reading/blocking/tx.rs b/crates/light_sdk/src/reading/blocking/tx.rs index 6e98d9adb2..27aa61ef40 100644 --- a/crates/light_sdk/src/reading/blocking/tx.rs +++ b/crates/light_sdk/src/reading/blocking/tx.rs @@ -26,7 +26,7 @@ pub fn query_tx_events( pub fn dry_run_tx( tendermint_addr: &str, tx_bytes: Vec, -) -> Result { +) -> Result { let client = HttpClient::new( TendermintAddress::from_str(tendermint_addr) .map_err(|e| Error::Other(e.to_string()))?, diff --git a/crates/namada/src/ledger/mod.rs b/crates/namada/src/ledger/mod.rs index 71304bc1e8..0211de33ff 100644 --- a/crates/namada/src/ledger/mod.rs +++ b/crates/namada/src/ledger/mod.rs @@ -25,7 +25,7 @@ mod dry_run_tx { use namada_sdk::queries::{EncodedResponseQuery, RequestCtx, RequestQuery}; use namada_state::{DBIter, ResultExt, StorageHasher, DB}; - use namada_tx::data::{ExtendedTxResult, GasLimit, TxResult}; + use namada_tx::data::{DryRunResult, ExtendedTxResult, GasLimit, TxResult}; use super::protocol; use crate::vm::wasm::{TxCache, VpCache}; @@ -109,15 +109,17 @@ mod dry_run_tx { let ExtendedTxResult { mut tx_result, ref masp_tx_refs, - is_ibc_shielding: _, + ref ibc_tx_data_refs, } = extended_tx_result; let tx_gas_meter = RefCell::new(tx_gas_meter); - for cmt in - crate::ledger::protocol::get_batch_txs_to_execute(&tx, masp_tx_refs) - { + for cmt in crate::ledger::protocol::get_batch_txs_to_execute( + &tx, + masp_tx_refs, + ibc_tx_data_refs, + ) { let batched_tx = tx.batch_ref_tx(cmt); let batched_tx_result = protocol::apply_wasm_tx( - batched_tx, + &batched_tx, &TxIndex(0), ShellParams::new( &tx_gas_meter, @@ -132,18 +134,22 @@ mod dry_run_tx { } else { temp_state.write_log_mut().drop_tx(); } - tx_result.batch_results.insert_inner_tx_result( + tx_result.insert_inner_tx_result( wrapper_hash.as_ref(), either::Right(cmt), batched_tx_result, ); } // Account gas for both batch and wrapper - tx_result.gas_used = tx_gas_meter.borrow().get_tx_consumed_gas(); + let gas_used = tx_gas_meter + .borrow() + .get_tx_consumed_gas() + .get_whole_gas_units(gas_scale); let tx_result_string = tx_result.to_result_string(); - let data = tx_result_string.serialize_to_vec(); + let dry_run_result = DryRunResult(tx_result_string, gas_used); + Ok(EncodedResponseQuery { - data, + data: dry_run_result.serialize_to_vec(), proof: None, info: Default::default(), height: ctx.state.in_mem().get_last_block_height(), @@ -331,7 +337,7 @@ mod test { assert!( result .data - .batch_results + .0 .get_inner_tx_result(None, either::Right(cmt)) .unwrap() .as_ref() diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs index 97616f3b34..ac91c74730 100644 --- a/crates/namada/src/ledger/protocol/mod.rs +++ b/crates/namada/src/ledger/protocol/mod.rs @@ -3,9 +3,11 @@ use std::cell::RefCell; use std::collections::BTreeSet; use std::fmt::Debug; +use either::Either; use eyre::{eyre, WrapErr}; use namada_core::booleans::BoolResultUnitExt; use namada_core::hash::Hash; +use namada_core::ibc::{IbcTxDataHash, IbcTxDataRefs}; use namada_core::masp::{MaspTxRefs, TxId}; use namada_events::extend::{ ComposeEvent, Height as HeightAttr, TxHash as TxHashAttr, UserAccount, @@ -16,11 +18,11 @@ use namada_parameters::get_gas_scale; use namada_state::TxWrites; use namada_token::event::{TokenEvent, TokenOperation}; use namada_token::utils::is_masp_transfer; -use namada_tx::action::Read; +use namada_tx::action::{is_ibc_shielding_transfer, Read}; use namada_tx::data::protocol::{ProtocolTx, ProtocolTxType}; use namada_tx::data::{ - BatchResults, BatchedTxResult, ExtendedTxResult, TxResult, VpStatusFlags, - VpsResult, WrapperTx, + BatchedTxResult, ExtendedTxResult, TxResult, VpStatusFlags, VpsResult, + WrapperTx, }; use namada_tx::{BatchedTxRef, Tx, TxCommitments}; use namada_vote_ext::EthereumTxData; @@ -265,7 +267,7 @@ where let cmt = tx.first_commitments().ok_or(Error::MissingInnerTxs)?; let batched_tx_result = apply_wasm_tx( - tx.batch_ref_tx(cmt), + &tx.batch_ref_tx(cmt), &tx_index, ShellParams { tx_gas_meter, @@ -275,17 +277,14 @@ where }, )?; - Ok(TxResult { - gas_used: tx_gas_meter.borrow().get_tx_consumed_gas(), - batch_results: { - let mut batch_results = BatchResults::new(); - batch_results.insert_inner_tx_result( - wrapper_hash, - either::Right(cmt), - Ok(batched_tx_result), - ); - batch_results - }, + Ok({ + let mut batch_results = TxResult::new(); + batch_results.insert_inner_tx_result( + wrapper_hash, + either::Right(cmt), + Ok(batched_tx_result), + ); + batch_results } .to_extended_result(None)) } @@ -296,17 +295,14 @@ where let batched_tx_result = apply_protocol_tx(protocol_tx.tx, tx.data(cmt), state)?; - Ok(TxResult { - batch_results: { - let mut batch_results = BatchResults::new(); - batch_results.insert_inner_tx_result( - None, - either::Right(cmt), - Ok(batched_tx_result), - ); - batch_results - }, - ..Default::default() + Ok({ + let mut batch_results = TxResult::new(); + batch_results.insert_inner_tx_result( + None, + either::Right(cmt), + Ok(batched_tx_result), + ); + batch_results } .to_extended_result(None)) } @@ -342,9 +338,10 @@ where pub(crate) fn get_batch_txs_to_execute<'a>( tx: &'a Tx, masp_tx_refs: &MaspTxRefs, + ibc_tx_data_refs: &IbcTxDataRefs, ) -> impl Iterator { let mut batch_iter = tx.commitments().iter(); - if !masp_tx_refs.0.is_empty() { + if !masp_tx_refs.0.is_empty() || !ibc_tx_data_refs.0.is_empty() { // If fees were paid via masp skip the first transaction of the batch // which has already been executed batch_iter.next(); @@ -369,9 +366,13 @@ where H: 'static + StorageHasher + Sync, CA: 'static + WasmCacheAccess + Sync, { - for cmt in get_batch_txs_to_execute(tx, &extended_tx_result.masp_tx_refs) { + for cmt in get_batch_txs_to_execute( + tx, + &extended_tx_result.masp_tx_refs, + &extended_tx_result.ibc_tx_data_refs, + ) { match apply_wasm_tx( - tx.batch_ref_tx(cmt), + &tx.batch_ref_tx(cmt), &tx_index, ShellParams { tx_gas_meter, @@ -382,16 +383,11 @@ where ) { Err(Error::GasError(ref msg)) => { // Gas error aborts the execution of the entire batch - extended_tx_result.tx_result.gas_used = - tx_gas_meter.borrow().get_tx_consumed_gas(); - extended_tx_result - .tx_result - .batch_results - .insert_inner_tx_result( - wrapper_hash, - either::Right(cmt), - Err(Error::GasError(msg.to_owned())), - ); + extended_tx_result.tx_result.insert_inner_tx_result( + wrapper_hash, + either::Right(cmt), + Err(Error::GasError(msg.to_owned())), + ); state.write_log_mut().drop_tx(); return Err(DispatchError { error: Error::GasError(msg.to_owned()), @@ -402,16 +398,11 @@ where let is_accepted = matches!(&res, Ok(result) if result.is_accepted()); - extended_tx_result - .tx_result - .batch_results - .insert_inner_tx_result( - wrapper_hash, - either::Right(cmt), - res, - ); - extended_tx_result.tx_result.gas_used = - tx_gas_meter.borrow().get_tx_consumed_gas(); + extended_tx_result.tx_result.insert_inner_tx_result( + wrapper_hash, + either::Right(cmt), + res, + ); if is_accepted { // If the transaction was a masp one append the // transaction refs for the events @@ -424,9 +415,14 @@ where .0 .push(masp_section_ref); } - extended_tx_result.is_ibc_shielding = - namada_tx::action::is_ibc_shielding_transfer(state) - .map_err(Error::StateError)?; + if is_ibc_shielding_transfer(&*state) + .map_err(Error::StateError)? + { + extended_tx_result + .ibc_tx_data_refs + .0 + .push(*cmt.data_sechash()) + } state.write_log_mut().commit_tx_to_batch(); } else { state.write_log_mut().drop_tx(); @@ -447,6 +443,12 @@ where Ok(extended_tx_result) } +/// Transaction result for masp transfer +pub struct MaspTxResult { + tx_result: BatchedTxResult, + masp_section_ref: Either, +} + /// Performs the required operation on a wrapper transaction: /// - replay protection /// - fee payment @@ -487,18 +489,23 @@ where // have propagated an error) shell_params.state.write_log_mut().commit_batch(); - let (batch_results, masp_tx_refs) = payment_result.map_or_else( - || (BatchResults::default(), None), - |(batched_result, masp_section_ref)| { - let mut batch = BatchResults::default(); + let (batch_results, masp_section_refs) = payment_result.map_or_else( + || (TxResult::default(), None), + |masp_tx_result| { + let mut batch = TxResult::default(); batch.insert_inner_tx_result( // Ok to unwrap cause if we have a batched result it means // we've executed the first tx in the batch tx.wrapper_hash().as_ref(), either::Right(tx.first_commitments().unwrap()), - Ok(batched_result), + Ok(masp_tx_result.tx_result), ); - (batch, Some(MaspTxRefs(vec![masp_section_ref]))) + let masp_section_refs = + Some(masp_tx_result.masp_section_ref.map_either( + |masp_tx_ref| MaspTxRefs(vec![masp_tx_ref]), + |ibc_tx_data| IbcTxDataRefs(vec![ibc_tx_data]), + )); + (batch, masp_section_refs) }, ); @@ -508,11 +515,7 @@ where .add_wrapper_gas(tx_bytes) .map_err(|err| Error::GasError(err.to_string()))?; - Ok(TxResult { - gas_used: tx_gas_meter.borrow().get_tx_consumed_gas(), - batch_results, - } - .to_extended_result(masp_tx_refs)) + Ok(batch_results.to_extended_result(masp_section_refs)) } /// Perform the actual transfer of fees from the fee payer to the block @@ -524,7 +527,7 @@ pub fn transfer_fee( tx: &Tx, wrapper: &WrapperTx, tx_index: &TxIndex, -) -> Result> +) -> Result> where S: State + StorageRead @@ -677,7 +680,7 @@ fn try_masp_fee_payment( }: &mut ShellParams<'_, S, D, H, CA>, tx: &Tx, tx_index: &TxIndex, -) -> Result> +) -> Result> where S: State + StorageRead @@ -702,7 +705,7 @@ where let gas_scale = get_gas_scale(&**state).map_err(Error::StorageError)?; let mut gas_meter = TxGasMeter::new( - namada_gas::Gas::from_whole_units(max_gas_limit, gas_scale) + namada_gas::Gas::from_whole_units(max_gas_limit.into(), gas_scale) .ok_or_else(|| { Error::GasError("Overflow in gas expansion".to_string()) })?, @@ -713,9 +716,11 @@ where let ref_unshield_gas_meter = RefCell::new(gas_meter); let valid_batched_tx_result = { + let first_tx = tx + .batch_ref_first_tx() + .ok_or_else(|| Error::MissingInnerTxs)?; match apply_wasm_tx( - tx.batch_ref_first_tx() - .ok_or_else(|| Error::MissingInnerTxs)?, + &first_tx, tx_index, ShellParams { tx_gas_meter: &ref_unshield_gas_meter, @@ -740,16 +745,32 @@ where ); } - let masp_ref = namada_tx::action::get_masp_section_ref(*state) - .map_err(Error::StateError)?; // Ensure that the transaction is actually a masp one, otherwise // reject - (is_masp_transfer(&result.changed_keys) && result.is_accepted()) - .then(|| { - masp_ref - .map(|masp_section_ref| (result, masp_section_ref)) - }) - .flatten() + if is_masp_transfer(&result.changed_keys) + && result.is_accepted() + { + if let Some(masp_tx_id) = + namada_tx::action::get_masp_section_ref(*state) + .map_err(Error::StateError)? + { + Some(MaspTxResult { + tx_result: result, + masp_section_ref: Either::Left(masp_tx_id), + }) + } else { + is_ibc_shielding_transfer(*state) + .map_err(Error::StateError)? + .then_some(MaspTxResult { + tx_result: result, + masp_section_ref: Either::Right( + *first_tx.cmt.data_sechash(), + ), + }) + } + } else { + None + } } Err(e) => { state.write_log_mut().drop_tx(); @@ -807,7 +828,7 @@ pub fn check_fees( shell_params: &mut ShellParams<'_, S, D, H, CA>, tx: &Tx, wrapper: &WrapperTx, -) -> Result> +) -> Result> where S: State + StorageRead @@ -877,7 +898,7 @@ where /// Apply a transaction going via the wasm environment. Gas will be metered and /// validity predicates will be triggered in the normal way. pub fn apply_wasm_tx<'a, S, D, H, CA>( - batched_tx: BatchedTxRef<'_>, + batched_tx: &BatchedTxRef<'_>, tx_index: &TxIndex, shell_params: ShellParams<'a, S, D, H, CA>, ) -> Result @@ -895,7 +916,7 @@ where } = shell_params; let verifiers = execute_tx( - &batched_tx, + batched_tx, tx_index, state, tx_gas_meter, @@ -904,7 +925,7 @@ where )?; let vps_result = check_vps(CheckVps { - batched_tx: &batched_tx, + batched_tx, tx_index, state, tx_gas_meter: &mut tx_gas_meter.borrow_mut(), diff --git a/crates/node/src/bench_utils.rs b/crates/node/src/bench_utils.rs index d4f9bf6334..a0b9f1aa91 100644 --- a/crates/node/src/bench_utils.rs +++ b/crates/node/src/bench_utils.rs @@ -77,9 +77,7 @@ use namada::masp::MaspTxRefs; use namada::state::StorageRead; use namada::token::{Amount, DenominatedAmount, Transfer}; use namada::tx::data::pos::Bond; -use namada::tx::data::{ - BatchResults, BatchedTxResult, Fee, TxResult, VpsResult, -}; +use namada::tx::data::{BatchedTxResult, Fee, TxResult, VpsResult}; use namada::tx::event::{new_tx_event, Batch}; use namada::tx::{ Authorization, BatchedTx, BatchedTxRef, Code, Data, Section, Tx, @@ -919,24 +917,19 @@ impl Client for BenchShell { .iter() .enumerate() .map(|(idx, (tx, changed_keys))| { - let tx_result = TxResult:: { - gas_used: 0.into(), - batch_results: { - let mut batch_results = BatchResults::new(); - batch_results.insert_inner_tx_result( - tx.wrapper_hash().as_ref(), - either::Right( - tx.first_commitments().unwrap(), - ), - Ok(BatchedTxResult { - changed_keys: changed_keys.to_owned(), - vps_result: VpsResult::default(), - initialized_accounts: vec![], - events: BTreeSet::default(), - }), - ); - batch_results - }, + let tx_result = { + let mut batch_results = TxResult::new(); + batch_results.insert_inner_tx_result( + tx.wrapper_hash().as_ref(), + either::Right(tx.first_commitments().unwrap()), + Ok(BatchedTxResult { + changed_keys: changed_keys.to_owned(), + vps_result: VpsResult::default(), + initialized_accounts: vec![], + events: BTreeSet::default(), + }), + ); + batch_results }; let event: Event = new_tx_event(tx, height.value()) .with(Batch(&tx_result)) @@ -1077,8 +1070,8 @@ impl BenchShieldedCtx { .block_on(namada_apps_lib::client::masp::syncing( self.shielded, &self.shell, + None, &StdIo, - 1, None, None, &[spending_key.into()], diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index 45550427b4..a6aadd1f8e 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -35,12 +35,10 @@ use futures::future::TryFutureExt; use namada::core::storage::BlockHeight; use namada::core::time::DateTimeUtc; use namada::eth_bridge::ethers::providers::{Http, Provider}; -use namada::key::tm_raw_hash_to_string; -use namada::ledger::pos::find_validator_by_raw_hash; -use namada::state::DB; +use namada::state::{ProcessProposalCachedResult, DB}; use namada::storage::DbColFam; use namada::tendermint::abci::request::CheckTxKind; -use namada::tx::data::ResultCode; +use namada::tendermint::abci::response::ProcessProposal; use namada_apps_lib::cli::args; use namada_apps_lib::config::utils::{ convert_tm_addr_to_socket_addr, num_of_threads, @@ -128,8 +126,33 @@ impl Shell { Request::ProcessProposal(block) => { tracing::debug!("Request ProcessProposal"); // TODO: use TM domain type in the handler - let (response, _tx_results) = + // NOTE: make sure to put any checks inside process_proposal + // since that function is called in other places to rerun the + // checks if (when) needed. Every check living outside that + // function will not be correctly replicated in the other + // locations + let block_hash = block.hash.try_into(); + let (response, tx_results) = self.process_proposal(block.into()); + // Cache the response in case of future calls from Namada. If + // hash conversion fails avoid caching + if let Ok(block_hash) = block_hash { + let result = if let ProcessProposal::Accept = response { + ProcessProposalCachedResult::Accepted( + tx_results + .into_iter() + .map(|res| res.into()) + .collect(), + ) + } else { + ProcessProposalCachedResult::Rejected + }; + + self.state + .in_mem_mut() + .block_proposals_cache + .put(block_hash, result); + } Ok(Response::ProcessProposal(response)) } Request::RevertProposal(_req) => { @@ -173,9 +196,9 @@ impl Shell { } // Checks if a run of process proposal is required before finalize block - // (recheck) and, in case, performs it + // (recheck) and, in case, performs it. Clears the cache before returning fn try_recheck_process_proposal( - &self, + &mut self, finalize_req: &shims::abcipp_shim_types::shim::request::FinalizeBlock, ) -> Result<(), Error> { let recheck_process_proposal = match self.mode { @@ -193,37 +216,42 @@ impl Shell { }; if recheck_process_proposal { - let tm_raw_hash_string = - tm_raw_hash_to_string(&finalize_req.proposer_address); - let block_proposer = - find_validator_by_raw_hash(&self.state, tm_raw_hash_string) - .unwrap() - .expect( - "Unable to find native validator address of block \ - proposer from tendermint raw hash", - ); - - let check_result = self.process_txs( - &finalize_req - .txs - .iter() - .map(|ptx| ptx.tx.clone()) - .collect::>(), - finalize_req.header.time, - &block_proposer, - ); - - let invalid_txs = check_result.iter().any(|res| { - let error = ResultCode::from_u32(res.code) - .expect("Failed to cast result code"); - !error.is_recoverable() - }); + let process_proposal_result = match self + .state + .in_mem_mut() + .block_proposals_cache + .get(&finalize_req.block_hash) + { + // We already have the result of process proposal for this block + // cached in memory + Some(res) => res.to_owned(), + None => { + let process_req = finalize_req + .clone() + .cast_to_process_proposal_req() + .map_err(|_| Error::InvalidBlockProposal)?; + // No need to cache the result since this is the last step + // before finalizing the block + if let ProcessProposal::Accept = + self.process_proposal(process_req.into()).0 + { + ProcessProposalCachedResult::Accepted(vec![]) + } else { + ProcessProposalCachedResult::Rejected + } + } + }; - if invalid_txs { - return Err(Error::InvalidBlockProposal); + if let ProcessProposalCachedResult::Rejected = + process_proposal_result + { + return Err(Error::RejectedBlockProposal); } } + // Clear the cache of proposed blocks' results + self.state.in_mem_mut().block_proposals_cache.clear(); + Ok(()) } } diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index c32ab0d12c..057f7bfa34 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -9,7 +9,8 @@ use namada::gas::event::GasUsed; use namada::governance::pgf::inflation as pgf_inflation; use namada::hash::Hash; use namada::ledger::events::extend::{ - ComposeEvent, Height, Info, MaspTxBatchRefs, MaspTxBlockIndex, TxHash, + ComposeEvent, Height, IbcMaspTxBatchRefs, Info, MaspTxBatchRefs, + MaspTxBlockIndex, TxHash, }; use namada::ledger::events::EmitEvents; use namada::ledger::gas::GasMetering; @@ -83,7 +84,8 @@ where let emit_events = &mut response.events; // Get the actual votes from cometBFT in the preferred format - let votes = pos_votes_from_abci(&self.state, &req.votes); + let votes = + pos_votes_from_abci(&self.state, &req.decided_last_commit.votes); let validator_set_update_epoch = self.get_validator_set_update_epoch(current_epoch); @@ -374,12 +376,10 @@ where ); let gas_scale = get_gas_scale(&self.state) .expect("Failed to get gas scale from parameters"); - let scaled_gas = Gas::from( - tx_data - .tx_gas_meter - .get_tx_consumed_gas() - .get_whole_gas_units(gas_scale), - ); + let scaled_gas = tx_data + .tx_gas_meter + .get_tx_consumed_gas() + .get_whole_gas_units(gas_scale); tx_logs .tx_event .extend(GasUsed(scaled_gas)) @@ -409,12 +409,10 @@ where let gas_scale = get_gas_scale(&self.state) .expect("Failed to get gas scale from parameters"); - let scaled_gas = Gas::from( - tx_data - .tx_gas_meter - .get_tx_consumed_gas() - .get_whole_gas_units(gas_scale), - ); + let scaled_gas = tx_data + .tx_gas_meter + .get_tx_consumed_gas() + .get_whole_gas_units(gas_scale); tx_logs .tx_event @@ -462,10 +460,8 @@ where let unrun_txs = tx_data .commitments_len .checked_sub( - u64::try_from( - extended_tx_result.tx_result.batch_results.len(), - ) - .expect("Should be able to convert to u64"), + u64::try_from(extended_tx_result.tx_result.len()) + .expect("Should be able to convert to u64"), ) .expect("Shouldn't underflow"); temp_log.stats.set_failing_atomic_batch(unrun_txs); @@ -494,12 +490,10 @@ where let gas_scale = get_gas_scale(&self.state) .expect("Failed to get gas scale from parameters"); - let scaled_gas = Gas::from( - tx_data - .tx_gas_meter - .get_tx_consumed_gas() - .get_whole_gas_units(gas_scale), - ); + let scaled_gas = tx_data + .tx_gas_meter + .get_tx_consumed_gas() + .get_whole_gas_units(gas_scale); tx_logs .tx_event @@ -530,7 +524,7 @@ where let unrun_txs = tx_data .commitments_len .checked_sub( - u64::try_from(extended_tx_result.tx_result.batch_results.len()) + u64::try_from(extended_tx_result.tx_result.len()) .expect("Should be able to convert to u64"), ) .expect("Shouldn't underflow"); @@ -983,9 +977,7 @@ impl<'finalize> TempTxLogs { ) -> ValidityFlags { let mut flags = ValidityFlags::default(); - for (cmt_hash, batched_result) in - extended_tx_result.tx_result.batch_results.iter() - { + for (cmt_hash, batched_result) in extended_tx_result.tx_result.iter() { match batched_result { Ok(result) => { if result.is_accepted() { @@ -1056,9 +1048,12 @@ impl<'finalize> TempTxLogs { )); } - if extended_tx_result.is_ibc_shielding { + if !extended_tx_result.ibc_tx_data_refs.0.is_empty() { self.tx_event .extend(MaspTxBlockIndex(TxIndex::must_from_usize(tx_index))); + self.tx_event.extend(IbcMaspTxBatchRefs( + extended_tx_result.ibc_tx_data_refs.clone(), + )); } flags @@ -1207,7 +1202,7 @@ mod test_finalize_block { FinalizeBlock, ProcessedTx, }; - const WRAPPER_GAS_LIMIT: u64 = 11_000; + const WRAPPER_GAS_LIMIT: u64 = 150_000; const STORAGE_VALUE: &str = "test_value"; /// Make a wrapper tx and a processed tx from the wrapped tx that can be @@ -1893,7 +1888,10 @@ mod test_finalize_block { let req = FinalizeBlock { txs, proposer_address: proposer_address.clone(), - votes: votes.clone(), + decided_last_commit: tendermint::abci::types::CommitInfo { + round: 0u8.into(), + votes: votes.clone(), + }, ..Default::default() }; // merkle tree root before finalize_block @@ -3278,7 +3276,6 @@ mod test_finalize_block { assert_eq!(code, ResultCode::Ok); let inner_tx_result = event[0].read_attribute::>().unwrap(); let first_tx_result = inner_tx_result - .batch_results .get_inner_tx_result( Some(&wrapper.header_hash()), either::Right(wrapper.first_commitments().unwrap()), @@ -3429,7 +3426,6 @@ mod test_finalize_block { assert_eq!(code, ResultCode::Ok); let inner_tx_result = event[1].read_attribute::>().unwrap(); let inner_result = inner_tx_result - .batch_results .get_inner_tx_result( Some(&unsigned_wrapper.header_hash()), either::Right(unsigned_wrapper.first_commitments().unwrap()), @@ -3441,7 +3437,6 @@ mod test_finalize_block { assert_eq!(code, ResultCode::Ok); let inner_tx_result = event[2].read_attribute::>().unwrap(); let inner_result = inner_tx_result - .batch_results .get_inner_tx_result( Some(&wrong_commitment_wrapper.header_hash()), either::Right( @@ -3455,7 +3450,6 @@ mod test_finalize_block { assert_eq!(code, ResultCode::Ok); let inner_tx_result = event[3].read_attribute::>().unwrap(); let inner_result = inner_tx_result - .batch_results .get_inner_tx_result( Some(&failing_wrapper.header_hash()), either::Right(failing_wrapper.first_commitments().unwrap()), @@ -3660,7 +3654,6 @@ mod test_finalize_block { assert_eq!(code, ResultCode::Ok); let inner_tx_result = event.read_attribute::>().unwrap(); let inner_result = inner_tx_result - .batch_results .get_inner_tx_result( Some(&wrapper.header_hash()), either::Right(wrapper.first_commitments().unwrap()), @@ -5566,7 +5559,7 @@ mod test_finalize_block { let code = event[0].read_attribute::().unwrap(); assert_eq!(code, ResultCode::Ok); let inner_tx_result = event[0].read_attribute::>().unwrap(); - let inner_results = inner_tx_result.batch_results; + let inner_results = inner_tx_result; for cmt in batch.commitments() { assert!( @@ -5614,7 +5607,7 @@ mod test_finalize_block { let code = event[0].read_attribute::().unwrap(); assert_eq!(code, ResultCode::WasmRuntimeError); let inner_tx_result = event[0].read_attribute::>().unwrap(); - let inner_results = inner_tx_result.batch_results; + let inner_results = inner_tx_result; assert!( inner_results @@ -5673,7 +5666,7 @@ mod test_finalize_block { let code = event[0].read_attribute::().unwrap(); assert_eq!(code, ResultCode::Ok); let inner_tx_result = event[0].read_attribute::>().unwrap(); - let inner_results = inner_tx_result.batch_results; + let inner_results = inner_tx_result; assert!( inner_results @@ -5750,7 +5743,7 @@ mod test_finalize_block { let code = event[0].read_attribute::().unwrap(); assert_eq!(code, ResultCode::WasmRuntimeError); let inner_tx_result = event[0].read_attribute::>().unwrap(); - let inner_results = inner_tx_result.batch_results; + let inner_results = inner_tx_result; assert!( inner_results @@ -5808,7 +5801,7 @@ mod test_finalize_block { let code = event[0].read_attribute::().unwrap(); assert_eq!(code, ResultCode::WasmRuntimeError); let inner_tx_result = event[0].read_attribute::>().unwrap(); - let inner_results = inner_tx_result.batch_results; + let inner_results = inner_tx_result; assert!( inner_results @@ -5917,10 +5910,10 @@ mod test_finalize_block { // multiple tx results (2) let tx_results = event.read_attribute::>().unwrap(); - assert_eq!(tx_results.batch_results.len(), 2); + assert_eq!(tx_results.len(), 2); // all txs should have succeeded - assert!(tx_results.batch_results.are_results_ok()); + assert!(tx_results.are_results_ok()); } #[test] @@ -5990,10 +5983,10 @@ mod test_finalize_block { // multiple tx results (2) let tx_results = event.read_attribute::>().unwrap(); - assert_eq!(tx_results.batch_results.len(), 2); + assert_eq!(tx_results.len(), 2); // check one succeeded and the other failed - assert!(tx_results.batch_results.are_any_ok()); - assert!(tx_results.batch_results.are_any_err()); + assert!(tx_results.are_any_ok()); + assert!(tx_results.are_any_err()); } } diff --git a/crates/node/src/shell/governance.rs b/crates/node/src/shell/governance.rs index fefa43fa55..c3112ba49b 100644 --- a/crates/node/src/shell/governance.rs +++ b/crates/node/src/shell/governance.rs @@ -428,7 +428,6 @@ where match dispatch_result { Ok(extended_tx_result) => match extended_tx_result .tx_result - .batch_results .get_inner_tx_result(None, either::Right(&cmt)) { Some(Ok(batched_result)) if batched_result.is_accepted() => { diff --git a/crates/node/src/shell/mod.rs b/crates/node/src/shell/mod.rs index 742c42e7ed..4d82c6f10d 100644 --- a/crates/node/src/shell/mod.rs +++ b/crates/node/src/shell/mod.rs @@ -126,6 +126,11 @@ pub enum Error { ReplayAttempt(String), #[error("Error with snapshots: {0}")] Snapshot(std::io::Error), + #[error( + "Received a finalize request for a block that was rejected by process \ + proposal" + )] + RejectedBlockProposal, #[error("Received an invalid block proposal")] InvalidBlockProposal, } @@ -1177,7 +1182,9 @@ where // Max block gas let block_gas_limit: Gas = Gas::from_whole_units( - namada::parameters::get_max_block_gas(&self.state).unwrap(), + namada::parameters::get_max_block_gas(&self.state) + .unwrap() + .into(), gas_scale, ) .expect("Gas limit from parameter must not overflow"); @@ -1902,6 +1909,7 @@ mod test_utils { time: DateTimeUtc::now(), next_validators_hash: Hash([0; 32]), }, + block_hash: Hash([0; 32]), byzantine_validators: vec![], txs: vec![], proposer_address: HEXUPPER @@ -1912,7 +1920,11 @@ mod test_utils { .as_bytes(), ) .unwrap(), - votes: vec![], + height: 0u8.into(), + decided_last_commit: tendermint::abci::types::CommitInfo { + round: 0u8.into(), + votes: vec![], + }, } } } @@ -1959,7 +1971,10 @@ mod test_utils { let mut req = FinalizeBlock { header, proposer_address, - votes, + decided_last_commit: tendermint::abci::types::CommitInfo { + round: 0u8.into(), + votes, + }, ..Default::default() }; if let Some(byz_vals) = byzantine_validators { diff --git a/crates/node/src/shell/prepare_proposal.rs b/crates/node/src/shell/prepare_proposal.rs index b5d8bba75a..4d77d522be 100644 --- a/crates/node/src/shell/prepare_proposal.rs +++ b/crates/node/src/shell/prepare_proposal.rs @@ -687,7 +687,10 @@ mod test_prepare_proposal { ]; let req = FinalizeBlock { proposer_address: pkh1.to_vec(), - votes, + decided_last_commit: namada::tendermint::abci::types::CommitInfo { + round: 0u8.into(), + votes, + }, ..Default::default() }; shell.start_new_epoch(Some(req)); diff --git a/crates/node/src/shell/queries.rs b/crates/node/src/shell/queries.rs index a1490b4a08..0269f36602 100644 --- a/crates/node/src/shell/queries.rs +++ b/crates/node/src/shell/queries.rs @@ -163,7 +163,10 @@ mod test_queries { }]; let req = FinalizeBlock { proposer_address: pkh1.to_vec(), - votes, + decided_last_commit: namada::tendermint::abci::types::CommitInfo{ + round: 0u8.into(), + votes + }, ..Default::default() }; shell.finalize_and_commit(Some(req)); diff --git a/crates/node/src/shell/testing/node.rs b/crates/node/src/shell/testing/node.rs index 30f43bf259..61db218cae 100644 --- a/crates/node/src/shell/testing/node.rs +++ b/crates/node/src/shell/testing/node.rs @@ -475,10 +475,15 @@ impl MockNode { time: DateTimeUtc::now(), next_validators_hash: Hash([0; 32]), }, + block_hash: Hash([0; 32]), byzantine_validators: vec![], txs: txs.clone(), proposer_address, - votes, + height: height.try_into().unwrap(), + decided_last_commit: tendermint::abci::types::CommitInfo { + round: 0u8.into(), + votes, + }, }; let resp = locked.finalize_block(req).expect("Test failed"); @@ -589,6 +594,7 @@ impl MockNode { time: DateTimeUtc::now(), next_validators_hash: Hash([0; 32]), }, + block_hash: Hash([0; 32]), byzantine_validators: vec![], txs: txs .clone() @@ -600,7 +606,11 @@ impl MockNode { }) .collect(), proposer_address, - votes, + height: height.try_into().unwrap(), + decided_last_commit: tendermint::abci::types::CommitInfo { + round: 0u8.into(), + votes, + }, }; // process the results diff --git a/crates/node/src/shell/vote_extensions/bridge_pool_vext.rs b/crates/node/src/shell/vote_extensions/bridge_pool_vext.rs index 59ced93374..f76d859886 100644 --- a/crates/node/src/shell/vote_extensions/bridge_pool_vext.rs +++ b/crates/node/src/shell/vote_extensions/bridge_pool_vext.rs @@ -145,7 +145,10 @@ mod test_bp_vote_extensions { }]; let req = FinalizeBlock { proposer_address: pkh1.to_vec(), - votes, + decided_last_commit: namada::tendermint::abci::types::CommitInfo { + round: 0u8.into(), + votes, + }, ..Default::default() }; assert_eq!(shell.start_new_epoch(Some(req)).0, 1); diff --git a/crates/node/src/shell/vote_extensions/eth_events.rs b/crates/node/src/shell/vote_extensions/eth_events.rs index 6e39450389..bab313dca3 100644 --- a/crates/node/src/shell/vote_extensions/eth_events.rs +++ b/crates/node/src/shell/vote_extensions/eth_events.rs @@ -471,7 +471,10 @@ mod test_vote_extensions { }]; let req = FinalizeBlock { proposer_address: pkh1.to_vec(), - votes, + decided_last_commit: namada::tendermint::abci::types::CommitInfo { + round: 0u8.into(), + votes, + }, ..Default::default() }; assert_eq!(shell.start_new_epoch(Some(req)).0, 1); diff --git a/crates/node/src/shell/vote_extensions/val_set_update.rs b/crates/node/src/shell/vote_extensions/val_set_update.rs index ed87a89896..54fc8d073e 100644 --- a/crates/node/src/shell/vote_extensions/val_set_update.rs +++ b/crates/node/src/shell/vote_extensions/val_set_update.rs @@ -323,7 +323,10 @@ mod test_vote_extensions { }]; let req = FinalizeBlock { proposer_address: pkh1.to_vec(), - votes, + decided_last_commit: namada::tendermint::abci::types::CommitInfo { + round: 0u8.into(), + votes, + }, ..Default::default() }; assert_eq!(shell.start_new_epoch(Some(req)).0, 1); diff --git a/crates/node/src/shims/abcipp_shim.rs b/crates/node/src/shims/abcipp_shim.rs index 998292b2c9..6ad77f364a 100644 --- a/crates/node/src/shims/abcipp_shim.rs +++ b/crates/node/src/shims/abcipp_shim.rs @@ -5,10 +5,9 @@ use std::task::{Context, Poll}; use futures::future::FutureExt; use namada::core::hash::Hash; -use namada::core::key::tm_raw_hash_to_string; use namada::core::storage::BlockHeight; -use namada::proof_of_stake::storage::find_validator_by_raw_hash; -use namada::state::DB; +use namada::state::{ProcessProposalCachedResult, DB}; +use namada::tendermint::abci::response::ProcessProposal; use namada::time::{DateTimeUtc, Utc}; use namada::tx::data::hash_tx; use namada_sdk::migrations::ScheduledMigration; @@ -16,7 +15,9 @@ use tokio::sync::broadcast; use tokio::sync::mpsc::UnboundedSender; use tower::Service; -use super::abcipp_shim_types::shim::request::{FinalizeBlock, ProcessedTx}; +use super::abcipp_shim_types::shim::request::{ + CheckProcessProposal, FinalizeBlock, ProcessedTx, +}; use super::abcipp_shim_types::shim::{ Error, Request, Response, TakeSnapshot, TxBytes, }; @@ -120,43 +121,28 @@ impl AbcippShim { Req::EndBlock(_) => { let begin_block_request = self.begin_block_request.take().unwrap(); - let block_time = begin_block_request - .header - .time - .try_into() - .expect("valid RFC3339 block time"); - - let tm_raw_hash_string = tm_raw_hash_to_string( - begin_block_request.header.proposer_address, - ); - let block_proposer = find_validator_by_raw_hash( - &self.service.state, - tm_raw_hash_string, - ) - .unwrap() - .expect( - "Unable to find native validator address of block \ - proposer from tendermint raw hash", - ); - let processing_results = self.service.process_txs( - &self.delivered_txs, - block_time, - &block_proposer, - ); - let mut txs = Vec::with_capacity(self.delivered_txs.len()); - let mut delivered = vec![]; - std::mem::swap(&mut self.delivered_txs, &mut delivered); - for (result, tx) in processing_results - .into_iter() - .zip(delivered.into_iter()) - { - txs.push(ProcessedTx { tx, result }); - } - let mut end_block_request: FinalizeBlock = - begin_block_request.into(); - end_block_request.txs = txs; - self.service + match self.get_process_proposal_result( + begin_block_request.clone(), + ) { + ProcessProposalCachedResult::Accepted(tx_results) => { + let mut txs = + Vec::with_capacity(self.delivered_txs.len()); + let delivered = + std::mem::take(&mut self.delivered_txs); + for (result, tx) in tx_results + .into_iter() + .zip(delivered.into_iter()) + { + txs.push(ProcessedTx { + tx, + result: result.into(), + }); + } + let mut end_block_request: FinalizeBlock = + begin_block_request.into(); + end_block_request.txs = txs; + self.service .call(Request::FinalizeBlock(end_block_request)) .map_err(Error::from) .and_then(|res| match res { @@ -165,6 +151,13 @@ impl AbcippShim { } _ => Err(Error::ConvertResp(res)), }) + } + ProcessProposalCachedResult::Rejected => { + Err(Error::Shell( + crate::shell::Error::RejectedBlockProposal, + )) + } + } } Req::Commit => match self.service.call(Request::Commit) { Ok(Response::Commit(res, take_snapshot)) => { @@ -247,6 +240,78 @@ impl AbcippShim { self.snapshot_task.replace(snapshot_task); } } + + // Retrieve the cached result of process proposal for the given block or + // compute it if missing + fn get_process_proposal_result( + &mut self, + begin_block_request: request::BeginBlock, + ) -> ProcessProposalCachedResult { + match namada::core::hash::Hash::try_from(begin_block_request.hash) { + Ok(block_hash) => { + match self + .service + .state + .in_mem_mut() + .block_proposals_cache + .get(&block_hash) + { + // We already have the result of process proposal for + // this block cached in memory + Some(res) => res.to_owned(), + None => { + // Need to run process proposal to extract the data we + // need for finalize block (tx results) + let process_req = + CheckProcessProposal::from(begin_block_request) + .cast_to_tendermint_req( + self.delivered_txs.clone(), + ); + + let (process_resp, res) = + self.service.process_proposal(process_req.into()); + let result = if let ProcessProposal::Accept = + process_resp + { + ProcessProposalCachedResult::Accepted( + res.into_iter().map(|res| res.into()).collect(), + ) + } else { + ProcessProposalCachedResult::Rejected + }; + + // Cache the result + self.service + .state + .in_mem_mut() + .block_proposals_cache + .put(block_hash.to_owned(), result.clone()); + + result + } + } + } + Err(_) => { + // Need to run process proposal to extract the data we need for + // finalize block (tx results) + let process_req = + CheckProcessProposal::from(begin_block_request) + .cast_to_tendermint_req(self.delivered_txs.clone()); + + // Do not cache the result in this case since we + // don't have the hash of the block + let (process_resp, res) = + self.service.process_proposal(process_req.into()); + if let ProcessProposal::Accept = process_resp { + ProcessProposalCachedResult::Accepted( + res.into_iter().map(|res| res.into()).collect(), + ) + } else { + ProcessProposalCachedResult::Rejected + } + } + } + } } /// Indicates how [`AbciService`] should diff --git a/crates/node/src/shims/abcipp_shim_types.rs b/crates/node/src/shims/abcipp_shim_types.rs index 50a01f3559..be671f6908 100644 --- a/crates/node/src/shims/abcipp_shim_types.rs +++ b/crates/node/src/shims/abcipp_shim_types.rs @@ -7,7 +7,6 @@ pub mod shim { use thiserror::Error; use super::{Request as Req, Response as Resp}; - use crate::facade::tendermint::abci::types::VoteInfo; use crate::facade::tendermint::v0_37::abci::{ request as tm_request, response as tm_response, }; @@ -169,11 +168,15 @@ pub mod shim { /// Custom types for request payloads pub mod request { + use bytes::Bytes; use namada::core::hash::Hash; use namada::core::storage::Header; use namada::core::time::DateTimeUtc; + use namada::tendermint::abci::types::CommitInfo; + use namada::tendermint::account::Id; + use namada::tendermint::block::Height; + use namada::tendermint::time::Time; - use super::VoteInfo; use crate::facade::tendermint::abci::types::Misbehavior; use crate::facade::tendermint::v0_37::abci::request as tm_request; @@ -191,10 +194,23 @@ pub mod shim { #[derive(Debug, Clone)] pub struct FinalizeBlock { pub header: Header, + pub block_hash: Hash, pub byzantine_validators: Vec, pub txs: Vec, pub proposer_address: Vec, - pub votes: Vec, + pub height: Height, + pub decided_last_commit: CommitInfo, + } + + // Type to run process proposal checks outside of the CometBFT call + pub(crate) struct CheckProcessProposal { + proposed_last_commit: Option, + misbehavior: Vec, + hash: namada::tendermint::Hash, + height: Height, + time: Time, + next_validators_hash: namada::tendermint::Hash, + proposer_address: Id, } impl From for FinalizeBlock { @@ -205,18 +221,92 @@ pub mod shim { hash: Hash::try_from(header.app_hash.as_bytes()) .unwrap_or_default(), time: DateTimeUtc::try_from(header.time).unwrap(), - next_validators_hash: Hash::try_from( - header.next_validators_hash.as_bytes(), - ) - .unwrap(), + next_validators_hash: header + .next_validators_hash + .try_into() + .unwrap(), }, + block_hash: req.hash.try_into().unwrap(), byzantine_validators: req.byzantine_validators, txs: vec![], proposer_address: header.proposer_address.into(), - votes: req.last_commit_info.votes, + height: header.height, + decided_last_commit: req.last_commit_info, + } + } + } + + impl From for CheckProcessProposal { + fn from(req: tm_request::BeginBlock) -> CheckProcessProposal { + let header = req.header; + CheckProcessProposal { + proposed_last_commit: Some(req.last_commit_info), + misbehavior: req.byzantine_validators, + hash: req.hash, + height: header.height, + time: header.time, + next_validators_hash: header.next_validators_hash, + proposer_address: header.proposer_address, + } + } + } + + impl CheckProcessProposal { + pub(crate) fn cast_to_tendermint_req( + self, + txs: Vec, + ) -> tm_request::ProcessProposal { + let Self { + proposed_last_commit, + misbehavior, + hash, + height, + time, + next_validators_hash, + proposer_address, + } = self; + + tm_request::ProcessProposal { + txs, + proposed_last_commit, + misbehavior, + hash, + height, + time, + next_validators_hash, + proposer_address, } } } + + impl FinalizeBlock { + pub(crate) fn cast_to_process_proposal_req( + self, + ) -> Result { + let header = self.header; + Ok(tm_request::ProcessProposal { + txs: self.txs.into_iter().map(|tx| tx.tx).collect(), + proposed_last_commit: Some(self.decided_last_commit), + misbehavior: self.byzantine_validators, + hash: self.block_hash.into(), + height: self.height, + time: header.time.try_into().map_err(|_| { + super::Error::Shell( + super::shell::Error::InvalidBlockProposal, + ) + })?, + next_validators_hash: header.next_validators_hash.into(), + proposer_address: self + .proposer_address + .try_into() + .map_err(|_| { + super::Error::Shell( + super::shell::Error::InvalidBlockProposal, + ) + })?, + }) + } + } } /// Custom types for response payloads @@ -265,5 +355,20 @@ pub mod shim { } } } + + impl From<(u32, String)> for TxResult { + fn from(value: (u32, String)) -> Self { + Self { + code: value.0, + info: value.1, + } + } + } + + impl From for (u32, String) { + fn from(value: TxResult) -> Self { + (value.code, value.info) + } + } } } diff --git a/crates/node/src/storage/mod.rs b/crates/node/src/storage/mod.rs index 07e56dec08..057337a3f2 100644 --- a/crates/node/src/storage/mod.rs +++ b/crates/node/src/storage/mod.rs @@ -174,7 +174,7 @@ mod tests { epochs_per_year: 365, masp_epoch_multiplier: 2, masp_fee_payment_gas_limit: 0, - gas_scale: 100_000_000, + gas_scale: 10_000_000, minimum_gas_price: Default::default(), is_native_token_transferable: true, }; diff --git a/crates/parameters/src/lib.rs b/crates/parameters/src/lib.rs index 3ec0fdbdfe..595df8fa05 100644 --- a/crates/parameters/src/lib.rs +++ b/crates/parameters/src/lib.rs @@ -433,7 +433,7 @@ where epochs_per_year: 365, masp_epoch_multiplier: 2, masp_fee_payment_gas_limit: 0, - gas_scale: 100_000_000, + gas_scale: 10_000_000, minimum_gas_price: Default::default(), is_native_token_transferable: true, }; diff --git a/crates/proof_of_stake/src/lib.rs b/crates/proof_of_stake/src/lib.rs index 3486c25948..fb2cfc93c3 100644 --- a/crates/proof_of_stake/src/lib.rs +++ b/crates/proof_of_stake/src/lib.rs @@ -2725,7 +2725,7 @@ pub mod test_utils { epochs_per_year: 10000000, masp_epoch_multiplier: 2, masp_fee_payment_gas_limit: 10000, - gas_scale: 100_000_000, + gas_scale: 10_000_000, minimum_gas_price: BTreeMap::new(), is_native_token_transferable: true, }; diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml index 622866bd66..413f4c8ecb 100644 --- a/crates/sdk/Cargo.toml +++ b/crates/sdk/Cargo.toml @@ -102,6 +102,7 @@ ethbridge-bridge-contract.workspace = true ethers.workspace = true eyre.workspace = true fd-lock = { workspace = true, optional = true } +flume = "0.11.0" futures.workspace = true itertools.workspace = true jubjub = { workspace = true, optional = true } @@ -134,6 +135,7 @@ tracing.workspace = true zeroize.workspace = true [target.'cfg(not(target_family = "wasm"))'.dependencies] +reqwest.workspace = true tokio = { workspace = true, features = ["full"] } [target.'cfg(target_family = "wasm")'.dependencies] diff --git a/crates/sdk/src/args.rs b/crates/sdk/src/args.rs index 8bdf73202c..47049dbdb5 100644 --- a/crates/sdk/src/args.rs +++ b/crates/sdk/src/args.rs @@ -79,6 +79,8 @@ pub trait NamadaTypes: Clone + std::fmt::Debug { type Data: Clone + std::fmt::Debug; /// Bridge pool recommendations conversion rates table. type BpConversionTable: Clone + std::fmt::Debug; + /// Address of a `namada-masp-indexer` live instance + type MaspIndexerAddress: Clone + std::fmt::Debug; } /// The concrete types being used in Namada SDK @@ -105,6 +107,7 @@ impl NamadaTypes for SdkTypes { type Data = Vec; type EthereumAddress = (); type Keypair = namada_core::key::common::SecretKey; + type MaspIndexerAddress = (); type PaymentAddress = namada_core::masp::PaymentAddress; type PublicKey = namada_core::key::common::PublicKey; type SpendingKey = namada_core::masp::ExtendedSpendingKey; @@ -2082,8 +2085,6 @@ pub struct SignTx { pub struct ShieldedSync { /// The ledger address pub ledger_address: C::ConfigRpcTendermintAddress, - /// The number of txs to fetch before caching - pub batch_size: u64, /// Height to start syncing from. Defaults to the correct one. pub start_query_height: Option, /// Height to sync up to. Defaults to most recent @@ -2092,6 +2093,11 @@ pub struct ShieldedSync { pub spending_keys: Vec, /// Viewing keys used to determine note ownership pub viewing_keys: Vec, + /// Address of a `namada-masp-indexer` live instance + /// + /// If present, the shielded sync will be performed + /// using data retrieved from the given indexer + pub with_indexer: Option, } /// Query PoS commission rate diff --git a/crates/sdk/src/control_flow/mod.rs b/crates/sdk/src/control_flow/mod.rs index 76327304b9..7d77529c3e 100644 --- a/crates/sdk/src/control_flow/mod.rs +++ b/crates/sdk/src/control_flow/mod.rs @@ -10,6 +10,7 @@ use std::task::{Context, Poll}; use futures::future::FutureExt; #[cfg(any(unix, windows))] use tokio::sync::oneshot; +use tokio::sync::oneshot::error::TryRecvError; /// A shutdown signal receiver. pub struct ShutdownSignal { @@ -19,6 +20,18 @@ pub struct ShutdownSignal { rx: oneshot::Receiver<()>, } +impl ShutdownSignal { + /// Checks if an interrupt signal was received. + #[cfg(any(unix, windows))] + pub fn received(&mut self) -> bool { + match self.rx.try_recv() { + Ok(_) => true, + Err(TryRecvError::Empty) => false, + Err(TryRecvError::Closed) => true, + } + } +} + #[cfg(any(unix, windows))] impl Future for ShutdownSignal { type Output = (); @@ -65,6 +78,13 @@ pub fn install_shutdown_signal() -> ShutdownSignal { } } +/// A manually triggerable shutdown signal used for testing +#[cfg(any(test, feature = "testing"))] +pub fn testing_shutdown_signal() -> (oneshot::Sender<()>, ShutdownSignal) { + let (tx, rx) = oneshot::channel(); + (tx, ShutdownSignal { rx }) +} + /// Shutdown signal receiver #[cfg(unix)] pub async fn shutdown_send(tx: oneshot::Sender<()>) { diff --git a/crates/sdk/src/error.rs b/crates/sdk/src/error.rs index f0c22adfca..fc93e2c94f 100644 --- a/crates/sdk/src/error.rs +++ b/crates/sdk/src/error.rs @@ -22,7 +22,7 @@ pub type Result = std::result::Result; pub enum Error { /// Key Retrieval Errors #[error("Key Error: {0}")] - KeyRetrival(#[from] storage::Error), + KeyRetrieval(#[from] storage::Error), /// Transaction Errors #[error("{0}")] Tx(#[from] TxSubmitError), @@ -44,6 +44,9 @@ pub enum Error { /// Any Other errors that are uncategorized #[error("{0}")] Other(String), + /// An interrupt was called + #[error("Process {0} received an interrupt signal")] + Interrupt(String), } /// Errors that deal with querying some kind of data diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index 1b0b8a344c..8ca26fd906 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -80,7 +80,7 @@ use tx::{ use wallet::{Wallet, WalletIo, WalletStorage}; /// Default gas-limit -pub const DEFAULT_GAS_LIMIT: u64 = 25_000; +pub const DEFAULT_GAS_LIMIT: u64 = 100_000; #[allow(missing_docs)] #[cfg(not(feature = "async-send"))] @@ -838,24 +838,25 @@ where /// Tests and strategies for transactions #[cfg(any(test, feature = "testing"))] pub mod testing { + use ::borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use borsh_ext::BorshSerializeExt; use governance::ProposalType; - use ibc::primitives::proto::Any; use masp_primitives::transaction::components::sapling::builder::StoredBuildParams; use namada_account::{InitAccount, UpdateAccount}; use namada_core::address::testing::{ arb_established_address, arb_non_internal_address, }; - use namada_core::address::MASP; + use namada_core::collections::HashMap; use namada_core::eth_bridge_pool::PendingTransfer; use namada_core::hash::testing::arb_hash; use namada_core::key::testing::arb_common_keypair; - use namada_core::masp::addr_taddr; + use namada_core::masp::AssetData; use namada_governance::storage::proposal::testing::{ arb_init_proposal, arb_vote_proposal, }; use namada_governance::{InitProposalData, VoteProposalData}; - use namada_ibc::testing::arb_ibc_any; + use namada_ibc::testing::{arb_ibc_msg_nft_transfer, arb_ibc_msg_transfer}; + use namada_ibc::{MsgNftTransfer, MsgTransfer}; use namada_token::testing::arb_denominated_amount; use namada_token::Transfer; use namada_tx::data::pgf::UpdateStewardCommission; @@ -866,17 +867,15 @@ pub mod testing { use namada_tx::data::{Fee, TxType, WrapperTx}; use proptest::prelude::{Just, Strategy}; use proptest::{arbitrary, collection, option, prop_compose, prop_oneof}; - use prost::Message; - use token::testing::arb_vectorized_transparent_transfer; + use token::testing::arb_transparent_transfer; use super::*; use crate::account::tests::{arb_init_account, arb_update_account}; use crate::chain::ChainId; use crate::eth_bridge_pool::testing::arb_pending_transfer; use crate::key::testing::arb_common_pk; - use crate::masp::testing::{ - arb_deshielding_transfer, arb_shielded_transfer, arb_shielding_transfer, - }; + use crate::masp::testing::arb_shielded_transfer; + use crate::masp::ShieldedTransfer; use crate::time::{DateTime, DateTimeUtc, TimeZone, Utc}; use crate::tx::data::pgf::tests::arb_update_steward_commission; use crate::tx::data::pos::tests::{ @@ -889,7 +888,8 @@ pub mod testing { TxCommitments, }; - #[derive(Debug, Clone)] + #[derive(Debug, Clone, BorshDeserialize, BorshSchema, BorshSerialize)] + #[borsh(crate = "::borsh")] #[allow(clippy::large_enum_variant)] #[allow(missing_docs)] /// To facilitate propagating debugging information @@ -909,14 +909,14 @@ pub mod testing { UpdateAccount(UpdateAccount), VoteProposal(VoteProposalData), Withdraw(Withdraw), - TransparentTransfer(Transfer), - MaspTransfer(Transfer, (StoredBuildParams, String)), + Transfer(Transfer, Option<(StoredBuildParams, String)>), Bond(Bond), Redelegation(Redelegation), UpdateStewardCommission(UpdateStewardCommission), ResignSteward(Address), PendingTransfer(PendingTransfer), - IbcAny(Any), + IbcMsgTransfer(MsgTransfer, Option<(StoredBuildParams, String)>), + IbcMsgNftTransfer(MsgNftTransfer, Option<(StoredBuildParams, String)>), Custom, } @@ -1064,117 +1064,52 @@ pub mod testing { } } - prop_compose! { - /// Generate an arbitrary transfer transaction - pub fn arb_transparent_transfer_tx()( - mut header in arb_header(), - wrapper in arb_wrapper_tx(), - transfer in arb_vectorized_transparent_transfer(10), - code_hash in arb_hash(), - ) -> (Tx, TxData) { - header.tx_type = TxType::Wrapper(Box::new(wrapper)); - let mut tx = Tx { header, sections: vec![] }; - tx.add_data(transfer.clone()); - tx.add_code_from_hash(code_hash, Some(TX_TRANSFER_WASM.to_owned())); - (tx, TxData::TransparentTransfer(transfer)) - } - } - // Maximum number of notes to include in a transaction const MAX_ASSETS: usize = 2; - // Type of MASP transaction - #[derive(Debug, Clone)] - enum MaspTxType { - // Shielded transaction - Shielded, - // Shielding transaction - Shielding, - // Unshielding transaction - Unshielding, + prop_compose! { + /// Generate an arbitrary transfer + pub fn arb_transfer()( + arb in prop_oneof![ + arb_transparent_transfer(..5).prop_map(|xfer| (xfer, None)), + arb_shielded_transfer(0..MAX_ASSETS) + .prop_map(|(w, x, y, z)| (w, Some((x, y, z)))) + ], + ) -> (Transfer, Option<(ShieldedTransfer, HashMap, StoredBuildParams)>) { + arb + } } prop_compose! { /// Generate an arbitrary masp transfer transaction - pub fn arb_masp_transfer_tx()(transfers in arb_vectorized_transparent_transfer(5))( + pub fn arb_transfer_tx()( mut header in arb_header(), wrapper in arb_wrapper_tx(), code_hash in arb_hash(), - (masp_tx_type, (shielded_transfer, asset_types, build_params)) in prop_oneof![ - (Just(MaspTxType::Shielded), arb_shielded_transfer(0..MAX_ASSETS)), - (Just(MaspTxType::Shielding), arb_shielding_transfer(addr_taddr(transfers.sources.keys().next().unwrap().owner.clone()), 1)), - (Just(MaspTxType::Unshielding), arb_deshielding_transfer(addr_taddr(transfers.targets.keys().next().unwrap().owner.clone()), 1)), - ], - transfers in Just(transfers), + (transfer, aux) in arb_transfer(), ) -> (Tx, TxData) { header.tx_type = TxType::Wrapper(Box::new(wrapper)); let mut tx = Tx { header, sections: vec![] }; - let shielded_section_hash = tx.add_masp_tx_section(shielded_transfer.masp_tx).1; - let build_param_bytes = - data_encoding::HEXLOWER.encode(&build_params.serialize_to_vec()); - let tx_data = match masp_tx_type { - MaspTxType::Shielded => { - tx.add_code_from_hash(code_hash, Some(TX_TRANSFER_WASM.to_owned())); - let mut data = Transfer::masp(shielded_section_hash); - if let Some((account, amount)) = transfers.targets.first_key_value() { - data = data.transfer(MASP, account.owner.to_owned(), account.token.to_owned(), *amount).unwrap(); - } - tx.add_data(data.clone()); - TxData::MaspTransfer(data, (build_params, build_param_bytes)) - }, - MaspTxType::Shielding => { - // Set the transparent amount and token - let (decoded, value) = asset_types.iter().next().unwrap(); - let token = decoded.token.clone(); - let amount = DenominatedAmount::new( - token::Amount::from_masp_denominated(*value, decoded.position), - decoded.denom, - ); - tx.add_code_from_hash(code_hash, Some(TX_TRANSFER_WASM.to_owned())); - let data = transfers.sources.into_iter().try_fold( - Transfer::masp(shielded_section_hash), - |acc, transfer| acc.transfer( - transfer.0.owner, - MASP, - token.clone(), - amount, - ), - ).unwrap(); - tx.add_data(data.clone()); - TxData::MaspTransfer(data, (build_params, build_param_bytes)) - }, - MaspTxType::Unshielding => { - // Set the transparent amount and token - let (decoded, value) = asset_types.iter().next().unwrap(); - let token = decoded.token.clone(); - let amount = DenominatedAmount::new( - token::Amount::from_masp_denominated(*value, decoded.position), - decoded.denom, - ); - tx.add_code_from_hash(code_hash, Some(TX_TRANSFER_WASM.to_owned())); - let data = transfers.targets.into_iter().try_fold( - Transfer::masp(shielded_section_hash), - |acc, transfer| acc.transfer( - MASP, - transfer.0.owner, - token.clone(), - amount, - ) - ).unwrap(); - tx.add_data(data.clone()); - TxData::MaspTransfer(data, (build_params, build_param_bytes)) - }, - }; - tx.add_masp_builder(MaspBuilder { - asset_types: asset_types.into_keys().collect(), - // Store how the Info objects map to Descriptors/Outputs - metadata: shielded_transfer.metadata, - // Store the data that was used to construct the Transaction - builder: shielded_transfer.builder, - // Link the Builder to the Transaction by hash code - target: shielded_section_hash, - }); - (tx, tx_data) + tx.add_code_from_hash(code_hash, Some(TX_TRANSFER_WASM.to_owned())); + tx.add_data(transfer.clone()); + if let Some((shielded_transfer, asset_types, build_params)) = aux { + let shielded_section_hash = + tx.add_masp_tx_section(shielded_transfer.masp_tx).1; + tx.add_masp_builder(MaspBuilder { + asset_types: asset_types.into_keys().collect(), + // Store how the Info objects map to Descriptors/Outputs + metadata: shielded_transfer.metadata, + // Store the data that was used to construct the Transaction + builder: shielded_transfer.builder, + // Link the Builder to the Transaction by hash code + target: shielded_section_hash, + }); + let build_param_bytes = + data_encoding::HEXLOWER.encode(&build_params.serialize_to_vec()); + (tx, TxData::Transfer(transfer, Some((build_params, build_param_bytes)))) + } else { + (tx, TxData::Transfer(transfer, None)) + } } } @@ -1532,29 +1467,104 @@ pub mod testing { } } + prop_compose! { + /// Generate an arbitrary IBC transfer message + pub fn arb_msg_transfer()( + message in arb_ibc_msg_transfer(), + transfer_aux in option::of(arb_transfer()), + ) -> (MsgTransfer, Option<(ShieldedTransfer, HashMap, StoredBuildParams)>) { + if let Some((transfer, aux)) = transfer_aux { + (MsgTransfer { message, transfer: Some(transfer) }, aux) + } else { + (MsgTransfer { message, transfer: None }, None) + } + } + } + prop_compose! { /// Generate an arbitrary IBC any transaction - pub fn arb_ibc_any_tx()( + pub fn arb_ibc_msg_transfer_tx()( mut header in arb_header(), wrapper in arb_wrapper_tx(), - ibc_any in arb_ibc_any(), + (msg_transfer, aux) in arb_msg_transfer(), code_hash in arb_hash(), ) -> (Tx, TxData) { header.tx_type = TxType::Wrapper(Box::new(wrapper)); let mut tx = Tx { header, sections: vec![] }; - let mut tx_data = vec![]; - ibc_any.encode(&mut tx_data).expect("unable to encode IBC data"); - tx.add_serialized_data(tx_data); + tx.add_serialized_data(msg_transfer.serialize_to_vec()); tx.add_code_from_hash(code_hash, Some(TX_IBC_WASM.to_owned())); - (tx, TxData::IbcAny(ibc_any)) + if let Some((shielded_transfer, asset_types, build_params)) = aux { + let shielded_section_hash = + tx.add_masp_tx_section(shielded_transfer.masp_tx).1; + tx.add_masp_builder(MaspBuilder { + asset_types: asset_types.into_keys().collect(), + // Store how the Info objects map to Descriptors/Outputs + metadata: shielded_transfer.metadata, + // Store the data that was used to construct the Transaction + builder: shielded_transfer.builder, + // Link the Builder to the Transaction by hash code + target: shielded_section_hash, + }); + let build_param_bytes = + data_encoding::HEXLOWER.encode(&build_params.serialize_to_vec()); + (tx, TxData::IbcMsgTransfer(msg_transfer, Some((build_params, build_param_bytes)))) + } else { + (tx, TxData::IbcMsgTransfer(msg_transfer, None)) + } + } + } + + prop_compose! { + /// Generate an arbitrary IBC NFT transfer message + pub fn arb_msg_nft_transfer()( + message in arb_ibc_msg_nft_transfer(), + transfer_aux in option::of(arb_transfer()), + ) -> (MsgNftTransfer, Option<(ShieldedTransfer, HashMap, StoredBuildParams)>) { + if let Some((transfer, aux)) = transfer_aux { + (MsgNftTransfer { message, transfer: Some(transfer) }, aux) + } else { + (MsgNftTransfer { message, transfer: None }, None) + } + } + } + + prop_compose! { + /// Generate an arbitrary IBC any transaction + pub fn arb_ibc_msg_nft_transfer_tx()( + mut header in arb_header(), + wrapper in arb_wrapper_tx(), + (msg_transfer, aux) in arb_msg_nft_transfer(), + code_hash in arb_hash(), + ) -> (Tx, TxData) { + header.tx_type = TxType::Wrapper(Box::new(wrapper)); + let mut tx = Tx { header, sections: vec![] }; + tx.add_serialized_data(msg_transfer.serialize_to_vec()); + tx.add_code_from_hash(code_hash, Some(TX_IBC_WASM.to_owned())); + if let Some((shielded_transfer, asset_types, build_params)) = aux { + let shielded_section_hash = + tx.add_masp_tx_section(shielded_transfer.masp_tx).1; + tx.add_masp_builder(MaspBuilder { + asset_types: asset_types.into_keys().collect(), + // Store how the Info objects map to Descriptors/Outputs + metadata: shielded_transfer.metadata, + // Store the data that was used to construct the Transaction + builder: shielded_transfer.builder, + // Link the Builder to the Transaction by hash code + target: shielded_section_hash, + }); + let build_param_bytes = + data_encoding::HEXLOWER.encode(&build_params.serialize_to_vec()); + (tx, TxData::IbcMsgNftTransfer(msg_transfer, Some((build_params, build_param_bytes)))) + } else { + (tx, TxData::IbcMsgNftTransfer(msg_transfer, None)) + } } } /// Generate an arbitrary tx pub fn arb_tx() -> impl Strategy { prop_oneof![ - arb_transparent_transfer_tx(), - arb_masp_transfer_tx(), + arb_transfer_tx(), arb_bond_tx(), arb_unbond_tx(), arb_init_account_tx(), @@ -1575,7 +1585,8 @@ pub mod testing { arb_update_steward_commission_tx(), arb_resign_steward_tx(), arb_pending_transfer_tx(), - arb_ibc_any_tx(), + arb_ibc_msg_transfer_tx(), + arb_ibc_msg_nft_transfer_tx(), ] } diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index bcf28db17b..ffee94a11f 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -1,12 +1,18 @@ //! MASP verification wrappers. +#[cfg(test)] +mod test_utils; +pub mod utils; use std::cmp::Ordering; use std::collections::{btree_map, BTreeMap, BTreeSet}; use std::env; use std::fmt::Debug; +use std::io::{Read, Write}; use std::path::PathBuf; +use std::sync::{Arc, Mutex}; use borsh::{BorshDeserialize, BorshSerialize}; +use borsh_ext::BorshSerializeExt; use itertools::Itertools; use masp_primitives::asset_type::AssetType; #[cfg(feature = "mainnet")] @@ -39,6 +45,7 @@ use namada_core::address::Address; use namada_core::arith::CheckedAdd; use namada_core::collections::{HashMap, HashSet}; use namada_core::dec::Dec; +use namada_core::ibc::IbcTxDataRefs; pub use namada_core::masp::{ encode_asset_type, AssetData, BalanceOwner, ExtendedViewingKey, PaymentAddress, TAddrData, TransferSource, TransferTarget, TxId, @@ -48,6 +55,7 @@ use namada_core::storage::{BlockHeight, TxIndex}; use namada_core::time::DateTimeUtc; use namada_core::uint::Uint; use namada_events::extend::{ + IbcMaspTxBatchRefs as IbcMaspTxBatchRefsAttr, MaspTxBatchRefs as MaspTxBatchRefsAttr, MaspTxBlockIndex as MaspTxBlockIndexAttr, ReadFromEventAttributes, }; @@ -66,13 +74,18 @@ use rand_core::{CryptoRng, OsRng, RngCore, SeedableRng}; use smooth_operator::checked; use thiserror::Error; +use crate::control_flow::ShutdownSignal; use crate::error::{Error, QueryError}; use crate::io::Io; +use crate::masp::utils::{ + fetch_channel, FetchQueueSender, MaspClient, ProgressTracker, RetryStrategy, +}; use crate::queries::Client; -use crate::rpc::{ - query_block, query_conversion, query_denom, query_native_token, +use crate::rpc::{query_conversion, query_denom}; +use crate::{ + control_flow, display_line, edisplay_line, query_native_token, rpc, + MaybeSend, MaybeSync, Namada, }; -use crate::{display_line, edisplay_line, rpc, MaybeSend, MaybeSync, Namada}; /// Randomness seed for MASP integration tests to build proofs with /// deterministic rng. @@ -349,34 +362,93 @@ pub type TransferDelta = HashMap; /// Represents the changes that were made to a list of shielded accounts pub type TransactionDelta = HashMap; + /// A cache of fetched indexed transactions. /// -/// The cache is designed so that it either contains -/// all transactions from a given height, or none. -#[derive( - BorshSerialize, BorshDeserialize, BorshDeserializer, Debug, Default, Clone, -)] +/// An invariant that shielded-sync maintains is that +/// this cache either contains all transactions from +/// a given height, or none. +#[derive(Debug, Default, Clone)] pub struct Unscanned { - txs: IndexedNoteData, + txs: Arc>, +} + +impl BorshSerialize for Unscanned { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + let locked = self.txs.lock().unwrap(); + let bytes = locked.serialize_to_vec(); + writer.write(&bytes).map(|_| ()) + } +} + +impl BorshDeserialize for Unscanned { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let unscanned = IndexedNoteData::deserialize_reader(reader)?; + Ok(Self { + txs: Arc::new(Mutex::new(unscanned)), + }) + } } impl Unscanned { - fn extend(&mut self, items: I) + /// Append elements to the cache from an iterator. + pub fn extend(&self, items: I) where I: IntoIterator, { - self.txs.extend(items); + let mut locked = self.txs.lock().unwrap(); + locked.extend(items); } - fn contains_height(&self, height: u64) -> bool { - self.txs.keys().any(|k| k.height.0 == height) + /// Add a single entry to the cache. + pub fn insert(&self, (k, v): IndexedNoteEntry) { + let mut locked = self.txs.lock().unwrap(); + locked.insert(k, v); + } + + /// Check if this cache has already been populated for a given + /// block height. + pub fn contains_height(&self, height: u64) -> bool { + let locked = self.txs.lock().unwrap(); + locked.keys().any(|k| k.height.0 == height) } /// We remove all indices from blocks that have been entirely scanned. /// If a block is only partially scanned, we leave all the events in the /// cache. - fn scanned(&mut self, ix: &IndexedTx) { - self.txs.retain(|i, _| i.height >= ix.height); + pub fn scanned(&self, ix: &IndexedTx) { + let mut locked = self.txs.lock().unwrap(); + locked.retain(|i, _| i.height >= ix.height); + } + + /// Gets the latest block height present in the cache + pub fn latest_height(&self) -> BlockHeight { + let txs = self.txs.lock().unwrap(); + txs.keys() + .max_by_key(|ix| ix.height) + .map(|ix| ix.height) + .unwrap_or_default() + } + + /// Gets the first block height present in the cache + pub fn first_height(&self) -> BlockHeight { + let txs = self.txs.lock().unwrap(); + txs.keys() + .min_by_key(|ix| ix.height) + .map(|ix| ix.height) + .unwrap_or_default() + } + + /// Remove the first entry from the cache and return it. + pub fn pop_first(&self) -> Option { + let mut locked = self.txs.lock().unwrap(); + locked.pop_first() + } + + /// Check if empty + pub fn is_empty(&self) -> bool { + let locked = self.txs.lock().unwrap(); + locked.is_empty() } } @@ -385,10 +457,13 @@ impl IntoIterator for Unscanned { type Item = IndexedNoteEntry; fn into_iter(self) -> Self::IntoIter { - self.txs.into_iter() + let txs = { + let mut locked = self.txs.lock().unwrap(); + std::mem::take(&mut *locked) + }; + txs.into_iter() } } - #[derive(BorshSerialize, BorshDeserialize, Debug)] /// The possible sync states of the shielded context pub enum ContextSyncStatus { @@ -523,18 +598,126 @@ impl ShieldedContext { /// Fetch the current state of the multi-asset shielded pool into a /// ShieldedContext #[allow(clippy::too_many_arguments)] - pub async fn fetch( + #[cfg(not(target_family = "wasm"))] + pub async fn fetch( &mut self, - client: &C, - logger: &impl ProgressLogger, + client: M, + progress: &impl ProgressTracker, start_query_height: Option, last_query_height: Option, - // NOTE: do not remove this argument, it will be used once the indexer - // is ready - _batch_size: u64, + retry: RetryStrategy, sks: &[ExtendedSpendingKey], fvks: &[ViewingKey], - ) -> Result<(), Error> { + ) -> Result<(), Error> + where + IO: Io, + M: MaspClient, + { + let shutdown_signal = control_flow::install_shutdown_signal(); + self.fetch_aux( + client, + progress, + start_query_height, + last_query_height, + retry, + sks, + fvks, + shutdown_signal, + ) + .await + } + + fn min_height_to_sync_from(&self) -> Result { + let Some(maybe_least_synced_vk_height) = + self.vk_heights.values().min().cloned() + else { + return Err(Error::Other( + "No viewing keys are available in the shielded context to \ + decrypt notes with" + .to_string(), + )); + }; + let maybe_last_witnessed_tx = self.tx_note_map.keys().max().cloned(); + let last_height_in_witnesses = std::cmp::min( + maybe_last_witnessed_tx.as_ref(), + maybe_least_synced_vk_height.as_ref(), + ) + .map(|ix| ix.height); + Ok(last_height_in_witnesses.unwrap_or_else(BlockHeight::first)) + } + + #[cfg(not(target_family = "wasm"))] + async fn update_with_pre_built_data( + &mut self, + client: &M, + height: BlockHeight, + ) -> Result<(), Error> + where + M: MaspClient, + { + let tree_fut = async { + if client.capabilities().may_fetch_pre_built_tree() { + client.fetch_commitment_tree(height).await.map(Some) + } else { + Ok(None) + } + }; + let notes_map_fut = async { + if client.capabilities().may_fetch_pre_built_notes_map() { + client.fetch_tx_notes_map(height).await.map(Some) + } else { + Ok(None) + } + }; + let witness_map_fut = async { + if client.capabilities().may_fetch_pre_built_witness_map() { + client.fetch_witness_map(height).await.map(Some) + } else { + Ok(None) + } + }; + + let (maybe_tree, maybe_notes_map, maybe_witness_map) = + futures::try_join!(tree_fut, notes_map_fut, witness_map_fut)?; + + if let Some(tree) = maybe_tree { + self.tree = tree; + } + if let Some(notes_map) = maybe_notes_map { + self.tx_note_map = notes_map; + } + if let Some(witness_map) = maybe_witness_map { + self.witness_map = witness_map; + } + + Ok(()) + } + + #[allow(clippy::too_many_arguments)] + #[cfg(not(target_family = "wasm"))] + async fn fetch_aux( + &mut self, + client: M, + progress: &impl ProgressTracker, + start_query_height: Option, + last_query_height: Option, + retry: RetryStrategy, + sks: &[ExtendedSpendingKey], + fvks: &[ViewingKey], + mut shutdown_signal: ShutdownSignal, + ) -> Result<(), Error> + where + IO: Io, + M: MaspClient, + { + if start_query_height > last_query_height { + return Err(Error::Other(format!( + "The start height {start_query_height:?} cannot be higher \ + than the ending height {last_query_height:?} in the shielded \ + sync" + ))); + } + // add new viewing keys // Reload the state from file to get the last confirmed state and // discard any speculative data, we cannot fetch on top of a @@ -549,7 +732,6 @@ impl ShieldedContext { ..Default::default() }; } - for esk in sks { let vk = to_viewing_key(esk).vk; self.vk_heights.entry(vk).or_default(); @@ -557,181 +739,142 @@ impl ShieldedContext { for vk in fvks { self.vk_heights.entry(*vk).or_default(); } + + // Save the context to persist newly added keys let _ = self.save().await; + // the latest block height which has been added to the witness Merkle // tree - let Some(least_idx) = self.vk_heights.values().min().cloned() else { - return Ok(()); - }; let last_witnessed_tx = self.tx_note_map.keys().max().cloned(); - // get the bounds on the block heights to fetch - let start_idx = - std::cmp::min(last_witnessed_tx.as_ref(), least_idx.as_ref()) - .map(|ix| ix.height); - let start_idx = start_query_height.or(start_idx); - // Load all transactions accepted until this point - // N.B. the cache is a hash map - self.unscanned.extend( - self.fetch_shielded_transfers( - client, - logger, - start_idx, - last_query_height, - ) - .await?, - ); - // persist the cache in case of interruptions. - let _ = self.save().await; - - let txs = logger.scan(self.unscanned.clone()); - for (ref indexed_tx, ref stx) in txs { - if Some(indexed_tx) > last_witnessed_tx.as_ref() { - self.update_witness_map(indexed_tx.to_owned(), stx)?; - } - let mut vk_heights = BTreeMap::new(); - std::mem::swap(&mut vk_heights, &mut self.vk_heights); - for (vk, h) in vk_heights - .iter_mut() - .filter(|(_vk, h)| h.as_ref() < Some(indexed_tx)) - { - self.scan_tx(indexed_tx.to_owned(), stx, vk)?; - *h = Some(indexed_tx.to_owned()); - } - // possibly remove unneeded elements from the cache. - self.unscanned.scanned(indexed_tx); - std::mem::swap(&mut vk_heights, &mut self.vk_heights); - let _ = self.save().await; - } - Ok(()) - } - - /// Obtain a chronologically-ordered list of all accepted shielded - /// transactions from a node. - pub async fn fetch_shielded_transfers( - &self, - client: &C, - logger: &impl ProgressLogger, - last_indexed_tx: Option, - last_query_height: Option, - ) -> Result { // Query for the last produced block height - let last_block_height = query_block(client) - .await? - .map_or_else(BlockHeight::first, |block| block.height); - let last_query_height = last_query_height.unwrap_or(last_block_height); + let Some(last_block_height) = client.last_block_height().await? else { + return Err(Error::Other( + "No block has been committed yet".to_string(), + )); + }; - let mut shielded_txs = BTreeMap::new(); - // Fetch all the transactions we do not have yet - let first_height_to_query = - last_indexed_tx.map_or_else(|| 1, |last| last.0); - let heights = logger.fetch(first_height_to_query..=last_query_height.0); - for height in heights { - if self.unscanned.contains_height(height) { - continue; - } + let last_query_height = last_query_height + .unwrap_or(last_block_height) + // NB: limit fetching until the last committed height + .min(last_block_height); - let txs_results = match get_indexed_masp_events_at_height( - client, - height.into(), - None, - ) - .await? - { - Some(events) => events, - None => continue, - }; + let mut start_height = start_query_height + .map_or_else(|| self.min_height_to_sync_from(), Ok)? + // NB: the start height cannot be greater than + // `last_query_height` + .min(last_query_height); - // Query the actual block to get the txs bytes. If we only need one - // tx it might be slightly better to query the /tx endpoint to - // reduce the amount of data sent over the network, but this is a - // minimal improvement and it's even hard to tell how many times - // we'd need a single masp tx to make this worth it - let block = client - .block(height) - .await - .map_err(|e| Error::from(QueryError::General(e.to_string())))? - .block - .data; + self.update_with_pre_built_data(&client, last_query_height) + .await?; - for (idx, masp_sections_refs) in txs_results { - let tx = Tx::try_from(block[idx.0 as usize].as_ref()) - .map_err(|e| Error::Other(e.to_string()))?; - let extracted_masp_txs = - if let Some(masp_sections_refs) = masp_sections_refs { - Self::extract_masp_tx(&tx, &masp_sections_refs).await? - } else { - Self::extract_masp_tx_from_ibc_message(&tx)? - }; - // Collect the current transactions - shielded_txs.insert( - IndexedTx { - height: height.into(), - index: idx, - }, - extracted_masp_txs, - ); + for _ in retry { + debug_assert!(start_height <= last_query_height); + + // a stateful channel that communicates notes fetched to the trial + // decryption process + let (fetch_send, fetch_recv) = + fetch_channel::new(self.unscanned.clone()); + let fetch_res = self + .fetch_shielded_transfers( + &client, + progress, + &mut shutdown_signal, + fetch_send, + start_height, + last_query_height, + ) + .await; + // if fetching errored, log it. But this is recoverable. + match fetch_res { + Err(e @ Error::Interrupt(_)) => { + display_line!(progress.io(), "{}", e.to_string(),); + return Err(e); + } + Err(e) => display_line!( + progress.io(), + "Error encountered while fetching: {}", + e.to_string(), + ), + _ => {} } - } - - Ok(shielded_txs) - } - - /// Extract the relevant shield portions of a [`Tx`], if any. - async fn extract_masp_tx( - tx: &Tx, - masp_section_refs: &MaspTxRefs, - ) -> Result, Error> { - // NOTE: simply looking for masp sections attached to the tx - // is not safe. We don't validate the sections attached to a - // transaction se we could end up with transactions carrying - // an unnecessary masp section. We must instead look for the - // required masp sections coming from the events - - masp_section_refs - .0 - .iter() - .try_fold(vec![], |mut acc, hash| { - match tx.get_masp_section(hash).cloned().ok_or_else(|| { - Error::Other( - "Missing expected masp transaction".to_string(), - ) - }) { - Ok(transaction) => { - acc.push(transaction); - Ok(acc) - } - Err(e) => Err(e), + let txs = progress.scan(fetch_recv); + for (ref indexed_tx, ref stx) in txs { + if client.capabilities().needs_witness_map_update() + && Some(indexed_tx) > last_witnessed_tx.as_ref() + { + self.update_witness_map(indexed_tx.to_owned(), stx)?; } - }) - } - - /// Extract the relevant shield portions from the IBC messages in [`Tx`] - fn extract_masp_tx_from_ibc_message( - tx: &Tx, - ) -> Result, Error> { - let mut masp_txs = Vec::new(); - for cmt in &tx.header.batch { - let tx_data = tx.data(cmt).ok_or_else(|| { - Error::Other("Missing transaction data".to_string()) - })?; - let ibc_msg = decode_message(&tx_data) - .map_err(|_| Error::Other("Invalid IBC message".to_string()))?; - if let IbcMessage::Envelope(ref envelope) = ibc_msg { - if let Some(masp_tx) = extract_masp_tx_from_envelope(envelope) { - masp_txs.push(masp_tx); + let mut vk_heights = BTreeMap::new(); + std::mem::swap(&mut vk_heights, &mut self.vk_heights); + for (vk, h) in vk_heights + .iter_mut() + .filter(|(_vk, h)| h.as_ref() < Some(indexed_tx)) + { + self.scan_tx(indexed_tx.to_owned(), stx, vk)?; + *h = Some(indexed_tx.to_owned()); + } + // possibly remove unneeded elements from the cache. + self.unscanned.scanned(indexed_tx); + std::mem::swap(&mut vk_heights, &mut self.vk_heights); + if shutdown_signal.received() { + let _ = self.save().await; + return Err(Error::Interrupt( + "[ShieldedSync::Scanning]".to_string(), + )); } } + + // If fetching failed before completing, we restart + // the process from the height we managed to sync to. + // Otherwise, we can break the loop. + if progress.left_to_fetch() == 0 { + break; + } + + start_height = self.min_height_to_sync_from()?.clamp( + start_query_height.unwrap_or_else(BlockHeight::first), + last_query_height, + ); } - if !masp_txs.is_empty() { - Ok(masp_txs) - } else { + _ = self.save().await; + + if progress.left_to_fetch() != 0 { Err(Error::Other( - "IBC message doesn't have masp transaction".to_string(), + "After retrying, could not fetch all MASP txs.".to_string(), )) + } else { + Ok(()) } } + /// Obtain a chronologically-ordered list of all accepted shielded + /// transactions from a node. + async fn fetch_shielded_transfers( + &self, + client: &M, + progress: &impl ProgressTracker, + shutdown_signal: &mut ShutdownSignal, + block_sender: FetchQueueSender, + last_indexed_tx: BlockHeight, + last_query_height: BlockHeight, + ) -> Result<(), Error> { + // Fetch all the transactions we do not have yet + let first_height_to_query = last_indexed_tx; + let res = client + .fetch_shielded_transfers( + progress, + shutdown_signal, + block_sender, + first_height_to_query, + last_query_height, + ) + .await; + // persist fetched notes + _ = self.save().await; + res + } + /// Applies the given transaction to the supplied context. More precisely, /// the shielded transaction's outputs are added to the commitment tree. /// Newly discovered notes are associated to the supplied viewing keys. Note @@ -746,6 +889,13 @@ impl ShieldedContext { shielded: &[Transaction], vk: &ViewingKey, ) -> Result<(), Error> { + type Proof = OutputDescription< + < + ::SaplingAuth + as masp_primitives::transaction::components::sapling::Authorization + >::Proof + >; + // For tracking the account changes caused by this Transaction let mut transaction_delta = TransactionDelta::new(); if let ContextSyncStatus::Confirmed = self.sync_status { @@ -759,12 +909,12 @@ impl ShieldedContext { // Let's try to see if this viewing key can decrypt latest // note let notes = self.pos_map.entry(*vk).or_default(); - let decres = try_sapling_note_decryption::<_, OutputDescription<<::SaplingAuth as masp_primitives::transaction::components::sapling::Authorization>::Proof>>( - &NETWORK, - 1.into(), - &PreparedIncomingViewingKey::new(&vk.ivk()), - so, - ); + let decres = try_sapling_note_decryption::<_, Proof>( + &NETWORK, + 1.into(), + &PreparedIncomingViewingKey::new(&vk.ivk()), + so, + ); // So this current viewing key does decrypt this current // note... if let Some((note, pa, memo)) = decres { @@ -2356,6 +2506,59 @@ impl ShieldedContext { } } +/// Extract the relevant shield portions of a [`Tx`], if any. +async fn extract_masp_tx( + tx: &Tx, + masp_section_refs: &MaspTxRefs, +) -> Result, Error> { + // NOTE: simply looking for masp sections attached to the tx + // is not safe. We don't validate the sections attached to a + // transaction se we could end up with transactions carrying + // an unnecessary masp section. We must instead look for the + // required masp sections coming from the events + + masp_section_refs + .0 + .iter() + .try_fold(vec![], |mut acc, hash| { + match tx.get_masp_section(hash).cloned().ok_or_else(|| { + Error::Other("Missing expected masp transaction".to_string()) + }) { + Ok(transaction) => { + acc.push(transaction); + Ok(acc) + } + Err(e) => Err(e), + } + }) +} + +/// Extract the relevant shield portions from the IBC messages in [`Tx`] +fn extract_masp_tx_from_ibc_message( + tx: &Tx, +) -> Result, Error> { + let mut masp_txs = Vec::new(); + for cmt in &tx.header.batch { + let tx_data = tx.data(cmt).ok_or_else(|| { + Error::Other("Missing transaction data".to_string()) + })?; + let ibc_msg = decode_message(&tx_data) + .map_err(|_| Error::Other("Invalid IBC message".to_string()))?; + if let IbcMessage::Envelope(ref envelope) = ibc_msg { + if let Some(masp_tx) = extract_masp_tx_from_envelope(envelope) { + masp_txs.push(masp_tx); + } + } + } + if !masp_txs.is_empty() { + Ok(masp_txs) + } else { + Err(Error::Other( + "IBC message doesn't have masp transaction".to_string(), + )) + } +} + // Retrieves all the indexes at the specified height which refer // to a valid masp transaction. If an index is given, it filters only the // transactions with an index equal or greater to the provided one. @@ -2363,7 +2566,10 @@ async fn get_indexed_masp_events_at_height( client: &C, height: BlockHeight, first_idx_to_query: Option, -) -> Result)>>, Error> { +) -> Result< + Option, Option)>>, + Error, +> { let first_idx_to_query = first_idx_to_query.unwrap_or_default(); Ok(client @@ -2388,8 +2594,13 @@ async fn get_indexed_masp_events_at_height( &event.attributes, ) .ok(); + let ibc_tx_data_refs = + IbcMaspTxBatchRefsAttr::read_from_event_attributes( + &event.attributes, + ) + .ok(); - Some((tx_index, masp_section_refs)) + Some((tx_index, masp_section_refs, ibc_tx_data_refs)) } else { None } @@ -2528,6 +2739,8 @@ pub mod testing { use masp_proofs::bellman::groth16::Proof; use masp_proofs::bls12_381; use masp_proofs::bls12_381::{Bls12, G1Affine, G2Affine}; + use namada_core::address::testing::arb_non_internal_address; + use namada_token::{DenominatedAmount, Transfer}; use proptest::prelude::*; use proptest::sample::SizeRange; use proptest::test_runner::TestRng; @@ -2535,6 +2748,7 @@ pub mod testing { use super::*; use crate::address::testing::arb_address; + use crate::address::MASP; use crate::masp_primitives::consensus::BranchId; use crate::masp_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR; use crate::masp_primitives::merkle_tree::FrozenCommitmentTree; @@ -3024,11 +3238,26 @@ pub mod testing { .iter() .map(|(asset, values)| arb_output_descriptions(asset.clone(), values.clone())) .collect::>(), + input_data in collection::vec((any::(), arb_non_internal_address()), assets.len() * MAX_SPLITS), + output_data in collection::vec((any::(), arb_non_internal_address()), assets.len() * MAX_SPLITS), assets in Just(assets), ) -> ( + Transfer, Builder::, HashMap, ) { + // Enable assets to be more easily decoded + let mut asset_decoder = BTreeMap::new(); + for asset_data in assets.keys() { + let asset_type = encode_asset_type( + asset_data.token.clone(), + asset_data.denom, + asset_data.position, + asset_data.epoch, + ).unwrap(); + asset_decoder.insert(asset_type, asset_data); + } + let mut transfer = Transfer::default(); let mut builder = Builder::::new( NETWORK, // NOTE: this is going to add 20 more blocks to the actual @@ -3043,13 +3272,52 @@ pub mod testing { } let tree = FrozenCommitmentTree::new(&leaves); // Then use the notes knowing that they all have the same anchor - for (idx, (esk, div, note, _node)) in spend_descriptions.iter().flatten().enumerate() { - builder.add_sapling_spend(*esk, *div, *note, tree.path(idx)).unwrap(); + for ((is_shielded, address), (idx, (esk, div, note, _node))) in + input_data.into_iter().zip(spend_descriptions.iter().flatten().enumerate()) + { + // Compute the equivalent transparent movement + let asset_data = asset_decoder[¬e.asset_type]; + let amount = DenominatedAmount::new( + token::Amount::from_masp_denominated(note.value, asset_data.position), + asset_data.denom, + ); + // Use either a transparent input or a shielded input + if is_shielded { + builder.add_sapling_spend(*esk, *div, *note, tree.path(idx)).unwrap(); + transfer = transfer.debit(MASP, asset_data.token.clone(), amount).unwrap(); + } else { + let txout = TxOut { + address: TAddrData::Addr(address.clone()).taddress(), + asset_type: note.asset_type, + value: note.value, + }; + builder.add_transparent_input(txout).unwrap(); + transfer = transfer.debit(address, asset_data.token.clone(), amount).unwrap(); + } } - for (ovk, payment_addr, asset_type, value, memo) in output_descriptions.into_iter().flatten() { - builder.add_sapling_output(ovk, payment_addr, asset_type, value, memo).unwrap(); + for ((is_shielded, address), (ovk, payment_addr, asset_type, value, memo)) in + output_data.into_iter().zip(output_descriptions.into_iter().flatten()) + { + // Compute the equivalent transparent movement + let asset_data = asset_decoder[&asset_type]; + let amount = DenominatedAmount::new( + token::Amount::from_masp_denominated(value, asset_data.position), + asset_data.denom, + ); + // Use either a transparent output or a shielded output + if is_shielded { + builder.add_sapling_output(ovk, payment_addr, asset_type, value, memo).unwrap(); + transfer = transfer.credit(MASP, asset_data.token.clone(), amount).unwrap(); + } else { + builder.add_transparent_output( + &TAddrData::Addr(address.clone()).taddress(), + asset_type, + value, + ).unwrap(); + transfer = transfer.credit(address, asset_data.token.clone(), amount).unwrap(); + } } - (builder, assets.into_iter().map(|(k, v)| (k, v.iter().sum())).collect()) + (transfer, builder, assets.into_iter().map(|(k, v)| (k, v.iter().sum())).collect()) } } @@ -3077,172 +3345,17 @@ pub mod testing { } } - prop_compose! { - /// Generate an arbitrary shielding MASP transaction builder - pub fn arb_shielding_builder( - source: TransparentAddress, - asset_range: impl Into, - )( - assets in collection::hash_map( - arb_pre_asset_type(), - collection::vec(..MAX_MONEY, ..MAX_SPLITS), - asset_range, - ), - )( - expiration_height in arb_height(BranchId::MASP, &Network), - txins in assets - .iter() - .map(|(asset, values)| arb_txouts(asset.clone(), values.clone(), source)) - .collect::>(), - output_descriptions in assets - .iter() - .map(|(asset, values)| arb_output_descriptions(asset.clone(), values.clone())) - .collect::>(), - assets in Just(assets), - ) -> ( - Builder::, - HashMap, - ) { - let mut builder = Builder::::new( - NETWORK, - // NOTE: this is going to add 20 more blocks to the actual - // expiration but there's no other exposed function that we could - // use from the masp crate to specify the expiration better - expiration_height.unwrap(), - ); - for txin in txins.into_iter().flatten() { - builder.add_transparent_input(txin).unwrap(); - } - for (ovk, payment_addr, asset_type, value, memo) in output_descriptions.into_iter().flatten() { - builder.add_sapling_output(ovk, payment_addr, asset_type, value, memo).unwrap(); - } - (builder, assets.into_iter().map(|(k, v)| (k, v.iter().sum())).collect()) - } - } - - prop_compose! { - /// Generate an arbitrary deshielding MASP transaction builder - pub fn arb_deshielding_builder( - target: TransparentAddress, - asset_range: impl Into, - )( - assets in collection::hash_map( - arb_pre_asset_type(), - collection::vec(..MAX_MONEY, ..MAX_SPLITS), - asset_range, - ), - )( - expiration_height in arb_height(BranchId::MASP, &Network), - spend_descriptions in assets - .iter() - .map(|(asset, values)| arb_spend_descriptions(asset.clone(), values.clone())) - .collect::>(), - txouts in assets - .iter() - .map(|(asset, values)| arb_txouts(asset.clone(), values.clone(), target)) - .collect::>(), - assets in Just(assets), - ) -> ( - Builder::, - HashMap, - ) { - let mut builder = Builder::::new( - NETWORK, - // NOTE: this is going to add 20 more blocks to the actual - // expiration but there's no other exposed function that we could - // use from the masp crate to specify the expiration better - expiration_height.unwrap(), - ); - let mut leaves = Vec::new(); - // First construct a Merkle tree containing all notes to be used - for (_esk, _div, _note, node) in spend_descriptions.iter().flatten() { - leaves.push(*node); - } - let tree = FrozenCommitmentTree::new(&leaves); - // Then use the notes knowing that they all have the same anchor - for (idx, (esk, div, note, _node)) in spend_descriptions.into_iter().flatten().enumerate() { - builder.add_sapling_spend(esk, div, note, tree.path(idx)).unwrap(); - } - for txout in txouts.into_iter().flatten() { - builder.add_transparent_output(&txout.address, txout.asset_type, txout.value).unwrap(); - } - (builder, assets.into_iter().map(|(k, v)| (k, v.iter().sum())).collect()) - } - } - prop_compose! { /// Generate an arbitrary MASP shielded transfer pub fn arb_shielded_transfer( asset_range: impl Into, )(asset_range in Just(asset_range.into()))( - (builder, asset_types) in arb_shielded_builder(asset_range), - epoch in arb_masp_epoch(), - prover_rng in arb_rng().prop_map(TestCsprng), - mut rng in arb_rng().prop_map(TestCsprng), - bparams_rng in arb_rng().prop_map(TestCsprng), - ) -> (ShieldedTransfer, HashMap, StoredBuildParams) { - let mut rng_build_params = RngBuildParams::new(bparams_rng); - let (masp_tx, metadata) = builder.clone().build( - &MockTxProver(Mutex::new(prover_rng)), - &FeeRule::non_standard(U64Sum::zero()), - &mut rng, - &mut rng_build_params, - ).unwrap(); - (ShieldedTransfer { - builder: builder.map_builder(WalletMap), - metadata, - masp_tx, - epoch, - }, asset_types, rng_build_params.to_stored().unwrap()) - } - } - - prop_compose! { - /// Generate an arbitrary MASP shielded transfer - pub fn arb_shielding_transfer( - source: TransparentAddress, - asset_range: impl Into, - )(asset_range in Just(asset_range.into()))( - (builder, asset_types) in arb_shielding_builder( - source, - asset_range, - ), - epoch in arb_masp_epoch(), - prover_rng in arb_rng().prop_map(TestCsprng), - mut rng in arb_rng().prop_map(TestCsprng), - bparams_rng in arb_rng().prop_map(TestCsprng), - ) -> (ShieldedTransfer, HashMap, StoredBuildParams) { - let mut rng_build_params = RngBuildParams::new(bparams_rng); - let (masp_tx, metadata) = builder.clone().build( - &MockTxProver(Mutex::new(prover_rng)), - &FeeRule::non_standard(U64Sum::zero()), - &mut rng, - &mut rng_build_params, - ).unwrap(); - (ShieldedTransfer { - builder: builder.map_builder(WalletMap), - metadata, - masp_tx, - epoch, - }, asset_types, rng_build_params.to_stored().unwrap()) - } - } - - prop_compose! { - /// Generate an arbitrary MASP shielded transfer - pub fn arb_deshielding_transfer( - target: TransparentAddress, - asset_range: impl Into, - )(asset_range in Just(asset_range.into()))( - (builder, asset_types) in arb_deshielding_builder( - target, - asset_range, - ), + (mut transfer, builder, asset_types) in arb_shielded_builder(asset_range), epoch in arb_masp_epoch(), prover_rng in arb_rng().prop_map(TestCsprng), mut rng in arb_rng().prop_map(TestCsprng), bparams_rng in arb_rng().prop_map(TestCsprng), - ) -> (ShieldedTransfer, HashMap, StoredBuildParams) { + ) -> (Transfer, ShieldedTransfer, HashMap, StoredBuildParams) { let mut rng_build_params = RngBuildParams::new(bparams_rng); let (masp_tx, metadata) = builder.clone().build( &MockTxProver(Mutex::new(prover_rng)), @@ -3250,7 +3363,8 @@ pub mod testing { &mut rng, &mut rng_build_params, ).unwrap(); - (ShieldedTransfer { + transfer.shielded_section_hash = Some(masp_tx.txid().into()); + (transfer, ShieldedTransfer { builder: builder.map_builder(WalletMap), metadata, masp_tx, @@ -3434,66 +3548,547 @@ pub mod fs { } } -/// A enum to indicate how to log sync progress depending on -/// whether sync is currently fetch or scanning blocks. -#[derive(Debug, Copy, Clone)] -pub enum ProgressType { - /// Fetch - Fetch, - /// Scan - Scan, -} +#[cfg(test)] +mod test_shielded_sync { + use core::str::FromStr; + use std::collections::BTreeSet; + + use borsh::BorshDeserialize; + use masp_primitives::transaction::Transaction; + use masp_primitives::zip32::ExtendedFullViewingKey; + use namada_core::masp::ExtendedViewingKey; + use namada_core::storage::{BlockHeight, TxIndex}; + use namada_tx::IndexedTx; + use tempfile::tempdir; + + use crate::control_flow::testing_shutdown_signal; + use crate::error::Error; + use crate::io::StdIo; + use crate::masp::fs::FsShieldedUtils; + use crate::masp::test_utils::{ + test_client, TestUnscannedTracker, TestingMaspClient, + }; + use crate::masp::utils::{DefaultTracker, ProgressTracker, RetryStrategy}; + + // A viewing key derived from A_SPENDING_KEY + pub const AA_VIEWING_KEY: &str = "zvknam1qqqqqqqqqqqqqq9v0sls5r5de7njx8ehu49pqgmqr9ygelg87l5x8y4s9r0pjlvu6x74w9gjpw856zcu826qesdre628y6tjc26uhgj6d9zqur9l5u3p99d9ggc74ald6s8y3sdtka74qmheyqvdrasqpwyv2fsmxlz57lj4grm2pthzj3sflxc0jx0edrakx3vdcngrfjmru8ywkguru8mxss2uuqxdlglaz6undx5h8w7g70t2es850g48xzdkqay5qs0yw06rtxcpjdve6"; + + /// A serialized transaction that will work for testing. + /// Would love to do this in a less opaque fashion, but + /// making these things is a misery not worth my time. + /// + /// This a tx sending 1 BTC from Albert to Albert's PA, + /// that was extracted from a masp integration test. + /// + /// ```ignore + /// vec![ + /// "shield", + /// "--source", + /// ALBERT, + /// "--target", + /// AA_PAYMENT_ADDRESS, + /// "--token", + /// BTC, + /// "--amount", + /// "1", + /// "--node", + /// validator_one_rpc, + /// ] + /// ``` + fn arbitrary_masp_tx() -> Transaction { + Transaction::try_from_slice(&[ + 2, 0, 0, 0, 10, 39, 167, 38, 166, 117, 255, 233, 0, 0, 0, 0, 255, + 255, 255, 255, 1, 162, 120, 217, 193, 173, 117, 92, 126, 107, 199, + 182, 72, 95, 60, 122, 52, 9, 134, 72, 4, 167, 41, 187, 171, 17, + 124, 114, 84, 191, 75, 37, 2, 0, 225, 245, 5, 0, 0, 0, 0, 93, 213, + 181, 21, 38, 32, 230, 52, 155, 4, 203, 26, 70, 63, 59, 179, 142, 7, + 72, 76, 0, 0, 0, 1, 132, 100, 41, 23, 128, 97, 116, 40, 195, 40, + 46, 55, 79, 106, 234, 32, 4, 216, 106, 88, 173, 65, 140, 99, 239, + 71, 103, 201, 111, 149, 166, 13, 73, 224, 253, 98, 27, 199, 11, + 142, 56, 214, 4, 96, 35, 72, 83, 86, 194, 107, 163, 194, 238, 37, + 19, 171, 8, 129, 53, 246, 64, 220, 155, 47, 177, 165, 109, 232, 84, + 247, 128, 184, 40, 26, 113, 196, 190, 181, 57, 213, 45, 144, 46, + 12, 145, 128, 169, 116, 65, 51, 208, 239, 50, 217, 224, 98, 179, + 53, 18, 130, 183, 114, 225, 21, 34, 175, 144, 125, 239, 240, 82, + 100, 174, 1, 192, 32, 187, 208, 205, 31, 108, 59, 87, 201, 148, + 214, 244, 255, 8, 150, 100, 225, 11, 245, 221, 170, 85, 241, 110, + 50, 90, 151, 210, 169, 41, 3, 23, 160, 196, 117, 211, 217, 121, 9, + 42, 236, 19, 149, 94, 62, 163, 222, 172, 128, 197, 56, 100, 233, + 227, 239, 60, 182, 191, 55, 148, 17, 0, 168, 198, 84, 87, 191, 89, + 229, 9, 129, 165, 98, 200, 127, 225, 192, 58, 0, 92, 104, 97, 26, + 125, 169, 209, 40, 170, 29, 93, 16, 114, 174, 23, 233, 218, 112, + 26, 175, 196, 198, 197, 159, 167, 157, 16, 232, 247, 193, 44, 82, + 143, 238, 179, 77, 87, 153, 3, 33, 207, 215, 142, 104, 179, 17, + 252, 148, 215, 150, 76, 56, 169, 13, 240, 4, 195, 221, 45, 250, 24, + 51, 243, 174, 176, 47, 117, 38, 1, 124, 193, 191, 55, 11, 164, 97, + 83, 188, 92, 202, 229, 106, 236, 165, 85, 236, 95, 255, 28, 71, 18, + 173, 202, 47, 63, 226, 129, 203, 154, 54, 155, 177, 161, 106, 210, + 220, 193, 142, 44, 105, 46, 164, 83, 136, 63, 24, 172, 157, 117, 9, + 202, 99, 223, 144, 36, 26, 154, 84, 175, 119, 12, 102, 71, 33, 14, + 131, 250, 86, 215, 153, 18, 94, 213, 61, 196, 67, 132, 204, 89, + 235, 241, 188, 147, 236, 92, 46, 83, 169, 236, 12, 34, 33, 65, 243, + 18, 23, 29, 41, 252, 207, 17, 196, 55, 56, 141, 158, 116, 227, 195, + 159, 233, 72, 26, 69, 72, 213, 50, 101, 161, 127, 213, 35, 210, + 223, 201, 219, 198, 192, 125, 129, 222, 178, 241, 116, 59, 255, 72, + 163, 46, 21, 222, 74, 202, 117, 217, 22, 188, 203, 2, 150, 38, 78, + 78, 250, 45, 36, 225, 240, 227, 115, 33, 114, 189, 25, 9, 219, 239, + 57, 103, 19, 109, 11, 5, 156, 43, 35, 53, 219, 250, 215, 185, 173, + 11, 101, 221, 29, 130, 74, 110, 225, 183, 77, 13, 52, 90, 183, 93, + 212, 175, 132, 21, 229, 109, 188, 124, 103, 3, 39, 174, 140, 115, + 67, 49, 100, 231, 129, 32, 24, 201, 196, 247, 33, 155, 20, 139, 34, + 3, 183, 12, 164, 6, 10, 219, 207, 151, 160, 4, 201, 160, 12, 156, + 82, 142, 226, 19, 134, 144, 53, 220, 140, 61, 74, 151, 129, 102, + 214, 73, 107, 147, 4, 98, 68, 79, 225, 103, 242, 187, 170, 102, + 225, 114, 4, 87, 96, 7, 212, 150, 127, 211, 158, 54, 86, 15, 191, + 21, 116, 202, 195, 60, 65, 134, 22, 2, 44, 133, 64, 181, 121, 66, + 218, 227, 72, 148, 63, 108, 227, 33, 66, 239, 77, 127, 139, 31, 16, + 150, 119, 198, 119, 229, 88, 188, 113, 80, 222, 86, 122, 181, 142, + 186, 130, 125, 236, 166, 95, 134, 243, 128, 65, 169, 33, 65, 73, + 182, 183, 156, 248, 39, 46, 199, 181, 85, 96, 126, 155, 189, 10, + 211, 145, 230, 94, 69, 232, 74, 87, 211, 46, 216, 30, 24, 38, 104, + 192, 165, 28, 73, 36, 227, 194, 41, 168, 5, 181, 176, 112, 67, 92, + 158, 212, 129, 207, 182, 223, 59, 185, 84, 210, 147, 32, 29, 61, + 56, 185, 21, 156, 114, 34, 115, 29, 25, 89, 152, 56, 55, 238, 43, + 0, 114, 89, 79, 95, 104, 143, 180, 51, 53, 108, 223, 236, 59, 47, + 188, 174, 196, 101, 180, 207, 162, 198, 104, 52, 67, 132, 178, 9, + 40, 10, 88, 206, 25, 132, 60, 136, 13, 213, 223, 81, 196, 131, 118, + 15, 53, 125, 165, 177, 170, 170, 17, 94, 53, 151, 51, 16, 170, 23, + 118, 255, 26, 46, 47, 37, 73, 165, 26, 43, 10, 221, 4, 132, 15, 78, + 214, 161, 3, 220, 10, 87, 139, 85, 61, 39, 131, 242, 216, 235, 52, + 93, 46, 180, 196, 151, 54, 207, 80, 223, 90, 252, 77, 10, 122, 175, + 229, 7, 144, 41, 1, 162, 120, 217, 193, 173, 117, 92, 126, 107, + 199, 182, 72, 95, 60, 122, 52, 9, 134, 72, 4, 167, 41, 187, 171, + 17, 124, 114, 84, 191, 75, 37, 2, 0, 31, 10, 250, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 151, 241, 211, 167, + 49, 151, 215, 148, 38, 149, 99, 140, 79, 169, 172, 15, 195, 104, + 140, 79, 151, 116, 185, 5, 161, 78, 58, 63, 23, 27, 172, 88, 108, + 85, 232, 63, 249, 122, 26, 239, 251, 58, 240, 10, 219, 34, 198, + 187, 147, 224, 43, 96, 82, 113, 159, 96, 125, 172, 211, 160, 136, + 39, 79, 101, 89, 107, 208, 208, 153, 32, 182, 26, 181, 218, 97, + 187, 220, 127, 80, 73, 51, 76, 241, 18, 19, 148, 93, 87, 229, 172, + 125, 5, 93, 4, 43, 126, 2, 74, 162, 178, 240, 143, 10, 145, 38, 8, + 5, 39, 45, 197, 16, 81, 198, 228, 122, 212, 250, 64, 59, 2, 180, + 81, 11, 100, 122, 227, 209, 119, 11, 172, 3, 38, 168, 5, 187, 239, + 212, 128, 86, 200, 193, 33, 189, 184, 151, 241, 211, 167, 49, 151, + 215, 148, 38, 149, 99, 140, 79, 169, 172, 15, 195, 104, 140, 79, + 151, 116, 185, 5, 161, 78, 58, 63, 23, 27, 172, 88, 108, 85, 232, + 63, 249, 122, 26, 239, 251, 58, 240, 10, 219, 34, 198, 187, 37, + 197, 248, 90, 113, 62, 149, 117, 145, 118, 42, 241, 60, 208, 83, + 57, 96, 143, 17, 128, 92, 118, 158, 188, 77, 37, 184, 164, 135, + 246, 196, 57, 198, 106, 139, 33, 15, 207, 0, 101, 143, 92, 178, + 132, 19, 106, 221, 246, 176, 100, 20, 114, 26, 55, 163, 14, 173, + 255, 121, 181, 58, 121, 140, 3, + ]) + .expect("Test failed") + } + + /// Test that if fetching fails before finishing, + /// we re-establish the fetching process + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_retry_fetch() { + let temp_dir = tempdir().unwrap(); + let mut shielded_ctx = + FsShieldedUtils::new(temp_dir.path().to_path_buf()); + let (client, masp_tx_sender) = test_client(2.into()); + let io = StdIo; + let progress = DefaultTracker::new(&io); + let vk = ExtendedFullViewingKey::from( + ExtendedViewingKey::from_str(AA_VIEWING_KEY).expect("Test failed"), + ) + .fvk + .vk; + masp_tx_sender.send(None).expect("Test failed"); + + // we first test that with no retries, a fetching failure + // stops process + let result = shielded_ctx + .fetch( + TestingMaspClient::new(&client), + &progress, + None, + None, + RetryStrategy::Times(1), + &[], + &[vk], + ) + .await + .unwrap_err(); + match result { + Error::Other(msg) => assert_eq!( + msg.as_str(), + "After retrying, could not fetch all MASP txs." + ), + other => panic!("{:?} does not match Error::Other(_)", other), + } -#[allow(missing_docs)] -pub trait ProgressLogger { - type Fetch: Iterator; - type Scan: Iterator; + // We now have a fetch failure followed by two successful + // masp txs from the same block. + let masp_tx = arbitrary_masp_tx(); + masp_tx_sender.send(None).expect("Test failed"); + masp_tx_sender + .send(Some(( + IndexedTx { + height: 1.into(), + index: TxIndex(1), + }, + vec![masp_tx.clone()], + ))) + .expect("Test failed"); + masp_tx_sender + .send(Some(( + IndexedTx { + height: 1.into(), + index: TxIndex(2), + }, + vec![masp_tx.clone()], + ))) + .expect("Test failed"); + + // This should complete successfully + shielded_ctx + .fetch( + TestingMaspClient::new(&client), + &progress, + None, + None, + RetryStrategy::Times(2), + &[], + &[vk], + ) + .await + .expect("Test failed"); + + shielded_ctx.load_confirmed().await.expect("Test failed"); + let keys = shielded_ctx + .tx_note_map + .keys() + .cloned() + .collect::>(); + let expected = BTreeSet::from([ + IndexedTx { + height: 1.into(), + index: TxIndex(1), + }, + IndexedTx { + height: 1.into(), + index: TxIndex(2), + }, + ]); + + assert_eq!(keys, expected); + assert_eq!( + *shielded_ctx.vk_heights[&vk].as_ref().unwrap(), + IndexedTx { + height: 1.into(), + index: TxIndex(2), + } + ); + assert_eq!(shielded_ctx.note_map.len(), 2); + } - fn io(&self) -> &IO; + /// Test that upon each retry, we either resume from the + /// latest height that had been previously stored in the + /// `tx_note_map`, or from the minimum height stored in + /// `vk_heights`. + #[test] + fn test_min_height_to_sync_from() { + let temp_dir = tempdir().unwrap(); + let mut shielded_ctx = + FsShieldedUtils::new(temp_dir.path().to_path_buf()); + + let vk = ExtendedFullViewingKey::from( + ExtendedViewingKey::from_str(AA_VIEWING_KEY).expect("Test failed"), + ) + .fvk + .vk; + + // pretend we start with a tx observed at height 4 whose + // notes cannot be decrypted with `vk` + shielded_ctx.tx_note_map.insert( + IndexedTx { + height: 4.into(), + index: TxIndex(0), + }, + 0, + ); - fn fetch(&self, items: I) -> Self::Fetch - where - I: IntoIterator; + // the min height here should be 1, since + // this vk hasn't decrypted any note yet + shielded_ctx.vk_heights.insert(vk, None); - fn scan(&self, items: I) -> Self::Scan - where - I: IntoIterator; -} + let height = shielded_ctx.min_height_to_sync_from().unwrap(); + assert_eq!(height, BlockHeight(1)); -/// The default type for logging sync progress. -#[derive(Debug, Clone)] -pub struct DefaultLogger<'io, IO: Io> { - io: &'io IO, -} + // let's bump the vk height past 4 + *shielded_ctx.vk_heights.get_mut(&vk).unwrap() = Some(IndexedTx { + height: 6.into(), + index: TxIndex(0), + }); -impl<'io, IO: Io> DefaultLogger<'io, IO> { - /// Initialize default logger - pub fn new(io: &'io IO) -> Self { - Self { io } - } -} + // the min height should now be 4 + let height = shielded_ctx.min_height_to_sync_from().unwrap(); + assert_eq!(height, BlockHeight(4)); -impl<'io, IO: Io> ProgressLogger for DefaultLogger<'io, IO> { - type Fetch = as IntoIterator>::IntoIter; - type Scan = as IntoIterator>::IntoIter; + // and now we bump the last seen tx to height 8 + shielded_ctx.tx_note_map.insert( + IndexedTx { + height: 8.into(), + index: TxIndex(0), + }, + 1, + ); - fn io(&self) -> &IO { - self.io - } + // the min height should now be 6 + let height = shielded_ctx.min_height_to_sync_from().unwrap(); + assert_eq!(height, BlockHeight(6)); + } + + /// Test that the progress tracker correctly keeps + /// track of how many blocks there are left to fetch + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_left_to_fetch() { + let temp_dir = tempdir().unwrap(); + let mut shielded_ctx = + FsShieldedUtils::new(temp_dir.path().to_path_buf()); + let (client, masp_tx_sender) = test_client(2.into()); + let io = StdIo; + let progress = DefaultTracker::new(&io); + let vk = ExtendedFullViewingKey::from( + ExtendedViewingKey::from_str(AA_VIEWING_KEY).expect("Test failed"), + ) + .fvk + .vk; + let masp_tx = arbitrary_masp_tx(); + + // first fetch no blocks + masp_tx_sender.send(None).expect("Test failed"); + shielded_ctx + .fetch( + TestingMaspClient::new(&client), + &progress, + None, + None, + RetryStrategy::Times(1), + &[], + &[vk], + ) + .await + .unwrap_err(); + assert_eq!(progress.left_to_fetch(), 2); - fn fetch(&self, items: I) -> Self::Fetch - where - I: IntoIterator, - { - let items: Vec<_> = items.into_iter().collect(); - items.into_iter() - } + // fetch one of the two blocks + masp_tx_sender + .send(Some(( + IndexedTx { + height: 1.into(), + index: Default::default(), + }, + vec![masp_tx.clone()], + ))) + .expect("Test failed"); + masp_tx_sender.send(None).expect("Test failed"); + shielded_ctx + .fetch( + TestingMaspClient::new(&client), + &progress, + None, + None, + RetryStrategy::Times(1), + &[], + &[vk], + ) + .await + .unwrap_err(); + assert_eq!(progress.left_to_fetch(), 1); + + // fetch no blocks + masp_tx_sender.send(None).expect("Test failed"); + shielded_ctx + .fetch( + TestingMaspClient::new(&client), + &progress, + None, + None, + RetryStrategy::Times(1), + &[], + &[vk], + ) + .await + .unwrap_err(); + assert_eq!(progress.left_to_fetch(), 1); + + // fetch no blocks, but increase the latest block height + // thus the amount left to fetch should increase + let (client, masp_tx_sender) = test_client(3.into()); + masp_tx_sender.send(None).expect("Test failed"); + shielded_ctx + .fetch( + TestingMaspClient::new(&client), + &progress, + None, + None, + RetryStrategy::Times(1), + &[], + &[vk], + ) + .await + .unwrap_err(); + assert_eq!(progress.left_to_fetch(), 2); - fn scan(&self, items: I) -> Self::Scan - where - I: IntoIterator, - { - let items: Vec<_> = items.into_iter().collect(); - items.into_iter() + // fetch remaining block + masp_tx_sender + .send(Some(( + IndexedTx { + height: 2.into(), + index: Default::default(), + }, + vec![masp_tx.clone()], + ))) + .expect("Test failed"); + masp_tx_sender + .send(Some(( + IndexedTx { + height: 3.into(), + index: Default::default(), + }, + vec![masp_tx.clone()], + ))) + .expect("Test failed"); + // this should not produce an error since we have fetched + // all expected blocks + masp_tx_sender.send(None).expect("Test failed"); + shielded_ctx + .fetch( + TestingMaspClient::new(&client), + &progress, + None, + None, + RetryStrategy::Times(1), + &[], + &[vk], + ) + .await + .expect("Test failed"); + assert_eq!(progress.left_to_fetch(), 0); + } + + /// Test that if we don't scan all fetched notes, they + /// are persisted in a cache + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_unscanned_cache() { + let (client, masp_tx_sender) = test_client(2.into()); + let temp_dir = tempdir().unwrap(); + let mut shielded_ctx = + FsShieldedUtils::new(temp_dir.path().to_path_buf()); + + let io = StdIo; + let progress = TestUnscannedTracker::new(&io); + let vk = ExtendedFullViewingKey::from( + ExtendedViewingKey::from_str(AA_VIEWING_KEY).expect("Test failed"), + ) + .fvk + .vk; + + // the fetched txs + let masp_tx = arbitrary_masp_tx(); + masp_tx_sender + .send(Some(( + IndexedTx { + height: 1.into(), + index: TxIndex(1), + }, + vec![masp_tx.clone()], + ))) + .expect("Test failed"); + masp_tx_sender + .send(Some(( + IndexedTx { + height: 1.into(), + index: TxIndex(2), + }, + vec![masp_tx.clone()], + ))) + .expect("Test failed"); + + shielded_ctx + .fetch( + TestingMaspClient::new(&client), + &progress, + None, + None, + RetryStrategy::Times(2), + &[], + &[vk], + ) + .await + .expect("Test failed"); + + shielded_ctx.load_confirmed().await.expect("Test failed"); + let keys = shielded_ctx + .unscanned + .txs + .lock() + .unwrap() + .keys() + .cloned() + .collect::>(); + let expected = vec![IndexedTx { + height: 1.into(), + index: TxIndex(2), + }]; + assert_eq!(keys, expected); + } + + /// Test that if fetching gets interrupted, + /// we persist the fetched notes in a cache + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_fetching_interrupt() { + let temp_dir = tempdir().unwrap(); + let mut shielded_ctx = + FsShieldedUtils::new(temp_dir.path().to_path_buf()); + let (client, masp_tx_sender) = test_client(2.into()); + let io = StdIo; + let progress = DefaultTracker::new(&io); + let vk = ExtendedFullViewingKey::from( + ExtendedViewingKey::from_str(AA_VIEWING_KEY).expect("Test failed"), + ) + .fvk + .vk; + let (shutdown_send, shutdown_signal) = testing_shutdown_signal(); + // the fetched txs + let masp_tx = arbitrary_masp_tx(); + // mock that we have already fetched a note + let expected = ( + IndexedTx { + height: 1.into(), + index: TxIndex(1), + }, + vec![masp_tx], + ); + masp_tx_sender + .send(Some(expected.clone())) + .expect("Test failed"); + shutdown_send.send(()).expect("Test failed"); + let Error::Interrupt(ref proc) = shielded_ctx + .fetch_aux( + TestingMaspClient::new(&client), + &progress, + None, + None, + RetryStrategy::Forever, + &[], + &[vk], + shutdown_signal, + ) + .await + .expect_err("Test failed") + else { + panic!("Test failed") + }; + assert_eq!(proc, "[Testing::Fetch]"); + shielded_ctx.load_confirmed().await.expect("Test failed"); + let entry = shielded_ctx.unscanned.pop_first().expect("Test failed"); + assert_eq!(entry, expected); + assert!(shielded_ctx.unscanned.is_empty()); } } diff --git a/crates/sdk/src/masp/test_utils.rs b/crates/sdk/src/masp/test_utils.rs new file mode 100644 index 0000000000..df8acbdd47 --- /dev/null +++ b/crates/sdk/src/masp/test_utils.rs @@ -0,0 +1,256 @@ +use std::collections::BTreeMap; +use std::ops::{Deref, DerefMut}; +use std::sync::{Arc, Mutex}; + +use masp_primitives::merkle_tree::{CommitmentTree, IncrementalWitness}; +use masp_primitives::sapling::Node; +use namada_core::collections::HashMap; +use namada_core::storage::BlockHeight; +use namada_state::LastBlock; +use namada_tx::IndexedTx; +use tendermint_rpc::SimpleRequest; + +use crate::control_flow::ShutdownSignal; +use crate::error::Error; +use crate::io::Io; +use crate::masp::utils::{ + FetchQueueSender, IterProgress, MaspClient, MaspClientCapabilities, + PeekableIter, ProgressTracker, +}; +use crate::masp::IndexedNoteEntry; +use crate::queries::testing::TestClient; +use crate::queries::{Client, EncodedResponseQuery, Rpc, RPC}; + +/// A client for testing the shielded-sync functionality +pub struct TestingClient { + /// An actual mocked client for querying + inner: TestClient, + /// Used to inject a channel that we control into + /// the fetch algorithm. The option is to mock connection + /// failures. + next_masp_txs: flume::Receiver>, +} + +impl Deref for TestingClient { + type Target = TestClient; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for TestingClient { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +#[cfg(any(test, feature = "async-client"))] +#[cfg_attr(feature = "async-send", async_trait::async_trait)] +#[cfg_attr(not(feature = "async-send"), async_trait::async_trait(?Send))] +impl Client for TestingClient { + type Error = std::io::Error; + + async fn request( + &self, + path: String, + data: Option>, + height: Option, + prove: bool, + ) -> Result { + self.inner.request(path, data, height, prove).await + } + + async fn perform( + &self, + request: R, + ) -> Result + where + R: SimpleRequest, + { + self.inner.perform(request).await + } +} + +/// Creat a test client for unit testing as well +/// as a channel for communicating with it. +pub fn test_client( + last_height: BlockHeight, +) -> (TestingClient, flume::Sender>) { + let (sender, recv) = flume::unbounded(); + let mut client = TestClient::new(RPC); + client.state.in_mem_mut().last_block = Some(LastBlock { + height: last_height, + time: Default::default(), + }); + ( + TestingClient { + inner: client, + next_masp_txs: recv, + }, + sender, + ) +} + +/// A client for unit tests. It "fetches" a new note +/// when a channel controlled by the unit test sends +/// it one. +#[derive(Clone)] +pub struct TestingMaspClient<'a> { + client: &'a TestingClient, +} + +impl<'client> TestingMaspClient<'client> { + /// Create a new [`TestingMaspClient`] given an rpc client + /// [`TestingClient`]. + pub const fn new(client: &'client TestingClient) -> Self { + Self { client } + } +} + +impl MaspClient for TestingMaspClient<'_> { + async fn last_block_height(&self) -> Result, Error> { + Ok(self + .client + .state + .in_mem() + .last_block + .as_ref() + .map(|b| b.height)) + } + + async fn fetch_shielded_transfers( + &self, + progress: &impl ProgressTracker, + shutdown_signal: &mut ShutdownSignal, + mut tx_sender: FetchQueueSender, + BlockHeight(from): BlockHeight, + BlockHeight(to): BlockHeight, + ) -> Result<(), Error> { + // N.B. this assumes one masp tx per block + let mut fetch_iter = progress.fetch(from..=to); + + while fetch_iter.peek().is_some() { + let next_tx = self + .client + .next_masp_txs + .recv() + .expect("Test failed") + .ok_or_else(|| { + Error::Other( + "Connection to fetch MASP txs failed".to_string(), + ) + })?; + tx_sender.send(next_tx); + if shutdown_signal.received() { + return Err(Error::Interrupt("[Testing::Fetch]".to_string())); + } + fetch_iter.next(); + } + Ok(()) + } + + #[inline(always)] + fn capabilities(&self) -> MaspClientCapabilities { + MaspClientCapabilities::OnlyTransfers + } + + async fn fetch_commitment_tree( + &self, + _: BlockHeight, + ) -> Result, Error> { + unimplemented!( + "Commitment tree fetching is not implemented by this client" + ) + } + + async fn fetch_tx_notes_map( + &self, + _: BlockHeight, + ) -> Result, Error> { + unimplemented!( + "Transaction notes map fetching is not implemented by this client" + ) + } + + async fn fetch_witness_map( + &self, + _: BlockHeight, + ) -> Result>, Error> { + unimplemented!("Witness map fetching is not implemented by this client") + } +} + +/// An iterator that yields its first element only +struct YieldOnceIterator { + first: Option, +} + +impl YieldOnceIterator { + fn new(mut iter: T) -> Self + where + T: Iterator, + { + let first = iter.next(); + Self { first } + } +} + +impl Iterator for YieldOnceIterator { + type Item = IndexedNoteEntry; + + fn next(&mut self) -> Option { + self.first.take() + } +} + +/// A progress tracker that only scans the first fetched +/// block. The rest are left in the unscanned cache +/// for the purposes of testing the persistence of +/// this cache. +pub(super) struct TestUnscannedTracker<'io, IO> { + io: &'io IO, + progress: Arc>, +} + +impl<'io, IO: Io> TestUnscannedTracker<'io, IO> { + pub fn new(io: &'io IO) -> Self { + Self { + io, + progress: Arc::new(Mutex::new(Default::default())), + } + } +} + +impl<'io, IO: Io> ProgressTracker for TestUnscannedTracker<'io, IO> { + fn io(&self) -> &IO { + self.io + } + + fn fetch(&self, items: I) -> impl PeekableIter + where + I: Iterator, + { + { + let mut locked = self.progress.lock().unwrap(); + locked.length = items.size_hint().0; + } + crate::masp::utils::DefaultFetchIterator { + inner: items, + progress: self.progress.clone(), + peeked: None, + } + } + + fn scan(&self, items: I) -> impl Iterator + Send + where + I: Iterator + Send, + { + YieldOnceIterator::new(items) + } + + fn left_to_fetch(&self) -> usize { + let locked = self.progress.lock().unwrap(); + locked.length - locked.index + } +} diff --git a/crates/sdk/src/masp/utils.rs b/crates/sdk/src/masp/utils.rs index 6dc740abab..38b0861b5b 100644 --- a/crates/sdk/src/masp/utils.rs +++ b/crates/sdk/src/masp/utils.rs @@ -1,12 +1,22 @@ //! Helper functions and types +use std::collections::BTreeMap; use std::sync::{Arc, Mutex}; -use namada_core::storage::BlockHeight; + +use borsh::BorshDeserialize; +use masp_primitives::merkle_tree::{CommitmentTree, IncrementalWitness}; +use masp_primitives::sapling::Node; +use namada_core::collections::HashMap; +use namada_core::storage::{BlockHeight, TxIndex}; use namada_tx::{IndexedTx, Tx}; +use crate::control_flow::ShutdownSignal; use crate::error::{Error, QueryError}; use crate::io::Io; -use crate::masp::{extract_masp_tx, get_indexed_masp_events_at_height, IndexedNoteEntry, Unscanned}; +use crate::masp::{ + extract_masp_tx, extract_masp_tx_from_ibc_message, + get_indexed_masp_events_at_height, IndexedNoteEntry, Unscanned, +}; use crate::queries::Client; /// When retrying to fetch all notes in a @@ -25,7 +35,7 @@ impl Iterator for RetryStrategy { fn next(&mut self) -> Option { match self { Self::Forever => Some(()), - Self::Times(ref mut count) => { + Self::Times(count) => { if *count == 0 { None } else { @@ -37,59 +47,137 @@ impl Iterator for RetryStrategy { } } +/// Enumerates the capabilities of a [`MaspClient`] implementation. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum MaspClientCapabilities { + /// The masp client implementation is only capable of fetching shielded + /// transfers. + OnlyTransfers, + /// The masp client implementation is capable of not only fetching shielded + /// transfers, but also of fetching commitment trees, witness maps, and + /// note maps. + AllData, +} + +impl MaspClientCapabilities { + /// Check if the lack of one or more capabilities in the + /// masp client implementation warrants a manual update + /// of the witnesses map. + pub const fn needs_witness_map_update(&self) -> bool { + matches!(self, Self::OnlyTransfers) + } + + /// Check if the masp client is able to fetch a pre-built + /// commitment tree. + pub const fn may_fetch_pre_built_tree(&self) -> bool { + matches!(self, Self::AllData) + } + + /// Check if the masp client is able to fetch a pre-built + /// notes map. + pub const fn may_fetch_pre_built_notes_map(&self) -> bool { + matches!(self, Self::AllData) + } + + /// Check if the masp client is able to fetch a pre-built + /// witness map. + pub const fn may_fetch_pre_built_witness_map(&self) -> bool { + matches!(self, Self::AllData) + } +} + /// This abstracts away the implementation details /// of how shielded-sync fetches the necessary data /// from a remote server. -pub trait MaspClient<'client, C: Client> { - /// Create a new [`MaspClient`] given an rpc client. - fn new(client: &'client C) -> Self - where - Self: 'client; +// TODO: redesign this api with progress bars in mind +pub trait MaspClient { + /// Return the last block height we can retrieve data from. + #[allow(async_fn_in_trait)] + async fn last_block_height(&self) -> Result, Error>; - /// Fetches shielded transfers + /// Fetch shielded transfers from blocks heights in the range `[from, to]`, + /// keeping track of progress through `progress`. The fetched transfers + /// are sent over to a separate worker through `tx_sender`. #[allow(async_fn_in_trait)] - async fn fetch_shielded_transfer( + async fn fetch_shielded_transfers( &self, progress: &impl ProgressTracker, + shutdown_signal: &mut ShutdownSignal, tx_sender: FetchQueueSender, - from: u64, - to: u64, + from: BlockHeight, + to: BlockHeight, ) -> Result<(), Error>; + + /// Return the capabilities of this client. + fn capabilities(&self) -> MaspClientCapabilities; + + /// Fetch the commitment tree of height `height`. + #[allow(async_fn_in_trait)] + async fn fetch_commitment_tree( + &self, + height: BlockHeight, + ) -> Result, Error>; + + /// Fetch the tx notes map of height `height`. + #[allow(async_fn_in_trait)] + async fn fetch_tx_notes_map( + &self, + height: BlockHeight, + ) -> Result, Error>; + + /// Fetch the witness map of height `height`. + #[allow(async_fn_in_trait)] + async fn fetch_witness_map( + &self, + height: BlockHeight, + ) -> Result>, Error>; } /// An inefficient MASP client which simply uses a /// client to the blockchain to query it directly. -pub struct LedgerMaspClient<'client, C: Client> { +#[cfg(not(target_family = "wasm"))] +pub struct LedgerMaspClient<'client, C> { client: &'client C, } #[cfg(not(target_family = "wasm"))] -impl<'client, C: Client + Sync> MaspClient<'client, C> for LedgerMaspClient<'client, C> - where - LedgerMaspClient<'client, C>: 'client, -{ - fn new(client: &'client C) -> Self - where - Self: 'client, - { +impl<'client, C> LedgerMaspClient<'client, C> { + /// Create a new [`MaspClient`] given an rpc client. + pub const fn new(client: &'client C) -> Self { Self { client } } +} +#[cfg(not(target_family = "wasm"))] +impl MaspClient for LedgerMaspClient<'_, C> { + async fn last_block_height(&self) -> Result, Error> { + let maybe_block = crate::rpc::query_block(self.client).await?; + Ok(maybe_block.map(|b| b.height)) + } - async fn fetch_shielded_transfer( + async fn fetch_shielded_transfers( &self, progress: &impl ProgressTracker, + shutdown_signal: &mut ShutdownSignal, mut tx_sender: FetchQueueSender, - from: u64, - to: u64, + BlockHeight(from): BlockHeight, + BlockHeight(to): BlockHeight, ) -> Result<(), Error> { // Fetch all the transactions we do not have yet let mut fetch_iter = progress.fetch(from..=to); - while let Some(height) = fetch_iter.peek() { - let height = *height; + loop { + let Some(height) = fetch_iter.peek().copied() else { + break; + }; + _ = fetch_iter.next(); + + if shutdown_signal.received() { + return Err(Error::Interrupt( + "[ShieldedSync::Fetching]".to_string(), + )); + } if tx_sender.contains_height(height) { - fetch_iter.next(); continue; } @@ -102,7 +190,6 @@ impl<'client, C: Client + Sync> MaspClient<'client, C> for LedgerMaspClient<'cli { Some(events) => events, None => { - fetch_iter.next(); continue; } }; @@ -120,11 +207,19 @@ impl<'client, C: Client + Sync> MaspClient<'client, C> for LedgerMaspClient<'cli .block .data; - for (idx, masp_sections_refs) in txs_results { + for (idx, masp_sections_refs, ibc_tx_data_refs) in txs_results { let tx = Tx::try_from(block[idx.0 as usize].as_ref()) .map_err(|e| Error::Other(e.to_string()))?; - let extracted_masp_txs = - extract_masp_tx(&tx, &masp_sections_refs).await?; + let mut extracted_masp_txs = vec![]; + if let Some(masp_sections_refs) = masp_sections_refs { + extracted_masp_txs.extend( + extract_masp_tx(&tx, &masp_sections_refs).await?, + ); + }; + if ibc_tx_data_refs.is_some() { + extracted_masp_txs + .extend(extract_masp_tx_from_ibc_message(&tx)?); + } tx_sender.send(( IndexedTx { @@ -134,14 +229,462 @@ impl<'client, C: Client + Sync> MaspClient<'client, C> for LedgerMaspClient<'cli extracted_masp_txs, )); } - fetch_iter.next(); } Ok(()) } + + #[inline(always)] + fn capabilities(&self) -> MaspClientCapabilities { + MaspClientCapabilities::OnlyTransfers + } + + async fn fetch_commitment_tree( + &self, + _: BlockHeight, + ) -> Result, Error> { + Err(Error::Other( + "Commitment tree fetching is not implemented by this client" + .to_string(), + )) + } + + async fn fetch_tx_notes_map( + &self, + _: BlockHeight, + ) -> Result, Error> { + Err(Error::Other( + "Transaction notes map fetching is not implemented by this client" + .to_string(), + )) + } + + async fn fetch_witness_map( + &self, + _: BlockHeight, + ) -> Result>, Error> { + Err(Error::Other( + "Witness map fetching is not implemented by this client" + .to_string(), + )) + } } +/// MASP client implementation that queries data from the +/// [`namada-masp-indexer`]. +/// +/// [`namada-masp-indexer`]: +#[cfg(not(target_family = "wasm"))] +#[derive(Clone, Debug)] +pub struct IndexerMaspClient { + indexer_api: Arc, + client: reqwest::Client, +} +#[cfg(not(target_family = "wasm"))] +trait RequestBuilderExt { + fn keep_alive(self) -> reqwest::RequestBuilder; +} + +#[cfg(not(target_family = "wasm"))] +impl RequestBuilderExt for reqwest::RequestBuilder { + #[inline(always)] + fn keep_alive(self) -> reqwest::RequestBuilder { + self.header("Connection", "Keep-Alive") + } +} + +#[cfg(not(target_family = "wasm"))] +impl IndexerMaspClient { + /// Create a new [`IndexerMaspClient`]. + #[inline] + pub fn new(client: reqwest::Client, indexer_api: reqwest::Url) -> Self { + let indexer_api = Arc::new(indexer_api); + Self { + client, + indexer_api, + } + } + + fn endpoint(&self, which: &str) -> String { + format!("{}{which}", self.indexer_api) + } + + async fn get_server_error( + response: reqwest::Response, + ) -> Result { + use serde::Deserialize; + + #[derive(Deserialize)] + struct Response { + message: String, + } + + let payload: Response = response.json().await.map_err(|err| { + Error::Other(format!( + "Could not deserialize server's error JSON response: {err}" + )) + })?; + + Ok(payload.message) + } +} + +#[cfg(not(target_family = "wasm"))] +impl MaspClient for IndexerMaspClient { + #[inline(always)] + fn capabilities(&self) -> MaspClientCapabilities { + MaspClientCapabilities::AllData + } + + async fn last_block_height(&self) -> Result, Error> { + use serde::Deserialize; + + #[derive(Deserialize)] + struct Response { + block_height: u64, + } + + let response = self + .client + .get(self.endpoint("/height")) + .keep_alive() + .send() + .await + .map_err(|err| { + Error::Other(format!( + "Failed to fetch latest block height: {err}" + )) + })?; + if !response.status().is_success() { + let err = Self::get_server_error(response).await?; + return Err(Error::Other(format!( + "Failed to fetch last block height: {err}" + ))); + } + let payload: Response = response.json().await.map_err(|err| { + Error::Other(format!( + "Could not deserialize latest block height JSON response: \ + {err}" + )) + })?; + + Ok(if payload.block_height != 0 { + Some(BlockHeight(payload.block_height)) + } else { + None + }) + } + + async fn fetch_shielded_transfers( + &self, + progress: &impl ProgressTracker, + shutdown_signal: &mut ShutdownSignal, + mut tx_sender: FetchQueueSender, + BlockHeight(mut from): BlockHeight, + BlockHeight(to): BlockHeight, + ) -> Result<(), Error> { + use serde::Deserialize; + + #[derive(Deserialize)] + struct TransactionSlot { + // masp_tx_index: u64, + bytes: Vec, + } + + #[derive(Deserialize)] + struct Transaction { + batch: Vec, + block_index: u32, + block_height: u64, + } + + #[derive(Deserialize)] + struct TxResponse { + txs: Vec, + } + + if from > to { + return Err(Error::Other(format!( + "Invalid block range {from}-{to}: Beginning height {from} is \ + greater than ending height {to}" + ))); + } + + const MAX_RANGE_THRES: u64 = 30; + let mut fetch_iter = progress.fetch(from..=to); + + loop { + let from_height = from; + let off = (to - from).min(MAX_RANGE_THRES); + let to_height = from + off; + from += off; + + let txs_fut = async { + let response = self + .client + .get(self.endpoint("/tx")) + .keep_alive() + .query(&[("height", from_height), ("height_offset", off)]) + .send() + .await + .map_err(|err| { + Error::Other(format!( + "Failed to fetch transactions in the height range \ + {from_height}-{to_height}: {err}" + )) + })?; + if !response.status().is_success() { + let err = Self::get_server_error(response).await?; + return Err(Error::Other(format!( + "Failed to fetch transactions in the range \ + {from_height}-{to_height}: {err}" + ))); + } + let payload: TxResponse = + response.json().await.map_err(|err| { + Error::Other(format!( + "Could not deserialize the transactions JSON \ + response in the height range \ + {from_height}-{to_height}: {err}" + )) + })?; + + Ok::<_, Error>(payload) + }; + let payload = tokio::select! { + maybe_payload = txs_fut => { + maybe_payload? + } + _ = &mut *shutdown_signal => { + return Err(Error::Interrupt( + "[ShieldedSync::Fetching]".to_string(), + )); + } + }; + + let mut last_height = None; + + for Transaction { + batch, + block_index, + block_height, + } in payload.txs + { + let mut extracted_masp_txs = Vec::with_capacity(batch.len()); + + for TransactionSlot { bytes } in batch { + type MaspTx = masp_primitives::transaction::Transaction; + + extracted_masp_txs.push( + MaspTx::try_from_slice(&bytes).map_err(|err| { + Error::Other(format!( + "Could not deserialize the masp txs borsh \ + data at height {block_height} and index \ + {block_index}: {err}" + )) + })?, + ); + } + + tx_sender.send(( + IndexedTx { + height: BlockHeight(block_height), + index: TxIndex(block_index), + }, + extracted_masp_txs, + )); + + let curr_height = Some(block_height); + if curr_height > last_height { + last_height = curr_height; + _ = fetch_iter.next(); + } + } + + if from >= to { + break; + } + } + + // NB: a hack to drain the iterator in case + // there were still some items left + // TODO: improve this lol + while fetch_iter.next().is_some() {} + + Ok(()) + } + + async fn fetch_commitment_tree( + &self, + BlockHeight(height): BlockHeight, + ) -> Result, Error> { + use serde::Deserialize; + + #[derive(Deserialize)] + struct Response { + commitment_tree: Vec, + } + + let response = self + .client + .get(self.endpoint("/commitment-tree")) + .keep_alive() + .query(&[("height", height)]) + .send() + .await + .map_err(|err| { + Error::Other(format!( + "Failed to fetch commitment tree at height {height}: {err}" + )) + })?; + if !response.status().is_success() { + let err = Self::get_server_error(response).await?; + return Err(Error::Other(format!( + "Failed to fetch commitment tree at height {height}: {err}" + ))); + } + let payload: Response = response.json().await.map_err(|err| { + Error::Other(format!( + "Could not deserialize the commitment tree JSON response at \ + height {height}: {err}" + )) + })?; + + BorshDeserialize::try_from_slice(&payload.commitment_tree).map_err( + |err| { + Error::Other(format!( + "Could not deserialize the commitment tree borsh data at \ + height {height}: {err}" + )) + }, + ) + } + + async fn fetch_tx_notes_map( + &self, + BlockHeight(height): BlockHeight, + ) -> Result, Error> { + use serde::Deserialize; + + #[derive(Deserialize)] + struct Note { + // masp_tx_index: u64, + note_position: usize, + block_index: u32, + block_height: u64, + } + + #[derive(Deserialize)] + struct Response { + notes_map: Vec, + } + + let response = self + .client + .get(self.endpoint("/notes-map")) + .keep_alive() + .query(&[("height", height)]) + .send() + .await + .map_err(|err| { + Error::Other(format!( + "Failed to fetch notes map at height {height}: {err}" + )) + })?; + if !response.status().is_success() { + let err = Self::get_server_error(response).await?; + return Err(Error::Other(format!( + "Failed to fetch notes map at height {height}: {err}" + ))); + } + let payload: Response = response.json().await.map_err(|err| { + Error::Other(format!( + "Could not deserialize the notes map JSON response at height \ + {height}: {err}" + )) + })?; + + Ok(payload + .notes_map + .into_iter() + .map( + |Note { + block_index, + block_height, + note_position, + }| { + ( + IndexedTx { + index: TxIndex(block_index), + height: BlockHeight(block_height), + }, + note_position, + ) + }, + ) + .collect()) + } + + async fn fetch_witness_map( + &self, + BlockHeight(height): BlockHeight, + ) -> Result>, Error> { + use serde::Deserialize; + + #[derive(Deserialize)] + struct Witness { + bytes: Vec, + index: usize, + } + + #[derive(Deserialize)] + struct WitnessMapResponse { + witnesses: Vec, + } + + let response = self + .client + .get(self.endpoint("/witness-map")) + .keep_alive() + .query(&[("height", height)]) + .send() + .await + .map_err(|err| { + Error::Other(format!( + "Failed to fetch witness map at height {height}: {err}" + )) + })?; + if !response.status().is_success() { + let err = Self::get_server_error(response).await?; + return Err(Error::Other(format!( + "Failed to fetch witness map at height {height}: {err}" + ))); + } + let payload: WitnessMapResponse = + response.json().await.map_err(|err| { + Error::Other(format!( + "Could not deserialize the witness map JSON response at \ + height {height}: {err}" + )) + })?; + + payload.witnesses.into_iter().try_fold( + HashMap::new(), + |mut accum, Witness { index, bytes }| { + let witness = BorshDeserialize::try_from_slice(&bytes) + .map_err(|err| { + Error::Other(format!( + "Could not deserialize the witness borsh data at \ + height {height}: {err}" + )) + })?; + accum.insert(index, witness); + Ok(accum) + }, + ) + } +} /// A channel-like struct for "sending" newly fetched blocks /// to the scanning algorithm. @@ -187,6 +730,7 @@ impl Iterator for FetchQueueReceiver { if let Some(entry) = self.cache.pop_first() { return Some(entry); } + core::hint::spin_loop(); } None } @@ -252,8 +796,8 @@ pub trait PeekableIter { } impl PeekableIter for std::iter::Peekable - where - I: Iterator, +where + I: Iterator, { fn peek(&mut self) -> Option<&J> { self.peek() @@ -278,16 +822,16 @@ pub trait ProgressTracker { /// Return an iterator to fetched shielded transfers fn fetch(&self, items: I) -> impl PeekableIter - where - I: Iterator; + where + I: Iterator; /// Return an iterator over MASP transactions to be scanned fn scan( &self, items: I, ) -> impl Iterator + Send - where - I: Iterator + Send; + where + I: Iterator + Send; /// The number of blocks that need to be fetched fn left_to_fetch(&self) -> usize; @@ -317,8 +861,8 @@ pub(super) struct IterProgress { } pub(super) struct DefaultFetchIterator - where - I: Iterator, +where + I: Iterator, { pub inner: I, pub progress: Arc>, @@ -326,8 +870,8 @@ pub(super) struct DefaultFetchIterator } impl PeekableIter for DefaultFetchIterator - where - I: Iterator, +where + I: Iterator, { fn peek(&mut self) -> Option<&u64> { if self.peeked.is_none() { @@ -351,8 +895,8 @@ impl<'io, IO: Io> ProgressTracker for DefaultTracker<'io, IO> { } fn fetch(&self, items: I) -> impl PeekableIter - where - I: Iterator, + where + I: Iterator, { { let mut locked = self.progress.lock().unwrap(); @@ -366,8 +910,8 @@ impl<'io, IO: Io> ProgressTracker for DefaultTracker<'io, IO> { } fn scan(&self, items: I) -> impl Iterator + Send - where - I: IntoIterator, + where + I: IntoIterator, { let items: Vec<_> = items.into_iter().collect(); items.into_iter() diff --git a/crates/sdk/src/queries/mod.rs b/crates/sdk/src/queries/mod.rs index ed5fdb1836..ce338c89fa 100644 --- a/crates/sdk/src/queries/mod.rs +++ b/crates/sdk/src/queries/mod.rs @@ -98,7 +98,7 @@ pub fn require_no_data(request: &RequestQuery) -> namada_storage::Result<()> { /// Queries testing helpers #[cfg(any(test, feature = "testing"))] -mod testing { +pub(crate) mod testing { use borsh_ext::BorshSerializeExt; use namada_state::testing::TestState; use tendermint_rpc::Response; diff --git a/crates/sdk/src/queries/shell.rs b/crates/sdk/src/queries/shell.rs index 2a8b22e717..403cc80851 100644 --- a/crates/sdk/src/queries/shell.rs +++ b/crates/sdk/src/queries/shell.rs @@ -25,7 +25,7 @@ use namada_state::{DBIter, LastBlock, StateRead, StorageHasher, DB}; use namada_storage::{ResultExt, StorageRead}; use namada_token::storage_key::masp_token_map_key; #[cfg(any(test, feature = "async-client"))] -use namada_tx::data::TxResult; +use namada_tx::data::DryRunResult; use self::eth_bridge::{EthBridge, ETH_BRIDGE}; use crate::events::log::dumb_queries; @@ -84,7 +84,7 @@ router! {SHELL, -> Vec = (with_options storage_value), // Dry run a transaction - ( "dry_run_tx" ) -> TxResult = (with_options dry_run_tx), + ( "dry_run_tx" ) -> DryRunResult = (with_options dry_run_tx), // Raw storage access - prefix iterator ( "prefix" / [storage_key: storage::Key] ) diff --git a/crates/sdk/src/rpc.rs b/crates/sdk/src/rpc.rs index 4856ef12a2..e43575d64e 100644 --- a/crates/sdk/src/rpc.rs +++ b/crates/sdk/src/rpc.rs @@ -25,7 +25,7 @@ use namada_core::token::{ }; use namada_core::{storage, token}; use namada_gas::event::GasUsed as GasUsedAttr; -use namada_gas::Gas; +use namada_gas::WholeGas; use namada_governance::parameters::GovernanceParameters; use namada_governance::pgf::parameters::PgfParameters; use namada_governance::pgf::storage::steward::StewardDetail; @@ -42,7 +42,7 @@ use namada_proof_of_stake::types::{ BondsAndUnbondsDetails, CommissionPair, ValidatorMetaData, }; use namada_state::LastBlock; -use namada_tx::data::{BatchedTxResult, ResultCode, TxResult}; +use namada_tx::data::{BatchedTxResult, DryRunResult, ResultCode, TxResult}; use namada_tx::event::{Batch as BatchAttr, Code as CodeAttr}; use serde::Serialize; @@ -549,7 +549,7 @@ pub async fn query_tx_events( pub async fn dry_run_tx( context: &N, tx_bytes: Vec, -) -> Result, Error> { +) -> Result { let (data, height, prove) = (Some(tx_bytes), None, false); let result = convert_response::( RPC.shell() @@ -557,10 +557,10 @@ pub async fn dry_run_tx( .await, )? .data; - let result_str = format!("Transaction consumed {} gas", result.gas_used); + let result_str = format!("Transaction consumed {} gas", result.1); let mut cmt_result_str = String::new(); - for (inner_hash, cmt_result) in result.batch_results.iter() { + for (inner_hash, cmt_result) in result.0.iter() { match cmt_result { Ok(result) => { if result.is_accepted() { @@ -631,7 +631,7 @@ pub struct TxResponse { /// Response code pub code: ResultCode, /// Gas used. - pub gas_used: Gas, + pub gas_used: WholeGas, } /// Determines a result of an inner tx from @@ -692,9 +692,9 @@ impl TxResponse { /// Check the result of the batch. This should not be used with wrapper /// txs. pub fn batch_result(&self) -> HashMap> { - if let Some(tx) = self.batch.as_ref() { + if let Some(tx_result) = self.batch.as_ref() { let mut result = HashMap::default(); - for (inner_hash, cmt_result) in tx.batch_results.iter() { + for (inner_hash, cmt_result) in tx_result.iter() { let value = match cmt_result { Ok(res) => { if res.is_accepted() { diff --git a/crates/sdk/src/signing.rs b/crates/sdk/src/signing.rs index 66f5d78047..3e5e3a3c6a 100644 --- a/crates/sdk/src/signing.rs +++ b/crates/sdk/src/signing.rs @@ -15,13 +15,14 @@ use namada_core::address::{Address, ImplicitAddress, InternalAddress, MASP}; use namada_core::arith::checked; use namada_core::collections::{HashMap, HashSet}; use namada_core::key::*; -use namada_core::masp::{AssetData, ExtendedViewingKey, PaymentAddress}; +use namada_core::masp::{AssetData, ExtendedViewingKey, PaymentAddress, TxId}; use namada_core::sign::SignatureIndex; use namada_core::token::{Amount, DenominatedAmount}; use namada_governance::storage::proposal::{ InitProposalData, ProposalType, VoteProposalData, }; use namada_governance::storage::vote::ProposalVote; +use namada_ibc::{MsgNftTransfer, MsgTransfer}; use namada_parameters::storage as parameter_storage; use namada_token as token; use namada_token::storage_key::balance_key; @@ -29,7 +30,6 @@ use namada_tx::data::pgf::UpdateStewardCommission; use namada_tx::data::pos::BecomeValidator; use namada_tx::data::{pos, Fee}; use namada_tx::{MaspBuilder, Section, Tx}; -use prost::Message; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; use tokio::sync::RwLock; @@ -38,8 +38,6 @@ use crate::args::SdkTypes; use crate::error::{EncodingError, Error, TxSubmitError}; use crate::eth_bridge_pool::PendingTransfer; use crate::governance::storage::proposal::{AddRemove, PGFAction, PGFTarget}; -use crate::ibc::apps::transfer::types::msgs::transfer::MsgTransfer; -use crate::ibc::primitives::proto::Any; use crate::io::*; use crate::rpc::validate_amount; use crate::token::Account; @@ -945,6 +943,30 @@ fn proposal_type_to_ledger_vector( } } +// Find the MASP Builder that was used to construct the given Transaction. +// Additionally record how to decode AssetTypes using information from the +// builder. +fn find_masp_builder<'a>( + tx: &'a Tx, + shielded_section_hash: Option, + asset_types: &mut HashMap, +) -> Result, std::io::Error> { + for section in &tx.sections { + match section { + Section::MaspBuilder(builder) + if Some(builder.target) == shielded_section_hash => + { + for decoded in &builder.asset_types { + asset_types.insert(decoded.encode()?, decoded.clone()); + } + return Ok(Some(builder)); + } + _ => {} + } + } + Ok(None) +} + /// Converts the given transaction to the form that is displayed on the Ledger /// device pub async fn to_ledger_vector( @@ -1265,30 +1287,17 @@ pub async fn to_ledger_vector( .map_err(|err| { Error::from(EncodingError::Conversion(err.to_string())) })?; - // To facilitate lookups of MASP AssetTypes - let mut asset_types = HashMap::new(); - let builder = tx.sections.iter().find_map(|x| match x { - Section::MaspBuilder(builder) - if Some(builder.target) - == transfer.shielded_section_hash => - { - for decoded in &builder.asset_types { - match decoded.encode() { - Err(_) => None, - Ok(asset) => { - asset_types.insert(asset, decoded.clone()); - Some(builder) - } - }?; - } - Some(builder) - } - _ => None, - }); - tv.name = "Transfer_0".to_string(); - tv.output.push("Type : Transfer".to_string()); + + // To facilitate lookups of MASP AssetTypes + let mut asset_types = HashMap::new(); + let builder = find_masp_builder( + tx, + transfer.shielded_section_hash, + &mut asset_types, + ) + .map_err(|_| Error::Other("Invalid Data".to_string()))?; make_ledger_token_transfer_endpoints( &tokens, &mut tv.output, @@ -1306,71 +1315,272 @@ pub async fn to_ledger_vector( ) .await?; } else if code_sec.tag == Some(TX_IBC_WASM.to_string()) { - let any_msg = Any::decode( - tx.data(cmt) - .ok_or_else(|| Error::Other("Invalid Data".to_string()))? - .as_ref(), - ) - .map_err(|x| { - Error::from(EncodingError::Conversion(x.to_string())) - })?; - - tv.name = "IBC_0".to_string(); - tv.output.push("Type : IBC".to_string()); - - match MsgTransfer::try_from(any_msg.clone()) { - Ok(transfer) => { - let transfer_token = format!( - "{} {}", - transfer.packet_data.token.amount, - transfer.packet_data.token.denom - ); - tv.output.extend(vec![ - format!("Source port : {}", transfer.port_id_on_a), - format!("Source channel : {}", transfer.chan_id_on_a), - format!("Token : {}", transfer_token), - format!("Sender : {}", transfer.packet_data.sender), - format!("Receiver : {}", transfer.packet_data.receiver), - format!( - "Timeout height : {}", - transfer.timeout_height_on_b - ), - format!( - "Timeout timestamp : {}", - transfer - .timeout_timestamp_on_b - .into_tm_time() - .map_or("(none)".to_string(), |time| time - .to_rfc3339()) - ), - ]); - tv.output_expert.extend(vec![ - format!("Source port : {}", transfer.port_id_on_a), - format!("Source channel : {}", transfer.chan_id_on_a), - format!("Token : {}", transfer_token), - format!("Sender : {}", transfer.packet_data.sender), - format!("Receiver : {}", transfer.packet_data.receiver), - format!( - "Timeout height : {}", - transfer.timeout_height_on_b - ), - format!( - "Timeout timestamp : {}", - transfer - .timeout_timestamp_on_b - .into_tm_time() - .map_or("(none)".to_string(), |time| time - .to_rfc3339()) - ), - ]); + let data = tx + .data(cmt) + .ok_or_else(|| Error::Other("Invalid Data".to_string()))?; + + if let Ok(transfer) = MsgTransfer::try_from_slice(data.as_ref()) { + tv.name = "IBC_Transfer_0".to_string(); + tv.output.push("Type : IBC Transfer".to_string()); + let transfer_token = format!( + "{} {}", + transfer.message.packet_data.token.amount, + transfer.message.packet_data.token.denom + ); + tv.output.extend(vec![ + format!("Source port : {}", transfer.message.port_id_on_a), + format!( + "Source channel : {}", + transfer.message.chan_id_on_a + ), + format!("Token : {}", transfer_token), + format!("Sender : {}", transfer.message.packet_data.sender), + format!( + "Receiver : {}", + transfer.message.packet_data.receiver + ), + format!("Memo : {}", transfer.message.packet_data.memo), + format!( + "Timeout height : {}", + transfer.message.timeout_height_on_b + ), + format!( + "Timeout timestamp : {}", + transfer + .message + .timeout_timestamp_on_b + .into_tm_time() + .map_or("no timestamp".to_string(), |time| time + .to_rfc3339()) + ), + ]); + tv.output_expert.extend(vec![ + format!("Source port : {}", transfer.message.port_id_on_a), + format!( + "Source channel : {}", + transfer.message.chan_id_on_a + ), + format!("Token : {}", transfer_token), + format!("Sender : {}", transfer.message.packet_data.sender), + format!( + "Receiver : {}", + transfer.message.packet_data.receiver + ), + format!("Memo : {}", transfer.message.packet_data.memo), + format!( + "Timeout height : {}", + transfer.message.timeout_height_on_b + ), + format!( + "Timeout timestamp : {}", + transfer + .message + .timeout_timestamp_on_b + .into_tm_time() + .map_or("no timestamp".to_string(), |time| time + .to_rfc3339()) + ), + ]); + if let Some(transfer) = transfer.transfer { + // To facilitate lookups of MASP AssetTypes + let mut asset_types = HashMap::new(); + let builder = find_masp_builder( + tx, + transfer.shielded_section_hash, + &mut asset_types, + ) + .map_err(|_| Error::Other("Invalid Data".to_string()))?; + make_ledger_token_transfer_endpoints( + &tokens, + &mut tv.output, + &transfer, + builder, + &asset_types, + ) + .await?; + make_ledger_token_transfer_endpoints( + &tokens, + &mut tv.output_expert, + &transfer, + builder, + &asset_types, + ) + .await?; + } + } else if let Ok(transfer) = + MsgNftTransfer::try_from_slice(data.as_ref()) + { + tv.name = "IBC_NFT_Transfer_0".to_string(); + tv.output.push("Type : IBC NFT Transfer".to_string()); + tv.output.extend(vec![ + format!("Source port : {}", transfer.message.port_id_on_a), + format!( + "Source channel : {}", + transfer.message.chan_id_on_a + ), + format!( + "Class ID: {}", + transfer.message.packet_data.class_id + ), + ]); + if let Some(class_uri) = &transfer.message.packet_data.class_uri + { + tv.output.push(format!("Class URI: {}", class_uri)); + } + if let Some(class_data) = + &transfer.message.packet_data.class_data + { + tv.output.push(format!("Class data: {}", class_data)); + } + for (idx, token_id) in + transfer.message.packet_data.token_ids.0.iter().enumerate() + { + tv.output.push(format!("Token ID: {}", token_id)); + if let Some(token_uris) = + &transfer.message.packet_data.token_uris + { + tv.output.push(format!( + "Token URI: {}", + token_uris.get(idx).ok_or_else(|| Error::Other( + "Invalid Data".to_string() + ))?, + )); + } + if let Some(token_data) = + &transfer.message.packet_data.token_data + { + tv.output.push(format!( + "Token data: {}", + token_data.get(idx).ok_or_else(|| Error::Other( + "Invalid Data".to_string() + ))?, + )); + } + } + tv.output.extend(vec![ + format!("Sender : {}", transfer.message.packet_data.sender), + format!( + "Receiver : {}", + transfer.message.packet_data.receiver + ), + ]); + if let Some(memo) = &transfer.message.packet_data.memo { + tv.output.push(format!("Memo: {}", memo)); + } + tv.output.extend(vec![ + format!( + "Timeout height : {}", + transfer.message.timeout_height_on_b + ), + format!( + "Timeout timestamp : {}", + transfer + .message + .timeout_timestamp_on_b + .into_tm_time() + .map_or("no timestamp".to_string(), |time| time + .to_rfc3339()) + ), + ]); + tv.output_expert.extend(vec![ + format!("Source port : {}", transfer.message.port_id_on_a), + format!( + "Source channel : {}", + transfer.message.chan_id_on_a + ), + format!( + "Class ID: {}", + transfer.message.packet_data.class_id + ), + ]); + if let Some(class_uri) = &transfer.message.packet_data.class_uri + { + tv.output_expert.push(format!("Class URI: {}", class_uri)); } - _ => { - for line in format!("{:#?}", any_msg).split('\n') { - let stripped = line.trim_start(); - tv.output.push(format!("Part : {}", stripped)); - tv.output_expert.push(format!("Part : {}", stripped)); + if let Some(class_data) = + &transfer.message.packet_data.class_data + { + tv.output_expert + .push(format!("Class data: {}", class_data)); + } + for (idx, token_id) in + transfer.message.packet_data.token_ids.0.iter().enumerate() + { + tv.output_expert.push(format!("Token ID: {}", token_id)); + if let Some(token_uris) = + &transfer.message.packet_data.token_uris + { + tv.output_expert.push(format!( + "Token URI: {}", + token_uris.get(idx).ok_or_else(|| Error::Other( + "Invalid Data".to_string() + ))?, + )); + } + if let Some(token_data) = + &transfer.message.packet_data.token_data + { + tv.output_expert.push(format!( + "Token data: {}", + token_data.get(idx).ok_or_else(|| Error::Other( + "Invalid Data".to_string() + ))?, + )); } } + tv.output_expert.extend(vec![ + format!("Sender : {}", transfer.message.packet_data.sender), + format!( + "Receiver : {}", + transfer.message.packet_data.receiver + ), + ]); + if let Some(memo) = &transfer.message.packet_data.memo { + tv.output_expert.push(format!("Memo: {}", memo)); + } + tv.output_expert.extend(vec![ + format!( + "Timeout height : {}", + transfer.message.timeout_height_on_b + ), + format!( + "Timeout timestamp : {}", + transfer + .message + .timeout_timestamp_on_b + .into_tm_time() + .map_or("no timestamp".to_string(), |time| time + .to_rfc3339()) + ), + ]); + if let Some(transfer) = transfer.transfer { + // To facilitate lookups of MASP AssetTypes + let mut asset_types = HashMap::new(); + let builder = find_masp_builder( + tx, + transfer.shielded_section_hash, + &mut asset_types, + ) + .map_err(|_| Error::Other("Invalid Data".to_string()))?; + make_ledger_token_transfer_endpoints( + &tokens, + &mut tv.output, + &transfer, + builder, + &asset_types, + ) + .await?; + make_ledger_token_transfer_endpoints( + &tokens, + &mut tv.output_expert, + &transfer, + builder, + &asset_types, + ) + .await?; + } + } else { + return Result::Err(Error::Other("Invalid Data".to_string())); } } else if code_sec.tag == Some(TX_BOND_WASM.to_string()) { let bond = pos::Bond::try_from_slice( diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index 403b99248e..3ee6feece2 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -66,7 +66,7 @@ use namada_token::DenominatedAmount; use namada_tx::data::pgf::UpdateStewardCommission; use namada_tx::data::pos::{BecomeValidator, ConsensusKeyChange}; use namada_tx::data::{ - compute_inner_tx_hash, pos, BatchedTxResult, ResultCode, TxResult, + compute_inner_tx_hash, pos, BatchedTxResult, DryRunResult, ResultCode, }; pub use namada_tx::{Authorization, *}; use num_traits::Zero; @@ -158,7 +158,7 @@ pub enum ProcessTxResponse { /// Result of submitting a transaction to the mempool Broadcast(Response), /// Result of dry running transaction - DryRun(TxResult), + DryRun(DryRunResult), } impl ProcessTxResponse { @@ -2750,25 +2750,7 @@ pub async fn build_ibc_transfer( /// Abstraction for helping build transactions #[allow(clippy::too_many_arguments)] -pub async fn build( - context: &impl Namada, - tx_args: &crate::args::Tx, - path: PathBuf, - data: D, - on_tx: F, - fee_amount: DenominatedAmount, - gas_payer: &common::PublicKey, -) -> Result -where - F: FnOnce(&mut Tx, &mut D) -> Result<()>, - D: BorshSerialize, -{ - build_pow_flag(context, tx_args, path, data, on_tx, fee_amount, gas_payer) - .await -} - -#[allow(clippy::too_many_arguments)] -async fn build_pow_flag( +async fn build( context: &impl Namada, tx_args: &crate::args::Tx, path: PathBuf, @@ -2989,7 +2971,7 @@ pub async fn build_transparent_transfer( .ok_or(Error::Other("Combined transfer overflows".to_string()))?; } - let tx = build_pow_flag( + let tx = build( context, &args.tx, args.tx_code_path.clone(), @@ -3096,7 +3078,7 @@ pub async fn build_shielded_transfer( Ok(()) }; - let tx = build_pow_flag( + let tx = build( context, &args.tx, args.tx_code_path.clone(), @@ -3256,7 +3238,7 @@ pub async fn build_shielding_transfer( Ok(()) }; - let tx = build_pow_flag( + let tx = build( context, &args.tx, args.tx_code_path.clone(), @@ -3370,7 +3352,7 @@ pub async fn build_unshielding_transfer( Ok(()) }; - let tx = build_pow_flag( + let tx = build( context, &args.tx, args.tx_code_path.clone(), diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index 56a80b261a..30985f248b 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -40,6 +40,7 @@ namada_storage = { path = "../storage" } namada_tx = { path = "../tx" } borsh.workspace = true +clru.workspace = true itertools.workspace = true linkme = {workspace = true, optional = true} smooth-operator.workspace = true diff --git a/crates/state/src/in_memory.rs b/crates/state/src/in_memory.rs index 785f4d4cca..e4c8d9817a 100644 --- a/crates/state/src/in_memory.rs +++ b/crates/state/src/in_memory.rs @@ -1,3 +1,6 @@ +use std::num::NonZeroUsize; + +use clru::CLruCache; use namada_core::address::{Address, EstablishedAddressGen, InternalAddress}; use namada_core::borsh::{BorshDeserialize, BorshSerialize}; use namada_core::chain::{ChainId, CHAIN_ID_LENGTH}; @@ -73,6 +76,14 @@ where pub storage_read_past_height_limit: Option, /// Data that needs to be committed to the merkle tree pub commit_only_data: CommitOnlyData, + /// Cache of the results of process proposal for the next height to decide. + /// A LRU cache is used to prevent consuming too much memory at times where + /// a node cannot make progress and keeps evaluating new proposals. The + /// different proposed blocks are indexed by their hash. This is used + /// to avoid running process proposal more than once internally because of + /// the shim or the recheck option (comet only calls it at most once + /// for a given height/round) + pub block_proposals_cache: CLruCache, } /// Last committed block @@ -84,6 +95,17 @@ pub struct LastBlock { pub time: DateTimeUtc, } +/// The result of process proposal that can be cached for future lookup +#[must_use] +#[derive(Debug, Clone)] +pub enum ProcessProposalCachedResult { + /// The proposed block was accepted by this node with the attached results + /// for every included tx + Accepted(Vec<(u32, String)>), + /// The proposed block was rejected by this node + Rejected, +} + /// The block storage data #[derive(Debug)] pub struct BlockStorage { @@ -143,6 +165,9 @@ where eth_events_queue: EthEventsQueue::default(), storage_read_past_height_limit, commit_only_data: CommitOnlyData::default(), + block_proposals_cache: CLruCache::new( + NonZeroUsize::new(10).unwrap(), + ), } } diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index 97686574d3..b5b8cdeca5 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -26,7 +26,9 @@ use std::fmt::Debug; use std::iter::Peekable; pub use host_env::{TxHostEnvState, VpHostEnvState}; -pub use in_memory::{BlockStorage, InMemory, LastBlock}; +pub use in_memory::{ + BlockStorage, InMemory, LastBlock, ProcessProposalCachedResult, +}; use namada_core::address::Address; use namada_core::arith::{self, checked}; use namada_core::eth_bridge_pool::is_pending_transfer_key; @@ -602,6 +604,9 @@ where #[cfg(any(test, feature = "testing"))] pub mod testing { + use std::num::NonZeroUsize; + + use clru::CLruCache; use namada_core::address; use namada_core::address::EstablishedAddressGen; use namada_core::chain::ChainId; @@ -665,6 +670,9 @@ pub mod testing { eth_events_queue: EthEventsQueue::default(), storage_read_past_height_limit: Some(1000), commit_only_data: CommitOnlyData::default(), + block_proposals_cache: CLruCache::new( + NonZeroUsize::new(10).unwrap(), + ), } } } @@ -764,7 +772,7 @@ mod tests { epochs_per_year: 100, masp_epoch_multiplier: 2, masp_fee_payment_gas_limit: 20_000, - gas_scale: 100_000_000, + gas_scale: 10_000_000, minimum_gas_price: BTreeMap::default(), is_native_token_transferable: true, }; diff --git a/crates/tests/src/e2e/ibc_tests.rs b/crates/tests/src/e2e/ibc_tests.rs index 808288b812..e4c7bcef06 100644 --- a/crates/tests/src/e2e/ibc_tests.rs +++ b/crates/tests/src/e2e/ibc_tests.rs @@ -1966,6 +1966,8 @@ fn submit_ibc_tx( signer, "--gas-token", NAM, + "--gas-limit", + "150000", "--node", &rpc ], @@ -2013,6 +2015,8 @@ fn transfer( &channel_id, "--port-id", &port_id, + "--gas-limit", + "150000", "--node", &rpc, ]; diff --git a/crates/tests/src/e2e/ledger_tests.rs b/crates/tests/src/e2e/ledger_tests.rs index b080983662..57bb4f0fac 100644 --- a/crates/tests/src/e2e/ledger_tests.rs +++ b/crates/tests/src/e2e/ledger_tests.rs @@ -2320,3 +2320,153 @@ fn rollback() -> Result<()> { Ok(()) } + +/// We test shielding, shielded to shielded and unshielding transfers: +/// 1. Run the ledger node +/// 2. Shield 20 BTC from Albert to PA(A) +/// 3. Transfer 7 BTC from SK(A) to PA(B) +/// 4. Assert BTC balance at VK(A) is 13 +/// 5. Unshield 5 BTC from SK(B) to Bertha +/// 6. Assert BTC balance at VK(B) is 2 +/// +/// NOTE: We need this test to verify the correctness of the proofs generation +/// and verification process because integration tests use mocks. +#[test] +fn masp_txs_and_queries() -> Result<()> { + // Lengthen epoch to ensure that a transaction can be constructed and + // submitted within the same block. Necessary to ensure that conversion is + // not invalidated. + let test = setup::network( + |mut genesis, base_dir| { + genesis.parameters.parameters.epochs_per_year = + epochs_per_year_from_min_duration(3600); + genesis.parameters.parameters.min_num_of_blocks = 1; + setup::set_validators(1, genesis, base_dir, default_port_offset) + }, + None, + )?; + // Run all cmds on the first validator + let who = Who::Validator(0); + set_ethereum_bridge_mode( + &test, + &test.net.chain_id, + who, + ethereum_bridge::ledger::Mode::Off, + None, + ); + + // 1. Run the ledger node + let _bg_ledger = + start_namada_ledger_node_wait_wasm(&test, Some(0), Some(40))? + .background(); + + let rpc_address = get_actor_rpc(&test, who); + let _ep1 = epoch_sleep(&test, &rpc_address, 720)?; + + // add necessary viewing keys to shielded context + let mut sync = run_as!( + test, + who, + Bin::Client, + vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + AB_VIEWING_KEY, + "--node", + &rpc_address, + ], + Some(15), + )?; + sync.assert_success(); + let txs_args = vec![ + // 2. Shield 20 BTC from Albert to PA(A) + ( + vec![ + "shield", + "--source", + ALBERT, + "--target", + AA_PAYMENT_ADDRESS, + "--token", + BTC, + "--amount", + "20", + ], + TX_APPLIED_SUCCESS, + ), + // 3. Transfer 7 BTC from SK(A) to PA(B) + ( + vec![ + "transfer", + "--source", + A_SPENDING_KEY, + "--target", + AB_PAYMENT_ADDRESS, + "--token", + BTC, + "--amount", + "7", + "--gas-payer", + CHRISTEL_KEY, + ], + TX_APPLIED_SUCCESS, + ), + // 4. Assert BTC balance at VK(A) is 13 + ( + vec!["balance", "--owner", AA_VIEWING_KEY, "--token", BTC], + "btc: 13", + ), + // 5. Unshield 5 BTC from SK(B) to Bertha + ( + vec![ + "unshield", + "--source", + B_SPENDING_KEY, + "--target", + BERTHA, + "--token", + BTC, + "--amount", + "5", + "--gas-payer", + CHRISTEL_KEY, + ], + TX_APPLIED_SUCCESS, + ), + // 6. Assert BTC balance at VK(B) is 2 + ( + vec!["balance", "--owner", AB_VIEWING_KEY, "--token", BTC], + "btc: 2", + ), + ]; + + for (tx_args, tx_result) in &txs_args { + // sync shielded context + let mut sync = run_as!( + test, + who, + Bin::Client, + vec!["shielded-sync", "--node", &rpc_address], + Some(15), + )?; + sync.assert_success(); + for &dry_run in &[true, false] { + let tx_args = if dry_run + && (tx_args[0] == "transfer" + || tx_args[0] == "shield" + || tx_args[0] == "unshield") + { + [tx_args.clone(), vec!["--dry-run"]].concat() + } else { + tx_args.clone() + }; + let mut client = + run_as!(test, who, Bin::Client, tx_args, Some(720))?; + + client.exp_string(tx_result)?; + } + } + + Ok(()) +} diff --git a/crates/tests/src/e2e/setup.rs b/crates/tests/src/e2e/setup.rs index c72f6cca5e..311fb8f966 100644 --- a/crates/tests/src/e2e/setup.rs +++ b/crates/tests/src/e2e/setup.rs @@ -292,7 +292,7 @@ where let mut sign_pre_genesis_txs = run_cmd( Bin::Client, args, - Some(5), + Some(15), &working_dir(), base_dir, format!("{}:{}", std::file!(), std::line!()), @@ -434,7 +434,7 @@ pub fn network( let mut init_network = run_cmd( Bin::Client, args, - Some(5), + Some(15), &working_dir, &genesis_dir, format!("{}:{}", std::file!(), std::line!()), diff --git a/crates/tests/src/integration/masp.rs b/crates/tests/src/integration/masp.rs index 3897ea66ba..336a4fe711 100644 --- a/crates/tests/src/integration/masp.rs +++ b/crates/tests/src/integration/masp.rs @@ -13,6 +13,7 @@ use namada_node::shell::testing::client::run; use namada_node::shell::testing::node::NodeResults; use namada_node::shell::testing::utils::{Bin, CapturedOutput}; use namada_sdk::masp::fs::FsShieldedUtils; +use namada_sdk::DEFAULT_GAS_LIMIT; use test_log::test; use super::setup; @@ -1504,7 +1505,7 @@ fn multiple_unfetched_txs_same_block() -> Result<()> { token: native_token.clone(), }, pk.clone(), - 20000.into(), + DEFAULT_GAS_LIMIT.into(), ); tx.sign_wrapper(sk.clone()); @@ -2183,10 +2184,7 @@ fn masp_fee_payment() -> Result<()> { let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); - let (mut node, _services) = setup::initialize_genesis(|mut genesis| { - genesis.parameters.parameters.masp_fee_payment_gas_limit = 20_000; - genesis - })?; + let (mut node, _services) = setup::setup()?; _ = node.next_masp_epoch(); // Add the relevant viewing keys to the wallet otherwise the shielded @@ -2231,7 +2229,7 @@ fn masp_fee_payment() -> Result<()> { "--token", NAM, "--amount", - "50000", + "500000", "--ledger-address", validator_one_rpc, ], @@ -2261,7 +2259,7 @@ fn masp_fee_payment() -> Result<()> { ) }); assert!(captured.result.is_ok()); - assert!(captured.contains("nam: 50000")); + assert!(captured.contains("nam: 500000")); // 1. Out of gas for masp fee payment let captured = CapturedOutput::of(|| { @@ -2279,7 +2277,7 @@ fn masp_fee_payment() -> Result<()> { "--amount", "1", "--gas-limit", - "2000", + "20000", "--gas-price", "1", "--disposable-gas-payer", @@ -2312,7 +2310,7 @@ fn masp_fee_payment() -> Result<()> { ) }); assert!(captured.result.is_ok()); - assert!(captured.contains("nam: 50000")); + assert!(captured.contains("nam: 500000")); // 2. Valid masp fee payment run( @@ -2329,7 +2327,7 @@ fn masp_fee_payment() -> Result<()> { "--amount", "10000", "--gas-limit", - "20000", + "200000", "--gas-price", "1", "--disposable-gas-payer", @@ -2363,7 +2361,7 @@ fn masp_fee_payment() -> Result<()> { ) }); assert!(captured.result.is_ok()); - assert!(captured.contains("nam: 20000")); + assert!(captured.contains("nam: 290000")); let captured = CapturedOutput::of(|| { run( &node, @@ -2396,7 +2394,7 @@ fn masp_fee_payment_gas_limit() -> Result<()> { let (mut node, _services) = setup::initialize_genesis(|mut genesis| { // Set an insufficient gas limit for masp fee payment to force all // transactions to fail - genesis.parameters.parameters.masp_fee_payment_gas_limit = 3_000; + genesis.parameters.parameters.masp_fee_payment_gas_limit = 10_000; genesis })?; _ = node.next_masp_epoch(); @@ -2548,10 +2546,7 @@ fn masp_fee_payment_with_non_disposable() -> Result<()> { let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); - let (mut node, _services) = setup::initialize_genesis(|mut genesis| { - genesis.parameters.parameters.masp_fee_payment_gas_limit = 20_000; - genesis - })?; + let (mut node, _services) = setup::setup()?; _ = node.next_masp_epoch(); // Add the relevant viewing keys to the wallet otherwise the shielded @@ -2596,7 +2591,7 @@ fn masp_fee_payment_with_non_disposable() -> Result<()> { "--token", NAM, "--amount", - // Drain balance of fee payer + // Decrease payer's balance to 1 "1999999", // Pay gas transparently "--gas-payer", @@ -2635,6 +2630,24 @@ fn masp_fee_payment_with_non_disposable() -> Result<()> { assert!(captured.result.is_ok()); assert!(captured.contains("nam: 1999999")); + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + ALBERT_KEY, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + assert!(captured.contains("nam: 1")); + // Masp fee payment to non-disposable address let captured = CapturedOutput::of(|| { run( @@ -2651,7 +2664,7 @@ fn masp_fee_payment_with_non_disposable() -> Result<()> { "--amount", "1", "--gas-limit", - "20000", + "200000", "--gas-price", "1", "--gas-payer", @@ -2690,7 +2703,7 @@ fn masp_fee_payment_with_non_disposable() -> Result<()> { ) }); assert!(captured.result.is_ok()); - assert!(captured.contains("nam: 1979999")); + assert!(captured.contains("nam: 1799999")); let captured = CapturedOutput::of(|| { run( @@ -2722,10 +2735,7 @@ fn masp_fee_payment_with_custom_spending_key() -> Result<()> { let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); - let (mut node, _services) = setup::initialize_genesis(|mut genesis| { - genesis.parameters.parameters.masp_fee_payment_gas_limit = 20_000; - genesis - })?; + let (mut node, _services) = setup::setup()?; _ = node.next_masp_epoch(); // Add the relevant viewing keys to the wallet otherwise the shielded @@ -2801,7 +2811,7 @@ fn masp_fee_payment_with_custom_spending_key() -> Result<()> { "--token", NAM, "--amount", - "30000", + "300000", "--ledger-address", validator_one_rpc, ], @@ -2851,7 +2861,7 @@ fn masp_fee_payment_with_custom_spending_key() -> Result<()> { ) }); assert!(captured.result.is_ok()); - assert!(captured.contains("nam: 30000")); + assert!(captured.contains("nam: 300000")); // Masp fee payment with custom gas payer let captured = CapturedOutput::of(|| { @@ -2869,7 +2879,7 @@ fn masp_fee_payment_with_custom_spending_key() -> Result<()> { "--amount", "9000", "--gas-limit", - "20000", + "200000", "--gas-price", "1", "--gas-spending-key", @@ -2927,7 +2937,7 @@ fn masp_fee_payment_with_custom_spending_key() -> Result<()> { ) }); assert!(captured.result.is_ok()); - assert!(captured.contains("nam: 11000")); + assert!(captured.contains("nam: 101000")); let captured = CapturedOutput::of(|| { run( @@ -2959,7 +2969,6 @@ fn masp_fee_payment_with_different_token() -> Result<()> { // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); let (mut node, _services) = setup::initialize_genesis(|mut genesis| { - genesis.parameters.parameters.masp_fee_payment_gas_limit = 20_000; // Whitelist BTC for gas payment genesis.parameters.parameters.minimum_gas_price.insert( "btc".into(), @@ -3049,7 +3058,7 @@ fn masp_fee_payment_with_different_token() -> Result<()> { "--token", BTC, "--amount", - "20000", + "200000", "--gas-payer", ALBERT_KEY, "--ledger-address", @@ -3118,7 +3127,7 @@ fn masp_fee_payment_with_different_token() -> Result<()> { ) }); assert!(captured.result.is_ok()); - assert!(captured.contains("btc: 20000")); + assert!(captured.contains("btc: 200000")); // Masp fee payment with custom token and gas payer let captured = CapturedOutput::of(|| { @@ -3138,7 +3147,7 @@ fn masp_fee_payment_with_different_token() -> Result<()> { "--gas-token", BTC, "--gas-limit", - "20000", + "200000", "--gas-price", "1", "--gas-spending-key", diff --git a/crates/token/src/lib.rs b/crates/token/src/lib.rs index 6ad9b323bb..8a27109e41 100644 --- a/crates/token/src/lib.rs +++ b/crates/token/src/lib.rs @@ -221,12 +221,13 @@ pub mod testing { pub use namada_core::token::*; pub use namada_trans_token::testing::*; use proptest::prelude::*; + use proptest::sample::SizeRange; use super::Transfer; prop_compose! { /// Generate a transparent transfer - fn arb_transparent_transfer()( + fn arb_single_transparent_transfer()( source in arb_non_internal_address(), target in arb_non_internal_address(), token in arb_established_address().prop_map(Address::Established), @@ -242,17 +243,20 @@ pub mod testing { } /// Generate a vectorized transparent transfer - pub fn arb_vectorized_transparent_transfer( - number_of_txs: usize, + pub fn arb_transparent_transfer( + number_of_txs: impl Into, ) -> impl Strategy { - proptest::collection::vec(arb_transparent_transfer(), 0..number_of_txs) - .prop_filter_map("Transfers must not overflow", |data| { - data.into_iter().try_fold( - Transfer::default(), - |acc, (source, target, token, amount)| { - acc.transfer(source, target, token, amount) - }, - ) - }) + proptest::collection::vec( + arb_single_transparent_transfer(), + number_of_txs, + ) + .prop_filter_map("Transfers must not overflow", |data| { + data.into_iter().try_fold( + Transfer::default(), + |acc, (source, target, token, amount)| { + acc.transfer(source, target, token, amount) + }, + ) + }) } } diff --git a/crates/tx/src/data/mod.rs b/crates/tx/src/data/mod.rs index 2cf49ec745..11386c0d02 100644 --- a/crates/tx/src/data/mod.rs +++ b/crates/tx/src/data/mod.rs @@ -22,10 +22,11 @@ use namada_core::borsh::{ BorshDeserialize, BorshSchema, BorshSerialize, BorshSerializeExt, }; use namada_core::hash::Hash; +use namada_core::ibc::IbcTxDataRefs; use namada_core::masp::MaspTxRefs; use namada_core::storage; use namada_events::Event; -use namada_gas::{Gas, VpsGas}; +use namada_gas::{VpsGas, WholeGas}; use namada_macros::BorshDeserializer; #[cfg(feature = "migrations")] use namada_migrations::*; @@ -166,81 +167,6 @@ pub fn hash_tx(tx_bytes: &[u8]) -> Hash { Hash(*digest.as_ref()) } -/// The set of inner tx results indexed by the inner tx hash -// The generic is only used to return typed errors in protocol for error -// management with regards to replay protection, whereas for logging we use -// strings -#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] -pub struct BatchResults(BTreeMap>); - -impl BatchResults { - /// Return a new set of batch results. - pub const fn new() -> Self { - Self(BTreeMap::new()) - } - - /// Insert an inner tx result into this [`BatchResults`]. - #[inline] - pub fn insert_inner_tx_result( - &mut self, - wrapper_hash: Option<&Hash>, - commitments: Either<&Hash, &TxCommitments>, - result: Result, - ) { - self.0 - .insert(compute_inner_tx_hash(wrapper_hash, commitments), result); - } - - /// Retrieve an inner tx result, if it exists. - #[inline] - pub fn get_inner_tx_result( - &self, - wrapper_hash: Option<&Hash>, - commitments: Either<&Hash, &TxCommitments>, - ) -> Option<&Result> { - self.0 - .get(&compute_inner_tx_hash(wrapper_hash, commitments)) - } - - /// Iterate over all the inner tx results. - #[inline] - pub fn iter( - &self, - ) -> impl Iterator)> + '_ { - self.0.iter() - } - - /// Return the length of the collecction of inner tx results. - #[inline] - pub fn len(&self) -> usize { - self.0.len() - } - - /// Check if the collecction of inner tx results is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Check if the collecction of inner tx results contains no errors. - #[inline] - pub fn are_results_ok(&self) -> bool { - self.iter().all(|(_, res)| res.is_ok()) - } - - /// Check if the collecction of inner tx results contains any ok results. - #[inline] - pub fn are_any_ok(&self) -> bool { - self.iter().any(|(_, res)| res.is_ok()) - } - - /// Check if the collecction of inner tx results contains any errors. - #[inline] - pub fn are_any_err(&self) -> bool { - self.iter().any(|(_, res)| res.is_err()) - } -} - /// Compute the hash of the some inner tx in a batch. pub fn compute_inner_tx_hash( wrapper_hash: Option<&Hash>, @@ -258,13 +184,48 @@ pub fn compute_inner_tx_hash( Hash(state.finalize_reset().into()) } -impl Default for BatchResults { +/// The extended transaction result, containing the references to masp +/// sections (if any) +pub struct ExtendedTxResult { + /// The transaction result + pub tx_result: TxResult, + /// The optional references to masp sections + pub masp_tx_refs: MaspTxRefs, + /// The optional data section hashes of IBC transaction + pub ibc_tx_data_refs: IbcTxDataRefs, +} + +impl Default for ExtendedTxResult { + fn default() -> Self { + Self { + tx_result: Default::default(), + masp_tx_refs: Default::default(), + ibc_tx_data_refs: Default::default(), + } + } +} + +#[derive(Debug, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] +/// The result of a dry run, included the actual transaction result and the gas +/// used +pub struct DryRunResult(pub TxResult, pub WholeGas); + +/// Transaction application result. More specifically the set of inner tx +/// results indexed by the inner tx hash +// The generic is only used to return typed errors in protocol for error +// management with regards to replay protection, whereas for logging we use +// strings +// TODO derive BorshSchema after +#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] +pub struct TxResult(pub BTreeMap>); + +impl Default for TxResult { fn default() -> Self { - Self(BTreeMap::default()) + Self(Default::default()) } } -impl Serialize for BatchResults { +impl Serialize for TxResult { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -278,11 +239,11 @@ impl Serialize for BatchResults { } } -struct BatchResultVisitor { +struct TxResultVisitor { _phantom: PhantomData, } -impl BatchResultVisitor { +impl TxResultVisitor { fn new() -> Self { Self { _phantom: PhantomData, @@ -290,21 +251,21 @@ impl BatchResultVisitor { } } -impl<'de, T> serde::de::Visitor<'de> for BatchResultVisitor +impl<'de, T> serde::de::Visitor<'de> for TxResultVisitor where T: serde::Deserialize<'de>, { - type Value = BatchResults; + type Value = TxResult; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("BatchResult") + formatter.write_str("a transaction's result") } fn visit_map(self, mut map: V) -> Result where V: serde::de::MapAccess<'de>, { - let mut result = BatchResults::::default(); + let mut result = TxResult::::default(); while let Some((key, value)) = map.next_entry()? { result.0.insert( @@ -317,53 +278,12 @@ where } } -impl<'de, T: Deserialize<'de>> serde::Deserialize<'de> for BatchResults { +impl<'de, T: Deserialize<'de>> serde::Deserialize<'de> for TxResult { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { - deserializer.deserialize_map(BatchResultVisitor::new()) - } -} - -/// The extended transaction result, containing the references to masp -/// sections (if any) -pub struct ExtendedTxResult { - /// The transaction result - pub tx_result: TxResult, - /// The optional references to masp sections - pub masp_tx_refs: MaspTxRefs, - /// The flag for IBC shielding transfer - pub is_ibc_shielding: bool, -} - -impl Default for ExtendedTxResult { - fn default() -> Self { - Self { - tx_result: Default::default(), - masp_tx_refs: Default::default(), - is_ibc_shielding: Default::default(), - } - } -} - -/// Transaction application result -#[derive( - Clone, Debug, BorshSerialize, BorshDeserialize, Serialize, Deserialize, -)] -pub struct TxResult { - /// Total gas used by the transaction (includes the gas used by VPs) - pub gas_used: Gas, - /// The results of the batch, indexed by the hash of each inner tx - pub batch_results: BatchResults, -} - -impl Default for TxResult { - fn default() -> Self { - Self { - gas_used: Default::default(), - batch_results: Default::default(), - } + deserializer.deserialize_map(TxResultVisitor::new()) } } @@ -373,7 +293,7 @@ impl TxResult { let mut batch_results: BTreeMap> = BTreeMap::new(); - for (hash, res) in self.batch_results.0 { + for (hash, res) in self.0 { let res = match res { Ok(value) => Ok(value), Err(e) => Err(e.to_string()), @@ -381,25 +301,99 @@ impl TxResult { batch_results.insert(hash, res); } - TxResult { - gas_used: self.gas_used, - batch_results: BatchResults(batch_results), - } + TxResult(batch_results) } /// Converts this result to [`ExtendedTxResult`] pub fn to_extended_result( self, - masp_tx_refs: Option, + masp_section_refs: Option>, ) -> ExtendedTxResult { + let (masp_tx_refs, ibc_tx_data_refs) = match masp_section_refs { + Some(Either::Left(masp_tx_refs)) => { + (masp_tx_refs, Default::default()) + } + Some(Either::Right(ibc_tx_data_refs)) => { + (Default::default(), ibc_tx_data_refs) + } + None => (Default::default(), Default::default()), + }; ExtendedTxResult { tx_result: self, - masp_tx_refs: masp_tx_refs.unwrap_or_default(), - is_ibc_shielding: false, + masp_tx_refs, + ibc_tx_data_refs, } } } +impl TxResult { + /// Return a new set of tx results. + pub const fn new() -> Self { + Self(BTreeMap::new()) + } + + /// Insert an inner tx result into this [`TxResult`]. + #[inline] + pub fn insert_inner_tx_result( + &mut self, + wrapper_hash: Option<&Hash>, + commitments: Either<&Hash, &TxCommitments>, + result: Result, + ) { + self.0 + .insert(compute_inner_tx_hash(wrapper_hash, commitments), result); + } + + /// Retrieve an inner tx result, if it exists. + #[inline] + pub fn get_inner_tx_result( + &self, + wrapper_hash: Option<&Hash>, + commitments: Either<&Hash, &TxCommitments>, + ) -> Option<&Result> { + self.0 + .get(&compute_inner_tx_hash(wrapper_hash, commitments)) + } + + /// Iterate over all the inner tx results. + #[inline] + pub fn iter( + &self, + ) -> impl Iterator)> + '_ { + self.0.iter() + } + + /// Return the length of the collecction of inner tx results. + #[inline] + pub fn len(&self) -> usize { + self.0.len() + } + + /// Check if the collecction of inner tx results is empty. + #[inline] + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Check if the collecction of inner tx results contains no errors. + #[inline] + pub fn are_results_ok(&self) -> bool { + self.iter().all(|(_, res)| res.is_ok()) + } + + /// Check if the collecction of inner tx results contains any ok results. + #[inline] + pub fn are_any_ok(&self) -> bool { + self.iter().any(|(_, res)| res.is_ok()) + } + + /// Check if the collecction of inner tx results contains any errors. + #[inline] + pub fn are_any_err(&self) -> bool { + self.iter().any(|(_, res)| res.is_err()) + } +} + #[cfg(feature = "migrations")] namada_macros::derive_borshdeserializer!(TxResult::); @@ -500,7 +494,7 @@ pub struct VpsResult { impl fmt::Display for TxResult { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if f.alternate() { - write!(f, "Transaction is valid. Gas used: {}", self.gas_used) + write!(f, "Transaction is valid.") } else { write!(f, "{}", serde_json::to_string(self).unwrap()) } diff --git a/crates/tx/src/data/pgf.rs b/crates/tx/src/data/pgf.rs index 72de35f42f..8b2c9f3944 100644 --- a/crates/tx/src/data/pgf.rs +++ b/crates/tx/src/data/pgf.rs @@ -1,5 +1,5 @@ use namada_core::address::Address; -use namada_core::borsh::{BorshDeserialize, BorshSerialize}; +use namada_core::borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use namada_core::collections::HashMap; use namada_core::dec::Dec; use namada_macros::BorshDeserializer; @@ -20,6 +20,7 @@ pub enum PgfError { Debug, Clone, PartialEq, + BorshSchema, BorshSerialize, BorshDeserialize, BorshDeserializer, diff --git a/crates/tx/src/data/wrapper.rs b/crates/tx/src/data/wrapper.rs index 3a2f1ebcc7..137054ed5a 100644 --- a/crates/tx/src/data/wrapper.rs +++ b/crates/tx/src/data/wrapper.rs @@ -9,7 +9,7 @@ use namada_core::borsh::{ use namada_core::key::*; use namada_core::token::{Amount, DenominatedAmount}; use namada_core::uint::Uint; -use namada_gas::Gas; +use namada_gas::{Gas, WholeGas}; use namada_macros::BorshDeserializer; #[cfg(feature = "migrations")] use namada_migrations::*; @@ -111,10 +111,22 @@ impl From for Amount { } } +impl From for WholeGas { + fn from(value: GasLimit) -> Self { + value.0.into() + } +} + +impl From for GasLimit { + fn from(value: WholeGas) -> Self { + u64::from(value).into() + } +} + impl GasLimit { /// Convert the gas limit into scaled gas - pub fn as_scaled_gas(&self, scale: u64) -> Result { - Gas::from_whole_units(u64::from(*self), scale).ok_or_else(|| { + pub fn as_scaled_gas(self, scale: u64) -> Result { + Gas::from_whole_units(self.into(), scale).ok_or_else(|| { std::io::Error::new( std::io::ErrorKind::InvalidInput, "gas overflow", diff --git a/crates/tx/src/types.rs b/crates/tx/src/types.rs index a8b3198006..ed185b9a4f 100644 --- a/crates/tx/src/types.rs +++ b/crates/tx/src/types.rs @@ -1298,7 +1298,15 @@ impl Tx { /// Get the data designated by the transaction data hash in the header at /// the specified commitment pub fn data(&self, cmt: &TxCommitments) -> Option> { - match self.get_section(&cmt.data_hash).as_ref().map(Cow::as_ref) { + self.get_data_section(&cmt.data_hash) + } + + /// Get the data designated by the transaction data hash + pub fn get_data_section( + &self, + data_hash: &namada_core::hash::Hash, + ) -> Option> { + match self.get_section(data_hash).as_ref().map(Cow::as_ref) { Some(Section::Data(data)) => Some(data.data.clone()), _ => None, } diff --git a/examples/tx_schema.rs b/examples/tx_schema.rs index 1fcf24e162..e76cec4a08 100644 --- a/examples/tx_schema.rs +++ b/examples/tx_schema.rs @@ -3,6 +3,7 @@ use std::error::Error; use masp_primitives::transaction::components::sapling::builder::StoredBuildParams; use namada_sdk::borsh::BorshSchema; +use namada_sdk::testing::TxData; use namada_sdk::tx::Tx; fn main() -> Result<(), Box> { @@ -13,6 +14,7 @@ fn main() -> Result<(), Box> { } let mut definitions = BTreeMap::new(); Tx::add_definitions_recursively(&mut definitions); + TxData::add_definitions_recursively(&mut definitions); StoredBuildParams::add_definitions_recursively(&mut definitions); std::fs::write(&args[1], format!("{:#?}", definitions)) .expect("unable to save schema"); diff --git a/genesis/localnet/parameters.toml b/genesis/localnet/parameters.toml index 834da9dd08..368ca0f108 100644 --- a/genesis/localnet/parameters.toml +++ b/genesis/localnet/parameters.toml @@ -21,9 +21,9 @@ masp_epoch_multiplier = 2 # Max gas for block max_block_gas = 20000000 # Masp fee payment gas limit -masp_fee_payment_gas_limit = 20000 +masp_fee_payment_gas_limit = 150_000 # Gas scale -gas_scale = 100_000_000 +gas_scale = 10_000_000 # Map of the cost per gas unit for every token allowed for fee payment [parameters.minimum_gas_price] diff --git a/genesis/starter/parameters.toml b/genesis/starter/parameters.toml index b89dd47555..7ab927009c 100644 --- a/genesis/starter/parameters.toml +++ b/genesis/starter/parameters.toml @@ -23,9 +23,9 @@ max_signatures_per_transaction = 15 # Max gas for block max_block_gas = 20000000 # Masp fee payment gas limit -masp_fee_payment_gas_limit = 20000 +masp_fee_payment_gas_limit = 150_000 # Gas scale -gas_scale = 100_000_000 +gas_scale = 10_000_000 # Map of the cost per gas unit for every token allowed for fee payment [parameters.minimum_gas_price] diff --git a/scripts/get_hermes.sh b/scripts/get_hermes.sh index 9ae6c1a829..8c74b20bde 100755 --- a/scripts/get_hermes.sh +++ b/scripts/get_hermes.sh @@ -4,7 +4,7 @@ set -Eo pipefail HERMES_MAJORMINOR="1.9" HERMES_PATCH="0" -HERMES_SUFFIX="-namada-beta13-rc2" +HERMES_SUFFIX="-namada-beta14-rc" HERMES_REPO="https://github.com/heliaxdev/hermes" diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 94a4eac8da..d2fce2a6a0 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -525,45 +525,16 @@ dependencies = [ "subtle", ] -[[package]] -name = "bnum" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" - -[[package]] -name = "borsh" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" -dependencies = [ - "borsh-derive 0.10.3", - "hashbrown 0.12.3", -] - [[package]] name = "borsh" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0901fc8eb0aca4c83be0106d6f2db17d86a08dfc2c25f0e84464bf381158add6" dependencies = [ - "borsh-derive 1.4.0", + "borsh-derive", "cfg_aliases", ] -[[package]] -name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "borsh-derive" version = "1.4.0" @@ -578,34 +549,12 @@ dependencies = [ "syn_derive", ] -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "borsh-ext" version = "1.2.0" source = "git+https://github.com/heliaxdev/borsh-ext?tag=v1.2.0#a62fee3e847e512cad9ac0f1fd5a900e5db9ba37" dependencies = [ - "borsh 1.4.0", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "borsh", ] [[package]] @@ -954,75 +903,6 @@ dependencies = [ "windows-sys 0.33.0", ] -[[package]] -name = "cosmwasm-crypto" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd50718a2b6830ce9eb5d465de5a018a12e71729d66b70807ce97e6dd14f931d" -dependencies = [ - "digest 0.10.7", - "ecdsa", - "ed25519-zebra", - "k256", - "rand_core 0.6.4", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "242e98e7a231c122e08f300d9db3262d1007b51758a8732cd6210b3e9faa4f3a" -dependencies = [ - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-schema" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7879036156092ad1c22fe0d7316efc5a5eceec2bc3906462a2560215f2a2f929" -dependencies = [ - "cosmwasm-schema-derive", - "schemars", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "cosmwasm-schema-derive" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb57855fbfc83327f8445ae0d413b1a05ac0d68c396ab4d122b2abd7bb82cb6" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-std" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" -dependencies = [ - "base64 0.21.7", - "bech32 0.9.1", - "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 = "cpufeatures" version = "0.2.11" @@ -1216,19 +1096,6 @@ dependencies = [ "cipher", ] -[[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-ng" version = "4.1.1" @@ -1242,17 +1109,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "cw-storage-plus" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - [[package]] name = "darling" version = "0.14.4" @@ -1410,13 +1266,13 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -1462,9 +1318,9 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", @@ -1572,21 +1428,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ed25519-zebra" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" -dependencies = [ - "curve25519-dalek", - "hashbrown 0.12.3", - "hex", - "rand_core 0.6.4", - "serde", - "sha2 0.9.9", - "zeroize", -] - [[package]] name = "either" version = "1.12.0" @@ -2103,12 +1944,39 @@ dependencies = [ "paste", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2118,12 +1986,6 @@ 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 = "fpe" version = "0.6.1" @@ -2474,9 +2336,9 @@ dependencies = [ [[package]] name = "http" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -2542,6 +2404,19 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "iana-time-zone" version = "0.1.58" @@ -2568,8 +2443,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9298a8de81eea8d496672e47f13ab1ae5145b3b554ec3951222197697e1cf82" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-apps", "ibc-clients", @@ -2582,25 +2456,23 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e4d7728ae132ecb49286f225d0ab6ad56b2a15af47e019da45ad23fd789d76f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", - "serde-json-wasm 1.0.1", + "serde-json-wasm", ] [[package]] name = "ibc-app-nft-transfer-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333b2fcc0226d150e996fddd3fd2041460c7ed7e7594b65077026c7e38587329" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "base64 0.21.7", - "borsh 0.10.3", + "base64 0.22.1", + "borsh", "derive_more", "displaydoc", - "http 1.0.0", + "http 1.1.0", "ibc-app-transfer-types", "ibc-core", "ibc-proto", @@ -2609,27 +2481,25 @@ dependencies = [ "scale-info", "schemars", "serde", - "serde-json-wasm 1.0.1", + "serde-json-wasm", ] [[package]] name = "ibc-app-transfer" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf138e322daa7b757b66a8c9a5bcac00773136f4b939b6cfb43bb95576ba59d" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-app-transfer-types", "ibc-core", - "serde-json-wasm 1.0.1", + "serde-json-wasm", ] [[package]] name = "ibc-app-transfer-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8777875777e43f3c18a340ac5ea2223dc87a67b60d99e451142eac3b7b7a46" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core", @@ -2645,34 +2515,16 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac849a9d4f6097cc81405b00428fd73b04ce5290d806ce7f5c8afd42fbfb9bd" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", ] -[[package]] -name = "ibc-client-cw" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14bf49f8f43c3fea593d7c2413e061f8df607de45e6f7d76de5346a456f6addd" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "derive_more", - "ibc-client-wasm-types", - "ibc-core", - "prost", - "serde", -] - [[package]] name = "ibc-client-tendermint" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804dcd81f62608c453e72f669b2df986eb49d4b4381deac2a70bd33ee94cef7f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -2682,27 +2534,14 @@ dependencies = [ "ibc-core-host", "ibc-primitives", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-light-client-verifier", ] -[[package]] -name = "ibc-client-tendermint-cw" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d6d96b221fb6b68dc89c49150f83110928aeac146f90a434dfa5e354fbf8ca7" -dependencies = [ - "cosmwasm-std", - "ibc-client-cw", - "ibc-client-tendermint", - "ibc-core", -] - [[package]] name = "ibc-client-tendermint-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b41444137be02cabc484079443f447d23e746fabd9ac6fd5d99faac0b30a5f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -2711,19 +2550,17 @@ dependencies = [ "ibc-primitives", "ibc-proto", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-light-client-verifier", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", ] [[package]] name = "ibc-client-wasm-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc05b707ee957b1272877606379647ae1e5897316a3406b6a93e1885ee99e68" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "base64 0.21.7", - "cosmwasm-schema", + "base64 0.22.1", "displaydoc", "ibc-core-client", "ibc-core-host-types", @@ -2735,8 +2572,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675754a0a5f2f70f71445338fa4d8b49d3c84ce1cf4748ca6c98bf6ede9c4bfc" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -2745,8 +2581,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cb69c4ee05d367fa321acf67ec00d3e9f8ecfef013accdb05889db32ff2de3f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2762,8 +2597,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5dcc1c14a92f01e556d72d834f842bb655043a7e122ebb8aabdb5e9df600aa8" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -2778,10 +2612,9 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2744ad32ae7360caefb80f495800f883f5e5687cfbd74ff82a444b59a47af7" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-client-types", @@ -2796,14 +2629,13 @@ dependencies = [ "serde", "sha2 0.10.8", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-client" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80071ac73dd4f3436bf1aef03c9b1715a4db0914f738904c281449dc05a0a9cf" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -2816,8 +2648,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9f751b62cad4195be5347646151020fd27c2924f10d82d6301a675fac544dd" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -2827,16 +2658,15 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-client-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "423e9e9a70b78fabc94c51dae76800459e126f891ae0987e88ac5e12c36e24de" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-commitment-types", @@ -2848,16 +2678,15 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-commitment-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b323c91e58ea7b573e01b8e76d13f146c97c245ada0aab3070576d54288f30" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-primitives", @@ -2873,23 +2702,23 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31271364789ccfc12c25afa21b47274d7e07bf49b1f728fd66cfa6c29daaf4a" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ + "ibc-client-wasm-types", "ibc-core-client", "ibc-core-connection-types", "ibc-core-handler-types", "ibc-core-host", "ibc-primitives", + "prost", ] [[package]] name = "ibc-core-connection-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d302a36925469589a911dab66654f390b87e98608d07515e47f5c7e51dffe7" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-client-types", @@ -2902,14 +2731,13 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-handler" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4523b9f77d3a1a391a3d63737760be44b23bc9b09ed297883a34654383b9b0e2" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2924,10 +2752,9 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b229a92aa8b06ab9ccde6e1b3dad597deb97cb40e3bb6a631799b4cd2ad124" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-channel-types", @@ -2943,14 +2770,13 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-host" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ed7421f285225b78f3d020df6126b61f94b9eb370a83e42fbd4e9c8b04162fa" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -2968,8 +2794,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b25b5b45cf47b1e73211a83adf3a753f1acdba887cd3bc5357d6f547d4a3e8c" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -2986,16 +2811,15 @@ dependencies = [ "serde", "sha2 0.10.8", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-host-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939178939d33e5af1aca19608b019233d753f3734b828d66f40152b382f3db53" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-primitives", @@ -3008,8 +2832,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328e6db6d3aa7126278c46c3dff779aa961952a63d031d3ddf4c202f4a3faad4" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -3023,10 +2846,9 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4175b57087b28759364572683b335ec4fe63a6f938f1a5d0c383a6297a032155" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-host-types", @@ -3037,14 +2859,13 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-derive" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d961d2194fd5229961835d2eb78091906ef8afbaaa55bce7ad41bf3ead8aa9" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "proc-macro2", "quote", @@ -3054,10 +2875,9 @@ dependencies = [ [[package]] name = "ibc-primitives" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3340c4908f1a1a36863270ac976e0295fbd1911cbc4609ab406967fd8ccc04" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-proto", @@ -3066,18 +2886,18 @@ dependencies = [ "scale-info", "schemars", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "time", ] [[package]] name = "ibc-proto" -version = "0.44.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66080040d5a4800d52966d55b055400f86b79c34b854b935bef03c87aacda62a" +checksum = "6cb09e0b52b8a16e98ce98845e7c15b018440f3c56defa12fa44782cd66bab65" dependencies = [ "base64 0.22.1", - "borsh 0.10.3", + "borsh", "bytes", "flex-error", "ics23", @@ -3088,15 +2908,14 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", "tonic", ] [[package]] name = "ibc-query" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a0a3c4ea045cb0971253508c9b074d2b80271f8e57d3716b67bc0b6c8365c6c" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "displaydoc", "ibc", @@ -3107,22 +2926,18 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28f040bb9654b2e618dc75a43d101f69678eeb665fdbef5e5755750ab72625a" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "basecoin-store", "derive_more", "displaydoc", "ibc", - "ibc-client-cw", - "ibc-client-tendermint-cw", "ibc-proto", "ibc-query", "parking_lot", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-testgen", - "tracing", "typed-builder", ] @@ -3228,7 +3043,7 @@ name = "index-set" version = "0.8.0" source = "git+https://github.com/heliaxdev/index-set?tag=v0.8.1#b0d928f83cf0d465ccda299d131e8df2859b5184" dependencies = [ - "borsh 1.4.0", + "borsh", "serde", ] @@ -3248,7 +3063,7 @@ name = "indexmap" version = "2.2.4" source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" dependencies = [ - "borsh 1.4.0", + "borsh", "equivalent", "hashbrown 0.14.3", "serde", @@ -3520,7 +3335,7 @@ name = "masp_note_encryption" version = "1.0.0" source = "git+https://github.com/anoma/masp?rev=8d83b172698098fba393006016072bc201ed9ab7#8d83b172698098fba393006016072bc201ed9ab7" dependencies = [ - "borsh 1.4.0", + "borsh", "chacha20", "chacha20poly1305", "cipher", @@ -3539,7 +3354,7 @@ dependencies = [ "blake2b_simd", "blake2s_simd", "bls12_381", - "borsh 1.4.0", + "borsh", "byteorder", "ff", "fpe", @@ -3697,7 +3512,7 @@ name = "namada" version = "0.40.0" dependencies = [ "async-trait", - "borsh 1.4.0", + "borsh", "borsh-ext", "clru", "either", @@ -3753,7 +3568,7 @@ dependencies = [ name = "namada_account" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "linkme", "namada_core", "namada_macros", @@ -3777,7 +3592,7 @@ name = "namada_core" version = "0.40.0" dependencies = [ "bech32 0.8.1", - "borsh 1.4.0", + "borsh", "borsh-ext", "chrono", "data-encoding", @@ -3811,8 +3626,8 @@ dependencies = [ "sha2 0.9.9", "smooth-operator", "sparse-merkle-tree", - "tendermint 0.36.0", - "tendermint-proto 0.36.0", + "tendermint 0.37.0", + "tendermint-proto 0.37.0", "thiserror", "tiny-keccak", "tracing", @@ -3824,7 +3639,7 @@ dependencies = [ name = "namada_ethereum_bridge" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "ethers", "eyre", "itertools 0.12.1", @@ -3851,7 +3666,7 @@ dependencies = [ name = "namada_events" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "linkme", "namada_core", "namada_macros", @@ -3866,7 +3681,7 @@ dependencies = [ name = "namada_gas" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "linkme", "namada_core", "namada_events", @@ -3880,7 +3695,7 @@ dependencies = [ name = "namada_governance" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "itertools 0.12.1", "konst", "linkme", @@ -3903,7 +3718,7 @@ dependencies = [ name = "namada_ibc" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "data-encoding", "ibc", "ibc-derive", @@ -3945,7 +3760,7 @@ dependencies = [ name = "namada_merkle_tree" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "eyre", "ics23", "namada_core", @@ -3979,7 +3794,7 @@ dependencies = [ name = "namada_proof_of_stake" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "konst", "linkme", "namada_account", @@ -4013,7 +3828,7 @@ version = "0.40.0" dependencies = [ "async-trait", "bimap", - "borsh 1.4.0", + "borsh", "borsh-ext", "circular-queue", "clap", @@ -4025,6 +3840,7 @@ dependencies = [ "ethers", "eyre", "fd-lock", + "flume", "futures", "itertools 0.12.1", "jubjub", @@ -4059,6 +3875,7 @@ dependencies = [ "rand 0.8.5", "rand_core 0.6.4", "regex", + "reqwest", "serde", "serde_json", "sha2 0.9.9", @@ -4079,7 +3896,7 @@ dependencies = [ name = "namada_shielded_token" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "lazy_static", "masp_primitives", "masp_proofs", @@ -4100,7 +3917,8 @@ dependencies = [ name = "namada_state" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", + "clru", "itertools 0.12.1", "linkme", "namada_core", @@ -4124,7 +3942,7 @@ dependencies = [ name = "namada_storage" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "itertools 0.12.1", "linkme", "namada_core", @@ -4143,7 +3961,7 @@ dependencies = [ name = "namada_test_utils" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "namada_core", "strum 0.24.1", ] @@ -4179,7 +3997,7 @@ dependencies = [ name = "namada_token" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "namada_core", "namada_events", "namada_macros", @@ -4206,7 +4024,7 @@ version = "0.40.0" dependencies = [ "ark-bls12-381", "bitflags 2.5.0", - "borsh 1.4.0", + "borsh", "data-encoding", "either", "konst", @@ -4243,7 +4061,7 @@ dependencies = [ name = "namada_tx_prelude" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "masp_primitives", "namada_account", "namada_core", @@ -4264,7 +4082,7 @@ dependencies = [ name = "namada_vm_env" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "masp_primitives", "namada_core", ] @@ -4273,7 +4091,7 @@ dependencies = [ name = "namada_vote_ext" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "linkme", "namada_core", "namada_macros", @@ -4300,7 +4118,7 @@ dependencies = [ name = "namada_vp_prelude" version = "0.40.0" dependencies = [ - "borsh 1.4.0", + "borsh", "namada_account", "namada_core", "namada_events", @@ -4317,6 +4135,32 @@ dependencies = [ "sha2 0.9.9", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nonempty" version = "0.7.0" @@ -4521,6 +4365,50 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "orion" version = "0.16.1" @@ -4550,9 +4438,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec", @@ -4564,11 +4452,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -4582,9 +4470,9 @@ checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -4786,6 +4674,12 @@ dependencies = [ "spki", ] +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "poly1305" version = "0.8.0" @@ -4833,25 +4727,6 @@ dependencies = [ "uint", ] -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml 0.5.11", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - [[package]] name = "proc-macro-crate" version = "2.0.0" @@ -5263,10 +5138,12 @@ dependencies = [ "http 0.2.11", "http-body", "hyper", + "hyper-tls", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -5275,6 +5152,7 @@ dependencies = [ "serde_urlencoded", "system-configuration", "tokio", + "tokio-native-tls", "tower-service", "url", "wasm-bindgen", @@ -5519,9 +5397,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "cfg-if", "derive_more", @@ -5531,21 +5409,30 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "schemars_derive", @@ -5556,14 +5443,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -5615,6 +5502,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "self_cell" version = "1.0.4" @@ -5669,15 +5579,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-json-wasm" -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" @@ -5730,13 +5631,13 @@ dependencies = [ [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -5974,7 +5875,7 @@ name = "sparse-merkle-tree" version = "0.3.1-pre" source = "git+https://github.com/heliaxdev/sparse-merkle-tree?rev=bab8cb96872db22cc9a139b2d3dfc4e00521d097#bab8cb96872db22cc9a139b2d3dfc4e00521d097" dependencies = [ - "borsh 1.4.0", + "borsh", "cfg-if", "ics23", "itertools 0.12.1", @@ -5992,6 +5893,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -6225,9 +6129,9 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b50aae6ec24c3429149ad59b5b8d3374d7804d4c7d6125ceb97cb53907fb68d" +checksum = "954496fbc9716eb4446cdd6d00c071a3e2f22578d62aa03b40c7e5b4fda3ed42" dependencies = [ "bytes", "digest 0.10.7", @@ -6249,35 +6153,35 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", "time", "zeroize", ] [[package]] name = "tendermint-config" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e07b383dc8780ebbec04cfb603f3fdaba6ea6663d8dd861425b1ffa7761fe90d" +checksum = "f84b11b57d20ee4492a1452faff85f5c520adc36ca9fe5e701066935255bb89f" dependencies = [ "flex-error", "serde", "serde_json", - "tendermint 0.36.0", + "tendermint 0.37.0", "toml 0.8.2", "url", ] [[package]] name = "tendermint-light-client-verifier" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4216e487165e5dbd7af79952eaa0d5f06c5bde861eb76c690acd7f2d2a19395c" +checksum = "3848090df4502a09ee27cb1a00f1835e1111c8993b22c5e1e41ffb7f6f09d57e" dependencies = [ "derive_more", "flex-error", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "time", ] @@ -6301,9 +6205,9 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f193d04afde6592c20fd70788a10b8cb3823091c07456db70d8a93f5fb99c1" +checksum = "dc87024548c7f3da479885201e3da20ef29e85a3b13d04606b380ac4c7120d87" dependencies = [ "bytes", "flex-error", @@ -6317,9 +6221,9 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e3c231a3632cab53f92ad4161c730c468c08cfe4f0aa5a6735b53b390aecbd" +checksum = "dfdc2281e271277fda184d96d874a6fe59f569b130b634289257baacfc95aa85" dependencies = [ "async-trait", "bytes", @@ -6334,9 +6238,9 @@ dependencies = [ "serde_json", "subtle", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-config", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", "thiserror", "time", "url", @@ -6346,9 +6250,9 @@ dependencies = [ [[package]] name = "tendermint-testgen" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b233cec83c56c413ccc346af866cb9206a14d468fcecf0255080107bc9b103c0" +checksum = "318a0e38b3b7b36b4078d78446d4284088aa9b173d519fc804c3ee4683972934" dependencies = [ "ed25519-consensus", "gumdrop", @@ -6356,7 +6260,7 @@ dependencies = [ "serde_json", "simple-error", "tempfile", - "tendermint 0.36.0", + "tendermint 0.37.0", "time", ] @@ -6534,6 +6438,16 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" @@ -7012,18 +6926,18 @@ dependencies = [ [[package]] name = "typed-builder" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47c0496149861b7c95198088cbf36645016b1a0734cf350c50e2a38e070f38a" +checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982ee4197351b5c9782847ef5ec1fdcaf50503fb19d68f9771adae314e72b492" +checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" dependencies = [ "proc-macro2", "quote", @@ -7164,6 +7078,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" diff --git a/wasm/checksums.json b/wasm/checksums.json index d9882a84df..f9af0e6bf0 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -23,4 +23,4 @@ "tx_withdraw.wasm": "tx_withdraw.358d5c6556ae07e0175c230c340d23f21ce0c9cde599b52b4d32b569253cbb5b.wasm", "vp_implicit.wasm": "vp_implicit.8bdb0fb0cace962ac68b9afd0030dcbdbfc3d140437cffdb8e7bf52172689348.wasm", "vp_user.wasm": "vp_user.1398e393bd42c0a2e63d1bc5cccd9e2bedaf4d70711927e60b8a408254477e38.wasm" -} \ No newline at end of file +} diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index 2e7778bbe4..b7904746d7 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -568,45 +568,16 @@ dependencies = [ "subtle", ] -[[package]] -name = "bnum" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" - -[[package]] -name = "borsh" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" -dependencies = [ - "borsh-derive 0.10.3", - "hashbrown 0.12.3", -] - [[package]] name = "borsh" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9897ef0f1bd2362169de6d7e436ea2237dc1085d7d1e4db75f4be34d86f309d1" dependencies = [ - "borsh-derive 1.2.1", + "borsh-derive", "cfg_aliases", ] -[[package]] -name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "borsh-derive" version = "1.2.1" @@ -614,41 +585,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478b41ff04256c5c8330f3dfdaaae2a5cc976a8e75088bafa4625b0d0208de8c" dependencies = [ "once_cell", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 2.0.65", "syn_derive", ] -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "borsh-ext" version = "1.2.0" source = "git+https://github.com/heliaxdev/borsh-ext?tag=v1.2.0#a62fee3e847e512cad9ac0f1fd5a900e5db9ba37" dependencies = [ - "borsh 1.2.1", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "borsh", ] [[package]] @@ -1018,75 +967,6 @@ dependencies = [ "windows-sys 0.33.0", ] -[[package]] -name = "cosmwasm-crypto" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd50718a2b6830ce9eb5d465de5a018a12e71729d66b70807ce97e6dd14f931d" -dependencies = [ - "digest 0.10.7", - "ecdsa", - "ed25519-zebra", - "k256", - "rand_core 0.6.4", - "thiserror", -] - -[[package]] -name = "cosmwasm-derive" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "242e98e7a231c122e08f300d9db3262d1007b51758a8732cd6210b3e9faa4f3a" -dependencies = [ - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-schema" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7879036156092ad1c22fe0d7316efc5a5eceec2bc3906462a2560215f2a2f929" -dependencies = [ - "cosmwasm-schema-derive", - "schemars", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "cosmwasm-schema-derive" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb57855fbfc83327f8445ae0d413b1a05ac0d68c396ab4d122b2abd7bb82cb6" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "cosmwasm-std" -version = "1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" -dependencies = [ - "base64 0.21.7", - "bech32 0.9.1", - "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 = "cpufeatures" version = "0.2.11" @@ -1280,19 +1160,6 @@ dependencies = [ "cipher", ] -[[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-ng" version = "4.1.1" @@ -1306,17 +1173,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "cw-storage-plus" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" -dependencies = [ - "cosmwasm-std", - "schemars", - "serde", -] - [[package]] name = "darling" version = "0.14.4" @@ -1474,13 +1330,13 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.65", ] [[package]] @@ -1526,9 +1382,9 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", @@ -1636,21 +1492,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ed25519-zebra" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" -dependencies = [ - "curve25519-dalek", - "hashbrown 0.12.3", - "hex", - "rand_core 0.6.4", - "serde", - "sha2 0.9.9", - "zeroize", -] - [[package]] name = "either" version = "1.12.0" @@ -2167,12 +2008,39 @@ dependencies = [ "paste", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2182,12 +2050,6 @@ 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 = "fpe" version = "0.6.1" @@ -2538,9 +2400,9 @@ dependencies = [ [[package]] name = "http" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -2606,6 +2468,19 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "iana-time-zone" version = "0.1.58" @@ -2632,8 +2507,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9298a8de81eea8d496672e47f13ab1ae5145b3b554ec3951222197697e1cf82" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-apps", "ibc-clients", @@ -2646,25 +2520,23 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e4d7728ae132ecb49286f225d0ab6ad56b2a15af47e019da45ad23fd789d76f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", - "serde-json-wasm 1.0.1", + "serde-json-wasm", ] [[package]] name = "ibc-app-nft-transfer-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333b2fcc0226d150e996fddd3fd2041460c7ed7e7594b65077026c7e38587329" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "base64 0.21.7", - "borsh 0.10.3", + "base64 0.22.1", + "borsh", "derive_more", "displaydoc", - "http 1.0.0", + "http 1.1.0", "ibc-app-transfer-types", "ibc-core", "ibc-proto", @@ -2673,27 +2545,25 @@ dependencies = [ "scale-info", "schemars", "serde", - "serde-json-wasm 1.0.1", + "serde-json-wasm", ] [[package]] name = "ibc-app-transfer" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf138e322daa7b757b66a8c9a5bcac00773136f4b939b6cfb43bb95576ba59d" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-app-transfer-types", "ibc-core", - "serde-json-wasm 1.0.1", + "serde-json-wasm", ] [[package]] name = "ibc-app-transfer-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8777875777e43f3c18a340ac5ea2223dc87a67b60d99e451142eac3b7b7a46" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core", @@ -2709,34 +2579,16 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac849a9d4f6097cc81405b00428fd73b04ce5290d806ce7f5c8afd42fbfb9bd" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", ] -[[package]] -name = "ibc-client-cw" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14bf49f8f43c3fea593d7c2413e061f8df607de45e6f7d76de5346a456f6addd" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "derive_more", - "ibc-client-wasm-types", - "ibc-core", - "prost", - "serde", -] - [[package]] name = "ibc-client-tendermint" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804dcd81f62608c453e72f669b2df986eb49d4b4381deac2a70bd33ee94cef7f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -2746,27 +2598,14 @@ dependencies = [ "ibc-core-host", "ibc-primitives", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-light-client-verifier", ] -[[package]] -name = "ibc-client-tendermint-cw" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d6d96b221fb6b68dc89c49150f83110928aeac146f90a434dfa5e354fbf8ca7" -dependencies = [ - "cosmwasm-std", - "ibc-client-cw", - "ibc-client-tendermint", - "ibc-core", -] - [[package]] name = "ibc-client-tendermint-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b41444137be02cabc484079443f447d23e746fabd9ac6fd5d99faac0b30a5f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -2775,19 +2614,17 @@ dependencies = [ "ibc-primitives", "ibc-proto", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-light-client-verifier", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", ] [[package]] name = "ibc-client-wasm-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc05b707ee957b1272877606379647ae1e5897316a3406b6a93e1885ee99e68" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "base64 0.21.7", - "cosmwasm-schema", + "base64 0.22.1", "displaydoc", "ibc-core-client", "ibc-core-host-types", @@ -2799,8 +2636,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675754a0a5f2f70f71445338fa4d8b49d3c84ce1cf4748ca6c98bf6ede9c4bfc" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -2809,8 +2645,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cb69c4ee05d367fa321acf67ec00d3e9f8ecfef013accdb05889db32ff2de3f" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2826,8 +2661,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5dcc1c14a92f01e556d72d834f842bb655043a7e122ebb8aabdb5e9df600aa8" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -2842,10 +2676,9 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2744ad32ae7360caefb80f495800f883f5e5687cfbd74ff82a444b59a47af7" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-client-types", @@ -2860,14 +2693,13 @@ dependencies = [ "serde", "sha2 0.10.8", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-client" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80071ac73dd4f3436bf1aef03c9b1715a4db0914f738904c281449dc05a0a9cf" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -2880,8 +2712,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9f751b62cad4195be5347646151020fd27c2924f10d82d6301a675fac544dd" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -2891,16 +2722,15 @@ dependencies = [ "ibc-core-host-types", "ibc-primitives", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-client-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "423e9e9a70b78fabc94c51dae76800459e126f891ae0987e88ac5e12c36e24de" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-commitment-types", @@ -2912,16 +2742,15 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-commitment-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b323c91e58ea7b573e01b8e76d13f146c97c245ada0aab3070576d54288f30" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-primitives", @@ -2937,23 +2766,23 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31271364789ccfc12c25afa21b47274d7e07bf49b1f728fd66cfa6c29daaf4a" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ + "ibc-client-wasm-types", "ibc-core-client", "ibc-core-connection-types", "ibc-core-handler-types", "ibc-core-host", "ibc-primitives", + "prost", ] [[package]] name = "ibc-core-connection-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d302a36925469589a911dab66654f390b87e98608d07515e47f5c7e51dffe7" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-client-types", @@ -2966,14 +2795,13 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-handler" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4523b9f77d3a1a391a3d63737760be44b23bc9b09ed297883a34654383b9b0e2" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2988,10 +2816,9 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b229a92aa8b06ab9ccde6e1b3dad597deb97cb40e3bb6a631799b4cd2ad124" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-channel-types", @@ -3007,14 +2834,13 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-host" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ed7421f285225b78f3d020df6126b61f94b9eb370a83e42fbd4e9c8b04162fa" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -3032,8 +2858,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b25b5b45cf47b1e73211a83adf3a753f1acdba887cd3bc5357d6f547d4a3e8c" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -3050,16 +2875,15 @@ dependencies = [ "serde", "sha2 0.10.8", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-core-host-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939178939d33e5af1aca19608b019233d753f3734b828d66f40152b382f3db53" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-primitives", @@ -3072,8 +2896,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328e6db6d3aa7126278c46c3dff779aa961952a63d031d3ddf4c202f4a3faad4" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "derive_more", "displaydoc", @@ -3087,10 +2910,9 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4175b57087b28759364572683b335ec4fe63a6f938f1a5d0c383a6297a032155" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-core-host-types", @@ -3101,14 +2923,13 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", ] [[package]] name = "ibc-derive" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d961d2194fd5229961835d2eb78091906ef8afbaaa55bce7ad41bf3ead8aa9" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "proc-macro2", "quote", @@ -3118,10 +2939,9 @@ dependencies = [ [[package]] name = "ibc-primitives" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3340c4908f1a1a36863270ac976e0295fbd1911cbc4609ab406967fd8ccc04" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ - "borsh 0.10.3", + "borsh", "derive_more", "displaydoc", "ibc-proto", @@ -3130,18 +2950,18 @@ dependencies = [ "scale-info", "schemars", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "time", ] [[package]] name = "ibc-proto" -version = "0.44.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66080040d5a4800d52966d55b055400f86b79c34b854b935bef03c87aacda62a" +checksum = "6cb09e0b52b8a16e98ce98845e7c15b018440f3c56defa12fa44782cd66bab65" dependencies = [ "base64 0.22.1", - "borsh 0.10.3", + "borsh", "bytes", "flex-error", "ics23", @@ -3152,15 +2972,14 @@ dependencies = [ "schemars", "serde", "subtle-encoding", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", "tonic", ] [[package]] name = "ibc-query" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a0a3c4ea045cb0971253508c9b074d2b80271f8e57d3716b67bc0b6c8365c6c" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "displaydoc", "ibc", @@ -3171,22 +2990,18 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28f040bb9654b2e618dc75a43d101f69678eeb665fdbef5e5755750ab72625a" +source = "git+https://github.com/cosmos/ibc-rs?rev=7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b#7ff41b3804cda649e0d7f7c21389b8d65f8d9b4b" dependencies = [ "basecoin-store", "derive_more", "displaydoc", "ibc", - "ibc-client-cw", - "ibc-client-tendermint-cw", "ibc-proto", "ibc-query", "parking_lot", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-testgen", - "tracing", "typed-builder", ] @@ -3292,7 +3107,7 @@ name = "index-set" version = "0.8.0" source = "git+https://github.com/heliaxdev/index-set?tag=v0.8.1#b0d928f83cf0d465ccda299d131e8df2859b5184" dependencies = [ - "borsh 1.2.1", + "borsh", "serde", ] @@ -3312,7 +3127,7 @@ name = "indexmap" version = "2.2.4" source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" dependencies = [ - "borsh 1.2.1", + "borsh", "equivalent", "hashbrown 0.14.3", "serde", @@ -3570,7 +3385,7 @@ name = "masp_note_encryption" version = "1.0.0" source = "git+https://github.com/anoma/masp?rev=8d83b172698098fba393006016072bc201ed9ab7#8d83b172698098fba393006016072bc201ed9ab7" dependencies = [ - "borsh 1.2.1", + "borsh", "chacha20", "chacha20poly1305", "cipher", @@ -3589,7 +3404,7 @@ dependencies = [ "blake2b_simd", "blake2s_simd", "bls12_381", - "borsh 1.2.1", + "borsh", "byteorder", "ff", "fpe", @@ -3747,7 +3562,7 @@ name = "namada" version = "0.40.0" dependencies = [ "async-trait", - "borsh 1.2.1", + "borsh", "borsh-ext", "clru", "either", @@ -3801,7 +3616,7 @@ dependencies = [ name = "namada_account" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_core", "namada_macros", "namada_storage", @@ -3823,7 +3638,7 @@ name = "namada_core" version = "0.40.0" dependencies = [ "bech32 0.8.1", - "borsh 1.2.1", + "borsh", "borsh-ext", "chrono", "data-encoding", @@ -3855,8 +3670,8 @@ dependencies = [ "sha2 0.9.9", "smooth-operator", "sparse-merkle-tree", - "tendermint 0.36.0", - "tendermint-proto 0.36.0", + "tendermint 0.37.0", + "tendermint-proto 0.37.0", "thiserror", "tiny-keccak", "tracing", @@ -3868,7 +3683,7 @@ dependencies = [ name = "namada_ethereum_bridge" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "ethers", "eyre", "itertools 0.12.1", @@ -3893,7 +3708,7 @@ dependencies = [ name = "namada_events" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_core", "namada_macros", "serde", @@ -3906,7 +3721,7 @@ dependencies = [ name = "namada_gas" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_core", "namada_events", "namada_macros", @@ -3918,7 +3733,7 @@ dependencies = [ name = "namada_governance" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "itertools 0.12.1", "konst", "namada_core", @@ -3939,7 +3754,7 @@ dependencies = [ name = "namada_ibc" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "data-encoding", "ibc", "ibc-derive", @@ -3981,7 +3796,7 @@ dependencies = [ name = "namada_merkle_tree" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "eyre", "ics23", "namada_core", @@ -4006,7 +3821,7 @@ dependencies = [ name = "namada_proof_of_stake" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "konst", "namada_account", "namada_controller", @@ -4038,7 +3853,7 @@ version = "0.40.0" dependencies = [ "async-trait", "bimap", - "borsh 1.2.1", + "borsh", "borsh-ext", "circular-queue", "clap", @@ -4050,6 +3865,7 @@ dependencies = [ "ethers", "eyre", "fd-lock", + "flume", "futures", "itertools 0.12.1", "jubjub", @@ -4082,6 +3898,7 @@ dependencies = [ "rand 0.8.5", "rand_core 0.6.4", "regex", + "reqwest", "serde", "serde_json", "sha2 0.9.9", @@ -4102,7 +3919,7 @@ dependencies = [ name = "namada_shielded_token" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "lazy_static", "masp_primitives", "masp_proofs", @@ -4123,7 +3940,8 @@ dependencies = [ name = "namada_state" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", + "clru", "itertools 0.12.1", "namada_core", "namada_events", @@ -4145,7 +3963,7 @@ dependencies = [ name = "namada_storage" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "itertools 0.12.1", "namada_core", "namada_macros", @@ -4162,7 +3980,7 @@ dependencies = [ name = "namada_test_utils" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_core", "strum 0.24.1", ] @@ -4198,7 +4016,7 @@ dependencies = [ name = "namada_token" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_core", "namada_events", "namada_macros", @@ -4225,7 +4043,7 @@ version = "0.40.0" dependencies = [ "ark-bls12-381", "bitflags 2.5.0", - "borsh 1.2.1", + "borsh", "data-encoding", "either", "konst", @@ -4260,7 +4078,7 @@ dependencies = [ name = "namada_tx_prelude" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "masp_primitives", "namada_account", "namada_core", @@ -4281,7 +4099,7 @@ dependencies = [ name = "namada_vm_env" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "masp_primitives", "namada_core", ] @@ -4290,7 +4108,7 @@ dependencies = [ name = "namada_vote_ext" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_core", "namada_macros", "namada_tx", @@ -4315,7 +4133,7 @@ dependencies = [ name = "namada_vp_prelude" version = "0.40.0" dependencies = [ - "borsh 1.2.1", + "borsh", "namada_account", "namada_core", "namada_events", @@ -4332,6 +4150,32 @@ dependencies = [ "sha2 0.9.9", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nonempty" version = "0.7.0" @@ -4484,7 +4328,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 2.0.65", @@ -4536,6 +4380,50 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "orion" version = "0.16.1" @@ -4565,9 +4453,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec", @@ -4579,11 +4467,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -4597,9 +4485,9 @@ checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -4801,6 +4689,12 @@ dependencies = [ "spki", ] +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "poly1305" version = "0.8.0" @@ -4850,31 +4744,30 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "0.1.5" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ - "toml 0.5.11", + "once_cell", + "toml_edit 0.19.15", ] [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "toml_edit 0.20.2", ] [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.21.1", ] [[package]] @@ -5270,10 +5163,12 @@ dependencies = [ "http 0.2.11", "http-body", "hyper", + "hyper-tls", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -5282,6 +5177,7 @@ dependencies = [ "serde_urlencoded", "system-configuration", "tokio", + "tokio-native-tls", "tower-service", "url", "wasm-bindgen", @@ -5526,9 +5422,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "cfg-if", "derive_more", @@ -5538,21 +5434,30 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "schemars_derive", @@ -5563,14 +5468,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.65", ] [[package]] @@ -5622,6 +5527,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "self_cell" version = "1.0.4" @@ -5676,15 +5604,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-json-wasm" -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" @@ -5737,13 +5656,13 @@ dependencies = [ [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.65", ] [[package]] @@ -5981,7 +5900,7 @@ name = "sparse-merkle-tree" version = "0.3.1-pre" source = "git+https://github.com/heliaxdev/sparse-merkle-tree?rev=bab8cb96872db22cc9a139b2d3dfc4e00521d097#bab8cb96872db22cc9a139b2d3dfc4e00521d097" dependencies = [ - "borsh 1.2.1", + "borsh", "cfg-if", "ics23", "itertools 0.12.1", @@ -5999,6 +5918,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -6232,9 +6154,9 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b50aae6ec24c3429149ad59b5b8d3374d7804d4c7d6125ceb97cb53907fb68d" +checksum = "954496fbc9716eb4446cdd6d00c071a3e2f22578d62aa03b40c7e5b4fda3ed42" dependencies = [ "bytes", "digest 0.10.7", @@ -6256,35 +6178,35 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", "time", "zeroize", ] [[package]] name = "tendermint-config" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e07b383dc8780ebbec04cfb603f3fdaba6ea6663d8dd861425b1ffa7761fe90d" +checksum = "f84b11b57d20ee4492a1452faff85f5c520adc36ca9fe5e701066935255bb89f" dependencies = [ "flex-error", "serde", "serde_json", - "tendermint 0.36.0", + "tendermint 0.37.0", "toml 0.8.2", "url", ] [[package]] name = "tendermint-light-client-verifier" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4216e487165e5dbd7af79952eaa0d5f06c5bde861eb76c690acd7f2d2a19395c" +checksum = "3848090df4502a09ee27cb1a00f1835e1111c8993b22c5e1e41ffb7f6f09d57e" dependencies = [ "derive_more", "flex-error", "serde", - "tendermint 0.36.0", + "tendermint 0.37.0", "time", ] @@ -6308,9 +6230,9 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f193d04afde6592c20fd70788a10b8cb3823091c07456db70d8a93f5fb99c1" +checksum = "dc87024548c7f3da479885201e3da20ef29e85a3b13d04606b380ac4c7120d87" dependencies = [ "bytes", "flex-error", @@ -6324,9 +6246,9 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e3c231a3632cab53f92ad4161c730c468c08cfe4f0aa5a6735b53b390aecbd" +checksum = "dfdc2281e271277fda184d96d874a6fe59f569b130b634289257baacfc95aa85" dependencies = [ "async-trait", "bytes", @@ -6341,9 +6263,9 @@ dependencies = [ "serde_json", "subtle", "subtle-encoding", - "tendermint 0.36.0", + "tendermint 0.37.0", "tendermint-config", - "tendermint-proto 0.36.0", + "tendermint-proto 0.37.0", "thiserror", "time", "url", @@ -6353,9 +6275,9 @@ dependencies = [ [[package]] name = "tendermint-testgen" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b233cec83c56c413ccc346af866cb9206a14d468fcecf0255080107bc9b103c0" +checksum = "318a0e38b3b7b36b4078d78446d4284088aa9b173d519fc804c3ee4683972934" dependencies = [ "ed25519-consensus", "gumdrop", @@ -6363,7 +6285,7 @@ dependencies = [ "serde_json", "simple-error", "tempfile", - "tendermint 0.36.0", + "tendermint 0.37.0", "time", ] @@ -6541,6 +6463,16 @@ dependencies = [ "syn 2.0.65", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" @@ -6601,9 +6533,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -6634,6 +6566,17 @@ dependencies = [ "winnow 0.5.25", ] +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.25", +] + [[package]] name = "tonic" version = "0.11.0" @@ -6926,18 +6869,18 @@ dependencies = [ [[package]] name = "typed-builder" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47c0496149861b7c95198088cbf36645016b1a0734cf350c50e2a38e070f38a" +checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982ee4197351b5c9782847ef5ec1fdcaf50503fb19d68f9771adae314e72b492" +checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" dependencies = [ "proc-macro2", "quote", @@ -7084,6 +7027,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4"