diff --git a/.changelog/unreleased/features/3705-support-namada.md b/.changelog/unreleased/features/3705-support-namada.md new file mode 100644 index 0000000000..9e7e7a7eb6 --- /dev/null +++ b/.changelog/unreleased/features/3705-support-namada.md @@ -0,0 +1,2 @@ +- Add support for relaying between Namada and CosmosSDK-based chains. + ([\#3705](https://github.com/informalsystems/hermes/issues/3705)) \ No newline at end of file diff --git a/.github/codespell/words.txt b/.github/codespell/words.txt index d15ff15549..eed2287f50 100644 --- a/.github/codespell/words.txt +++ b/.github/codespell/words.txt @@ -2,3 +2,6 @@ crate shs ser numer +nam +inout +wast diff --git a/.github/workflows/cargo-doc.yaml b/.github/workflows/cargo-doc.yaml index 9682a8456f..564d51c810 100644 --- a/.github/workflows/cargo-doc.yaml +++ b/.github/workflows/cargo-doc.yaml @@ -28,7 +28,12 @@ jobs: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 with: - toolchain: nightly-2024-04-21 + toolchain: nightly-2024-10-15 + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Build API documentation uses: actions-rs/cargo@v1 env: diff --git a/.github/workflows/guide-templates.yaml b/.github/workflows/guide-templates.yaml index 9eefc0d3fc..76152d6513 100644 --- a/.github/workflows/guide-templates.yaml +++ b/.github/workflows/guide-templates.yaml @@ -31,13 +31,13 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Check templates run: bash scripts/auto_gen_templates.sh --mode "check" - - uses: actions-rs/cargo@v1 - name: Update lockfile - with: - command: generate-lockfile - args: --manifest-path tools/check-guide/Cargo.toml - uses: actions-rs/cargo@v1 name: Check guide with: diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index fb98841907..137a63cafb 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -118,6 +118,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/cargo@v1 with: command: test @@ -156,6 +161,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/cargo@v1 with: command: test @@ -199,6 +209,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/cargo@v1 with: command: test @@ -242,6 +257,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/cargo@v1 with: command: test @@ -284,6 +304,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/cargo@v1 with: command: test @@ -328,6 +353,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/cargo@v1 with: command: test diff --git a/.github/workflows/misbehaviour.yml b/.github/workflows/misbehaviour.yml index 135ef7c9a1..37e5b75986 100644 --- a/.github/workflows/misbehaviour.yml +++ b/.github/workflows/misbehaviour.yml @@ -80,6 +80,11 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Build Hermes uses: actions-rs/cargo@v1 with: @@ -132,6 +137,11 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Build Hermes uses: actions-rs/cargo@v1 with: @@ -184,6 +194,11 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Build Hermes uses: actions-rs/cargo@v1 with: @@ -236,6 +251,11 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Build Hermes uses: actions-rs/cargo@v1 with: diff --git a/.github/workflows/multi-chains.yaml b/.github/workflows/multi-chains.yaml index 9aeb907848..2e902ce8a0 100644 --- a/.github/workflows/multi-chains.yaml +++ b/.github/workflows/multi-chains.yaml @@ -99,6 +99,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/cargo@v1 with: command: test diff --git a/.github/workflows/namada.yaml b/.github/workflows/namada.yaml new file mode 100644 index 0000000000..ded8f201b4 --- /dev/null +++ b/.github/workflows/namada.yaml @@ -0,0 +1,199 @@ +name: Namada Integration + +on: + workflow_dispatch: + pull_request: + paths: + - .github/workflows/namada.yaml + - Cargo.toml + - Cargo.lock + - flake.nix + - flake.lock + - ci/** + - e2e/** + - crates/** + - tools/** + +env: + CARGO_INCREMENTAL: 0 + CARGO_PROFILE_DEV_DEBUG: 1 + CARGO_PROFILE_RELEASE_DEBUG: 1 + RUST_BACKTRACE: short + CARGO_NET_RETRY: 10 + RUSTUP_MAX_RETRIES: 10 + +# Cancel previous runs of this workflow when a new commit is added to the PR, branch or tag +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + cosmos-namada: + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + chain: + - package: .#gaia20 + command: gaiad,namada + account_prefix: cosmos,'' + native_token: stake,nam + - package: .#osmosis + command: osmosisd,namada + account_prefix: osmo,'' + native_token: stake,nam + steps: + - uses: actions/checkout@v4 + - name: Clone Namada + uses: actions/checkout@v4 + with: + repository: anoma/namada + ref: v0.46.1 + path: namada + - name: Retrieve Namada repository path + id: namada-repo-path + run: | + echo "NAMADA_REPO_PATH=$(pwd)/namada" >> "$GITHUB_ENV" + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + with: + extra-conf: | + substituters = https://cache.nixos.org + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= + - name: Install Cachix + uses: cachix/cachix-action@v14 + with: + name: cosmos-nix + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + - name: Install libudev + run: sudo apt-get update && sudo apt-get -y install libudev-dev + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions-rs/cargo@v1 + with: + command: test + args: -p ibc-integration-test --features namada --no-fail-fast --no-run + - name: Install cargo-nextest + run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin + - name: Download CometBFT + run: | + curl -o cometbft.tar.gz -LO https://github.com/cometbft/cometbft/releases/download/v0.37.11/cometbft_0.37.11_linux_amd64.tar.gz + tar -xvzf cometbft.tar.gz + chmod +x cometbft + mkdir -p $HOME/local/bin + mv cometbft ~/local/bin + - name: Download Namada binaries + env: + OPERATING_SYSTEM: Linux + run: | + release_url=$(curl -s "https://api.github.com/repos/anoma/namada/releases/188247367" | grep "browser_download_url" | cut -d '"' -f 4 | grep "$OPERATING_SYSTEM") + wget "$release_url" + tar -xzvf namada*.tar.gz + cp ./namada*/namadac ~/local/bin/namadac + cp ./namada*/namadan ~/local/bin/namadan + cp ./namada*/namadaw ~/local/bin/namadaw + cp ./namada*/namada ~/local/bin/namada + cp ./namada*/wasm/checksums.json $NAMADA_REPO_PATH/wasm + cp ./namada*/wasm/*.wasm $NAMADA_REPO_PATH/wasm + - name: Update environment path + run: | + echo "${HOME}/local/bin" >> $GITHUB_PATH + - name: Download MASP parameters + run: | + echo $HOME + mkdir -p $HOME/.masp-params + curl -o $HOME/.masp-params/masp-spend.params -L https://github.com/anoma/masp-mpc/releases/download/namada-trusted-setup/masp-spend.params\?raw\=true + curl -o $HOME/.masp-params/masp-output.params -L https://github.com/anoma/masp-mpc/releases/download/namada-trusted-setup/masp-output.params?raw=true + curl -o $HOME/.masp-params/masp-convert.params -L https://github.com/anoma/masp-mpc/releases/download/namada-trusted-setup/masp-convert.params?raw=true + - env: + RUST_LOG: info + RUST_BACKTRACE: 1 + NO_COLOR_LOG: 1 + NEXTEST_RETRIES: 2 + CHAIN_COMMAND_PATHS: ${{ matrix.chain.command }} + ACCOUNT_PREFIXES: ${{ matrix.chain.account_prefix }} + NATIVE_TOKENS: ${{ matrix.chain.native_token }} + run: | + nix shell ${{ matrix.chain.package }} -c \ + cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=1 \ + --features namada + + namada: + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v4 + - name: Clone Namada + uses: actions/checkout@v4 + with: + repository: anoma/namada + ref: v0.46.1 + path: namada + - name: Retrieve Namada repository path + id: namada-repo-path + run: | + echo "NAMADA_REPO_PATH=$(pwd)/namada" >> "$GITHUB_ENV" + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + - name: Install libudev + run: sudo apt-get update && sudo apt-get -y install libudev-dev + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions-rs/cargo@v1 + with: + command: test + args: -p ibc-integration-test --features namada --no-fail-fast --no-run + - name: Install cargo-nextest + run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin + - name: Download CometBFT + run: | + curl -o cometbft.tar.gz -LO https://github.com/cometbft/cometbft/releases/download/v0.37.11/cometbft_0.37.11_linux_amd64.tar.gz + tar -xvzf cometbft.tar.gz + mkdir -p ~/local/bin + chmod +x cometbft + mv cometbft ~/local/bin + - name: Download Namada binaries + env: + OPERATING_SYSTEM: Linux + run: | + release_url=$(curl -s "https://api.github.com/repos/anoma/namada/releases/188247367" | grep "browser_download_url" | cut -d '"' -f 4 | grep "$OPERATING_SYSTEM") + wget "$release_url" + tar -xzvf namada*.tar.gz + cp ./namada*/namadac ~/local/bin/namadac + cp ./namada*/namadan ~/local/bin/namadan + cp ./namada*/namadaw ~/local/bin/namadaw + cp ./namada*/namada ~/local/bin/namada + cp ./namada*/wasm/checksums.json $NAMADA_REPO_PATH/wasm + cp ./namada*/wasm/*.wasm $NAMADA_REPO_PATH/wasm + - name: Update environment path + run: | + echo "${HOME}/local/bin" >> $GITHUB_PATH + - name: Download MASP parameters + run: | + echo $HOME + mkdir -p $HOME/.masp-params + curl -o $HOME/.masp-params/masp-spend.params -L https://github.com/anoma/masp-mpc/releases/download/namada-trusted-setup/masp-spend.params\?raw\=true + curl -o $HOME/.masp-params/masp-output.params -L https://github.com/anoma/masp-mpc/releases/download/namada-trusted-setup/masp-output.params?raw=true + curl -o $HOME/.masp-params/masp-convert.params -L https://github.com/anoma/masp-mpc/releases/download/namada-trusted-setup/masp-convert.params?raw=true + - env: + RUST_LOG: info + RUST_BACKTRACE: 1 + NO_COLOR_LOG: 1 + NEXTEST_RETRIES: 2 + CHAIN_COMMAND_PATHS: namada + ACCOUNT_PREFIXES: '' + NATIVE_TOKENS: nam + run: | + cargo nextest run -p ibc-integration-test --no-fail-fast --failure-output final --test-threads=1 \ + --features namada + diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 42106466c5..34e99fd9f6 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,6 +14,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: katyo/publish-crates@v2 with: registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b1f7b3a39c..20dd2d8ab2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,6 +31,11 @@ jobs: runs-on: ${{ matrix.config.os }} steps: - uses: actions/checkout@v4 + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: taiki-e/upload-rust-binary-action@v1 with: # (required) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bc19b03142..12271bbfe6 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -54,6 +54,11 @@ jobs: with: toolchain: stable components: clippy + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/clippy-check@v1 with: name: clippy-all-features @@ -68,6 +73,11 @@ jobs: with: toolchain: stable components: clippy + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions-rs/clippy-check@v1 with: name: clippy-no-default-features @@ -82,6 +92,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Install cargo-nextest run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin - uses: actions-rs/cargo@v1 @@ -100,12 +115,17 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable + - name: Install Protoc + uses: heliaxdev/setup-protoc@v2 + with: + version: "25.0" + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Install cargo-binstall uses: taiki-e/install-action@cargo-binstall - name: Install cargo-msrv - run: cargo binstall --no-confirm --force cargo-msrv@0.16.0-beta.20 + run: cargo binstall --no-confirm --force cargo-msrv@0.17.1 - name: Check MSRV - run: cargo msrv verify --output-format minimal --manifest-path crates/relayer-cli/Cargo.toml -- 'cargo check --all-features' + run: cargo msrv verify --output-format json --manifest-path crates/relayer-cli/Cargo.toml # test-coverage: # runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index dcde31350b..9ac5d6f0c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,16 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + [[package]] name = "abscissa_core" version = "0.6.0" @@ -12,13 +22,13 @@ dependencies = [ "arc-swap", "backtrace", "canonical-path", - "clap", + "clap 3.2.25", "color-eyre", "fs-err", "once_cell", "regex", "secrecy", - "semver", + "semver 1.0.23", "serde", "termcolor", "toml 0.5.11", @@ -56,6 +66,33 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -141,6 +178,91 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +[[package]] +name = "ark-bls12-381" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65be532f9dd1e98ad0150b037276cde464c6f371059e6dd02c0222395761f6aa" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea978406c4b1ca13c2db2373b05cc55429c3575b8b21f1b9ee859aa5b03dd42" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "num-bigint", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std", + "digest 0.9.0", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.8.5", +] + [[package]] name = "arrayref" version = "0.3.9" @@ -153,6 +275,15 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -172,7 +303,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -183,7 +314,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -200,7 +331,18 @@ dependencies = [ "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", - "tungstenite", + "tungstenite 0.21.0", +] + +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures", + "pharos", + "rustc_version 0.4.1", ] [[package]] @@ -220,6 +362,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -332,7 +485,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -343,6 +496,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -361,6 +526,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b" + [[package]] name = "bech32" version = "0.9.1" @@ -373,6 +544,60 @@ version = "0.10.0-beta" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea" +[[package]] +name = "bellman" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afceed28bac7f9f5a508bca8aeeff51cdfa4770c0b967ac55c621e2ddfd6171" +dependencies = [ + "bitvec", + "blake2s_simd", + "byteorder", + "ff", + "group", + "pairing", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "bimap" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" +dependencies = [ + "serde", +] + +[[package]] +name = "bip0039" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "568b6890865156d9043af490d4c4081c385dd68ea10acd6ca15733d511e6b51c" +dependencies = [ + "hmac 0.12.1", + "pbkdf2 0.12.2", + "rand 0.8.5", + "sha2 0.10.8", + "unicode-normalization", + "zeroize", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitcoin" version = "0.31.2" @@ -419,6 +644,21 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] [[package]] name = "blake2" @@ -429,6 +669,28 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq 0.3.1", +] + +[[package]] +name = "blake2s_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94230421e395b9920d23df13ea5d77a20e1725331f90fbbf6df6040b33f756ae" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq 0.3.1", +] + [[package]] name = "blake3" version = "1.5.4" @@ -439,7 +701,7 @@ dependencies = [ "arrayvec", "cc", "cfg-if", - "constant_time_eq", + "constant_time_eq 0.3.1", ] [[package]] @@ -460,12 +722,67 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bls12_381" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "bls12_381" +version = "0.8.0" +source = "git+https://github.com/heliaxdev/bls12_381.git?rev=d3ebe9dd6488fac1923db120a7498079e55dd838#d3ebe9dd6488fac1923db120a7498079e55dd838" +dependencies = [ + "ff", + "group", + "pairing", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "borsh" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "borsh-ext" +version = "1.2.0" +source = "git+https://github.com/heliaxdev/borsh-ext?tag=v1.2.0#a62fee3e847e512cad9ac0f1fd5a900e5db9ba37" +dependencies = [ + "borsh", +] + [[package]] name = "bs58" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ + "sha2 0.10.8", "tinyvec", ] @@ -475,6 +792,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + [[package]] name = "byte-unit" version = "4.0.19" @@ -500,18 +823,82 @@ dependencies = [ "serde", ] +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + [[package]] name = "canonical-path" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e9e01327e6c86e92ec72b1c798d4a94810f147209bbe3ffab6a86954937a6f" +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.23", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -522,19 +909,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "chrono" -version = "0.4.38" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", - "num-traits", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen", "windows-targets 0.52.6", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "circular-queue" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d34327ead1c743a10db339de35fb58957564b99d248a67985c55638b22c59b5" +dependencies = [ + "version_check", +] + [[package]] name = "clap" version = "3.2.25" @@ -544,7 +981,7 @@ dependencies = [ "atty", "bitflags 1.3.2", "clap_derive", - "clap_lex", + "clap_lex 0.2.4", "indexmap 1.9.3", "once_cell", "strsim", @@ -552,13 +989,32 @@ dependencies = [ "textwrap", ] +[[package]] +name = "clap" +version = "4.5.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +dependencies = [ + "anstyle", + "clap_lex 0.7.3", +] + [[package]] name = "clap_complete" version = "3.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f7a2e0a962c45ce25afce14220bc24f9dade0a1787f185cecf96bfba7847cd8" dependencies = [ - "clap", + "clap 3.2.25", ] [[package]] @@ -567,7 +1023,7 @@ version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", @@ -583,6 +1039,69 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" + +[[package]] +name = "clru" +version = "0.5.0" +source = "git+https://github.com/marmeladema/clru-rs.git?rev=71ca566#71ca566915f21f3c308091ca7756a91b0f8b5afc" + +[[package]] +name = "coins-bip32" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" +dependencies = [ + "bs58", + "coins-core", + "digest 0.10.7", + "hmac 0.12.1", + "k256", + "serde", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "coins-bip39" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" +dependencies = [ + "bitvec", + "coins-bip32", + "hmac 0.12.1", + "once_cell", + "pbkdf2 0.12.2", + "rand 0.8.5", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "coins-core" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" +dependencies = [ + "base64 0.21.7", + "bech32 0.9.1", + "bs58", + "digest 0.10.7", + "generic-array", + "hex", + "ripemd", + "serde", + "serde_derive", + "sha2 0.10.8", + "sha3", + "thiserror", +] + [[package]] name = "color-eyre" version = "0.6.3" @@ -629,12 +1148,37 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "const-hex" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487981fa1af147182687064d0a2c336586d337a606595ced9ffb0c685c250c73" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_panic" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "013b6c2c3a14d678f38cd23994b02da3a1a1b6a5d1eedddfe63a5a5f11b13a81" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "constant_time_eq" version = "0.3.1" @@ -675,9 +1219,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "462e1f6a8e005acc8835d32d60cbd7973ed65ea2a8d8473830e675f050956427" dependencies = [ "informalsystems-pbjson", - "prost", + "prost 0.13.3", "serde", - "tendermint-proto", + "tendermint-proto 0.40.0", "tonic", ] @@ -690,6 +1234,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-channel" version = "0.5.13" @@ -699,6 +1252,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + [[package]] name = "crossbeam-epoch" version = "0.9.18" @@ -727,7 +1290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -742,6 +1305,31 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ct-codecs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "026ac6ceace6298d2c557ef5ed798894962296469ec7842288ea64674201a2d1" + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -753,7 +1341,7 @@ dependencies = [ "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "rustc_version", + "rustc_version 0.4.1", "subtle", "zeroize", ] @@ -766,7 +1354,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -777,7 +1365,7 @@ checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" dependencies = [ "byteorder", "digest 0.9.0", - "rand_core", + "rand_core 0.6.4", "subtle-ng", "zeroize", ] @@ -826,6 +1414,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -834,7 +1433,27 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", ] [[package]] @@ -871,6 +1490,24 @@ dependencies = [ "subtle", ] +[[package]] +name = "directories" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +dependencies = [ + "dirs-sys 0.3.7", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys 0.4.1", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -881,6 +1518,29 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -900,9 +1560,35 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "duration-str" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c1a2e028bbf7921549873b291ddc0cfe08b673d9489da81ac28898cd5a0e6e0" +dependencies = [ + "chrono", + "rust_decimal", + "serde", + "thiserror", + "time", + "winnow", ] +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.16.9" @@ -913,6 +1599,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", + "serdect", "signature", "spki", ] @@ -936,8 +1623,10 @@ checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" dependencies = [ "curve25519-dalek-ng", "hex", - "rand_core", + "rand_core 0.6.4", + "serde", "sha2 0.9.9", + "thiserror", "zeroize", ] @@ -949,7 +1638,7 @@ checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", - "rand_core", + "rand_core 0.6.4", "serde", "sha2 0.10.8", "subtle", @@ -964,7 +1653,7 @@ checksum = "6b49a684b133c4980d7ee783936af771516011c8cd15f429dbda77245e282f03" dependencies = [ "derivation-path", "ed25519-dalek", - "hmac", + "hmac 0.12.1", "sha2 0.10.8", ] @@ -987,12 +1676,22 @@ dependencies = [ "generic-array", "group", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", + "serdect", "subtle", "zeroize", ] +[[package]] +name = "ena" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +dependencies = [ + "log", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -1008,6 +1707,24 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enr" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" +dependencies = [ + "base64 0.21.7", + "bytes", + "hex", + "k256", + "log", + "rand 0.8.5", + "rlp", + "serde", + "sha3", + "zeroize", +] + [[package]] name = "env_filter" version = "0.1.2" @@ -1048,28 +1765,390 @@ dependencies = [ ] [[package]] -name = "eyre" -version = "0.6.12" +name = "eth-keystore" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" dependencies = [ - "indenter", - "once_cell", + "aes", + "ctr", + "digest 0.10.7", + "hex", + "hmac 0.12.1", + "pbkdf2 0.11.0", + "rand 0.8.5", + "scrypt", + "serde", + "serde_json", + "sha2 0.10.8", + "sha3", + "thiserror", + "uuid 0.8.2", ] [[package]] -name = "fastrand" -version = "2.2.0" +name = "ethabi" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" - -[[package]] -name = "ff" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethbridge-bridge-contract" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" +dependencies = [ + "ethbridge-bridge-events", + "ethbridge-structs", + "ethers", + "ethers-contract", +] + +[[package]] +name = "ethbridge-bridge-events" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" +dependencies = [ + "ethabi", + "ethbridge-structs", + "ethers", + "ethers-contract", +] + +[[package]] +name = "ethbridge-structs" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" +dependencies = [ + "ethabi", + "ethers", + "ethers-contract", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "ethers" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816841ea989f0c69e459af1cf23a6b0033b19a55424a1ea3a30099becdb8dec0" +dependencies = [ + "ethers-addressbook", + "ethers-contract", + "ethers-core", + "ethers-etherscan", + "ethers-middleware", + "ethers-providers", + "ethers-signers", + "ethers-solc", +] + +[[package]] +name = "ethers-addressbook" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5495afd16b4faa556c3bba1f21b98b4983e53c1755022377051a975c3b021759" +dependencies = [ + "ethers-core", + "once_cell", + "serde", + "serde_json", +] + +[[package]] +name = "ethers-contract" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fceafa3578c836eeb874af87abacfb041f92b4da0a78a5edd042564b8ecdaaa" +dependencies = [ + "const-hex", + "ethers-contract-abigen", + "ethers-contract-derive", + "ethers-core", + "ethers-providers", + "futures-util", + "once_cell", + "pin-project", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "ethers-contract-abigen" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04ba01fbc2331a38c429eb95d4a570166781f14290ef9fdb144278a90b5a739b" +dependencies = [ + "Inflector", + "const-hex", + "dunce", + "ethers-core", + "ethers-etherscan", + "eyre", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "reqwest", + "serde", + "serde_json", + "syn 2.0.89", + "toml 0.8.19", + "walkdir", +] + +[[package]] +name = "ethers-contract-derive" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87689dcabc0051cde10caaade298f9e9093d65f6125c14575db3fd8c669a168f" +dependencies = [ + "Inflector", + "const-hex", + "ethers-contract-abigen", + "ethers-core", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.89", +] + +[[package]] +name = "ethers-core" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" +dependencies = [ + "arrayvec", + "bytes", + "cargo_metadata", + "chrono", + "const-hex", + "elliptic-curve", + "ethabi", + "generic-array", + "k256", + "num_enum", + "once_cell", + "open-fastrlp", + "rand 0.8.5", + "rlp", + "serde", + "serde_json", + "strum 0.26.3", + "syn 2.0.89", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "ethers-etherscan" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79e5973c26d4baf0ce55520bd732314328cabe53193286671b47144145b9649" +dependencies = [ + "chrono", + "ethers-core", + "reqwest", + "semver 1.0.23", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "ethers-middleware" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f9fdf09aec667c099909d91908d5eaf9be1bd0e2500ba4172c1d28bfaa43de" +dependencies = [ + "async-trait", + "auto_impl", + "ethers-contract", + "ethers-core", + "ethers-etherscan", + "ethers-providers", + "ethers-signers", + "futures-channel", + "futures-locks", + "futures-util", + "instant", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "tracing-futures", + "url", +] + +[[package]] +name = "ethers-providers" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6434c9a33891f1effc9c75472e12666db2fa5a0fec4b29af6221680a6fe83ab2" +dependencies = [ + "async-trait", + "auto_impl", + "base64 0.21.7", + "bytes", + "const-hex", + "enr", + "ethers-core", + "futures-core", + "futures-timer", + "futures-util", + "hashers", + "http 0.2.12", + "instant", + "jsonwebtoken", + "once_cell", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-futures", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "ws_stream_wasm", +] + +[[package]] +name = "ethers-signers" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228875491c782ad851773b652dd8ecac62cda8571d3bc32a5853644dd26766c2" +dependencies = [ + "async-trait", + "coins-bip32", + "coins-bip39", + "const-hex", + "elliptic-curve", + "eth-keystore", + "ethers-core", + "rand 0.8.5", + "sha2 0.10.8", + "thiserror", + "tracing", +] + +[[package]] +name = "ethers-solc" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66244a771d9163282646dbeffe0e6eca4dda4146b6498644e678ac6089b11edd" +dependencies = [ + "cfg-if", + "const-hex", + "dirs", + "dunce", + "ethers-core", + "glob", + "home", + "md-5", + "num_cpus", + "once_cell", + "path-slash", + "rayon", + "regex", + "semver 1.0.23", + "serde", + "serde_json", + "solang-parser", + "svm-rs", + "thiserror", + "tiny-keccak", + "tokio", + "tracing", + "walkdir", + "yansi", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fastrand" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" + +[[package]] +name = "fd-lock" +version = "3.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "ff" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core", + "bitvec", + "rand_core 0.6.4", "subtle", ] @@ -1085,9 +2164,28 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", "static_assertions", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] + [[package]] name = "flex-error" version = "0.4.4" @@ -1098,12 +2196,39 @@ dependencies = [ "paste", ] +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +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" @@ -1113,6 +2238,20 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fpe" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c4b37de5ae15812a764c958297cfc50f5c010438f60c6ce75d11b802abd404" +dependencies = [ + "cbc", + "cipher", + "libm", + "num-bigint", + "num-integer", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fs-err" version = "2.11.0" @@ -1122,6 +2261,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.3.31" @@ -1171,14 +2326,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] -name = "futures-macro" -version = "0.3.31" +name = "futures-locks" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" +dependencies = [ + "futures-channel", + "futures-task", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1193,6 +2358,16 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +dependencies = [ + "gloo-timers", + "send_wrapper 0.4.0", +] + [[package]] name = "futures-util" version = "0.3.31" @@ -1211,6 +2386,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1222,6 +2406,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -1231,7 +2428,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -1241,6 +2438,24 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "group" version = "0.13.0" @@ -1248,7 +2463,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "memuse", + "rand_core 0.6.4", "subtle", ] @@ -1334,6 +2550,15 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +[[package]] +name = "hashers" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" +dependencies = [ + "fxhash", +] + [[package]] name = "hdpath" version = "0.6.3" @@ -1349,6 +2574,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1382,6 +2613,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + [[package]] name = "hmac" version = "0.12.1" @@ -1391,6 +2632,21 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "hmac-sha512" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e806677ce663d0a199541030c816847b36e8dc095f70dae4a4f4ad63da5383" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "http" version = "0.2.12" @@ -1547,6 +2803,19 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper 0.14.31", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "hyper-util" version = "0.1.10" @@ -1589,6 +2858,87 @@ dependencies = [ "cc", ] +[[package]] +name = "ibc" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-apps", + "ibc-clients", + "ibc-core", + "ibc-core-host-cosmos", + "ibc-derive", + "ibc-primitives", +] + +[[package]] +name = "ibc-app-nft-transfer" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-app-nft-transfer-types", + "ibc-core", + "serde-json-wasm", +] + +[[package]] +name = "ibc-app-nft-transfer-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "base64 0.22.1", + "borsh", + "derive_more 0.99.18", + "displaydoc", + "http 1.1.0", + "ibc-app-transfer-types", + "ibc-core", + "ibc-proto 0.47.1", + "mime", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", + "serde-json-wasm", +] + +[[package]] +name = "ibc-app-transfer" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-app-transfer-types", + "ibc-core", + "serde-json-wasm", +] + +[[package]] +name = "ibc-app-transfer-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "borsh", + "derive_more 0.99.18", + "displaydoc", + "ibc-core", + "ibc-proto 0.47.1", + "parity-scale-codec", + "primitive-types", + "scale-info", + "schemars", + "serde", + "uint", +] + +[[package]] +name = "ibc-apps" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-app-nft-transfer", + "ibc-app-transfer", +] + [[package]] name = "ibc-chain-registry" version = "0.30.0" @@ -1597,18 +2947,370 @@ dependencies = [ "flex-error", "futures", "http 1.1.0", - "ibc-proto", + "ibc-proto 0.51.1", "ibc-relayer", "ibc-relayer-types", - "itertools", + "itertools 0.13.0", "reqwest", "serde", "serde_json", - "tendermint-rpc", + "tendermint-rpc 0.40.0", "tokio", "tracing", ] +[[package]] +name = "ibc-client-tendermint" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "derive_more 0.99.18", + "ibc-client-tendermint-types", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "serde", + "tendermint 0.38.1", + "tendermint-light-client-verifier 0.38.1", +] + +[[package]] +name = "ibc-client-tendermint-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto 0.47.1", + "serde", + "tendermint 0.38.1", + "tendermint-light-client-verifier 0.38.1", + "tendermint-proto 0.38.1", +] + +[[package]] +name = "ibc-client-wasm-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "base64 0.22.1", + "displaydoc", + "ibc-core-client", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto 0.47.1", + "serde", +] + +[[package]] +name = "ibc-clients" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-client-tendermint", + "ibc-client-wasm-types", +] + +[[package]] +name = "ibc-core" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-core-channel", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler", + "ibc-core-host", + "ibc-core-router", + "ibc-derive", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-channel" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-core-channel-types", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-channel-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "borsh", + "derive_more 0.99.18", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto 0.47.1", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", + "sha2 0.10.8", + "subtle-encoding", + "tendermint 0.38.1", +] + +[[package]] +name = "ibc-core-client" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-client-context" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "derive_more 0.99.18", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-primitives", + "subtle-encoding", + "tendermint 0.38.1", +] + +[[package]] +name = "ibc-core-client-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "borsh", + "derive_more 0.99.18", + "displaydoc", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto 0.47.1", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", + "subtle-encoding", + "tendermint 0.38.1", +] + +[[package]] +name = "ibc-core-commitment-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "borsh", + "derive_more 0.99.18", + "displaydoc", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto 0.47.1", + "ics23", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-connection" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-client-wasm-types", + "ibc-core-client", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.13.3", +] + +[[package]] +name = "ibc-core-connection-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "borsh", + "derive_more 0.99.18", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto 0.47.1", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", + "subtle-encoding", + "tendermint 0.38.1", +] + +[[package]] +name = "ibc-core-handler" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "ibc-core-channel", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-handler-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "borsh", + "derive_more 0.99.18", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-host-types", + "ibc-core-router-types", + "ibc-primitives", + "ibc-proto 0.47.1", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", + "subtle-encoding", + "tendermint 0.38.1", +] + +[[package]] +name = "ibc-core-host" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "derive_more 0.99.18", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-primitives", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-host-cosmos" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "derive_more 0.99.18", + "displaydoc", + "ibc-app-transfer-types", + "ibc-client-tendermint", + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto 0.47.1", + "serde", + "sha2 0.10.8", + "subtle-encoding", + "tendermint 0.38.1", +] + +[[package]] +name = "ibc-core-host-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "borsh", + "derive_more 0.99.18", + "displaydoc", + "ibc-primitives", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", +] + +[[package]] +name = "ibc-core-router" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "derive_more 0.99.18", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-host-types", + "ibc-core-router-types", + "ibc-primitives", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-router-types" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "borsh", + "derive_more 0.99.18", + "displaydoc", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto 0.47.1", + "parity-scale-codec", + "scale-info", + "schemars", + "serde", + "subtle-encoding", + "tendermint 0.38.1", +] + +[[package]] +name = "ibc-derive" +version = "0.8.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "ibc-integration-test" version = "0.30.0" @@ -1618,38 +3320,77 @@ dependencies = [ "ibc-relayer", "ibc-relayer-types", "ibc-test-framework", - "prost", + "prost 0.13.3", "serde", "serde_json", - "tendermint", - "tendermint-rpc", + "tendermint 0.40.0", + "tendermint-rpc 0.40.0", "time", "toml 0.8.19", "tonic", ] +[[package]] +name = "ibc-primitives" +version = "0.54.0" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +dependencies = [ + "borsh", + "derive_more 0.99.18", + "displaydoc", + "ibc-proto 0.47.1", + "parity-scale-codec", + "prost 0.13.3", + "scale-info", + "schemars", + "serde", + "tendermint 0.38.1", + "time", +] + [[package]] name = "ibc-proto" -version = "0.51.1" +version = "0.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b70f517162e74e2d35875b8b94bf4d1e45f2c69ef3de452dc855944455d33ca" +checksum = "c852d22b782d2d793f4a646f968de419be635e02bc8798d5d74a6e44eef27733" dependencies = [ "base64 0.22.1", + "borsh", "bytes", - "cosmos-sdk-proto", "flex-error", "ics23", "informalsystems-pbjson", - "prost", + "parity-scale-codec", + "prost 0.13.3", + "scale-info", + "schemars", "serde", "subtle-encoding", - "tendermint-proto", - "tonic", + "tendermint-proto 0.38.1", ] [[package]] -name = "ibc-relayer" -version = "0.30.0" +name = "ibc-proto" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b70f517162e74e2d35875b8b94bf4d1e45f2c69ef3de452dc855944455d33ca" +dependencies = [ + "base64 0.22.1", + "bytes", + "cosmos-sdk-proto", + "flex-error", + "ics23", + "informalsystems-pbjson", + "prost 0.13.3", + "serde", + "subtle-encoding", + "tendermint-proto 0.40.0", + "tonic", +] + +[[package]] +name = "ibc-relayer" +version = "0.30.0" dependencies = [ "anyhow", "async-stream", @@ -1673,39 +3414,44 @@ dependencies = [ "http 1.1.0", "humantime", "humantime-serde", - "ibc-proto", + "ibc-proto 0.51.1", "ibc-relayer-types", "ibc-telemetry", - "itertools", + "itertools 0.13.0", "moka", + "namada_sdk", "num-bigint", "num-rational", "once_cell", - "prost", + "prost 0.13.3", "regex", "reqwest", "retry", "ripemd", + "rpassword", "secp256k1", - "semver", + "semver 1.0.23", "serde", "serde_derive", "serde_json", "serial_test", "sha2 0.10.8", "signature", - "strum", + "strum 0.25.0", "subtle-encoding", - "tendermint", + "tendermint 0.38.1", + "tendermint 0.40.0", "tendermint-light-client", "tendermint-light-client-detector", - "tendermint-light-client-verifier", - "tendermint-proto", - "tendermint-rpc", + "tendermint-light-client-verifier 0.40.0", + "tendermint-proto 0.38.1", + "tendermint-proto 0.40.0", + "tendermint-rpc 0.38.1", + "tendermint-rpc 0.40.0", "tendermint-testgen", "test-log", "thiserror", - "tiny-bip39", + "tiny-bip39 1.0.0", "tiny-keccak", "tokio", "tokio-stream", @@ -1713,7 +3459,7 @@ dependencies = [ "tonic", "tracing", "tracing-subscriber", - "uuid", + "uuid 1.11.0", ] [[package]] @@ -1721,7 +3467,7 @@ name = "ibc-relayer-cli" version = "1.11.0" dependencies = [ "abscissa_core", - "clap", + "clap 3.2.25", "clap_complete", "color-eyre", "console", @@ -1739,7 +3485,7 @@ dependencies = [ "ibc-relayer-rest", "ibc-relayer-types", "ibc-telemetry", - "itertools", + "itertools 0.13.0", "once_cell", "oneline-eyre", "regex", @@ -1748,9 +3494,9 @@ dependencies = [ "serial_test", "signal-hook", "subtle-encoding", - "tendermint", - "tendermint-light-client-verifier", - "tendermint-rpc", + "tendermint 0.40.0", + "tendermint-light-client-verifier 0.40.0", + "tendermint-rpc 0.40.0", "time", "tokio", "tracing", @@ -1767,6 +3513,7 @@ dependencies = [ "ibc-relayer-types", "reqwest", "serde", + "serde_json", "tokio", "toml 0.8.19", "tracing", @@ -1777,24 +3524,24 @@ name = "ibc-relayer-types" version = "0.30.0" dependencies = [ "bytes", - "derive_more", + "derive_more 0.99.18", "env_logger", "flex-error", - "ibc-proto", + "ibc-proto 0.51.1", "ics23", - "itertools", + "itertools 0.13.0", "num-rational", "primitive-types", - "prost", + "prost 0.13.3", "regex", "serde", "serde_derive", "serde_json", "subtle-encoding", - "tendermint", - "tendermint-light-client-verifier", - "tendermint-proto", - "tendermint-rpc", + "tendermint 0.40.0", + "tendermint-light-client-verifier 0.40.0", + "tendermint-proto 0.40.0", + "tendermint-rpc 0.40.0", "tendermint-testgen", "test-log", "time", @@ -1817,7 +3564,7 @@ dependencies = [ "prometheus", "serde", "serde_json", - "tendermint", + "tendermint 0.40.0", "tokio", "tracing", ] @@ -1834,21 +3581,25 @@ dependencies = [ "hdpath", "hex", "http 1.1.0", - "ibc-proto", + "ibc-proto 0.51.1", "ibc-relayer", "ibc-relayer-cli", "ibc-relayer-types", - "itertools", + "itertools 0.13.0", + "namada_sdk", "once_cell", - "prost", - "rand", - "semver", + "prost 0.13.3", + "rand 0.8.5", + "semver 1.0.23", "serde", "serde_json", "serde_yaml", "sha2 0.10.8", "subtle-encoding", - "tendermint-rpc", + "tendermint 0.38.1", + "tendermint 0.40.0", + "tendermint-rpc 0.38.1", + "tendermint-rpc 0.40.0", "tokio", "toml 0.8.19", "tonic", @@ -1868,7 +3619,7 @@ dependencies = [ "bytes", "hex", "informalsystems-pbjson", - "prost", + "prost 0.13.3", "ripemd", "serde", "sha2 0.10.8", @@ -1990,7 +3741,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2020,6 +3771,35 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-num-traits" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "951641f13f873bff03d4bf19ae8bec531935ac0ac2cc775f84d7edfdcfed3f17" +dependencies = [ + "integer-sqrt", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "uint", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + [[package]] name = "impl-serde" version = "0.4.0" @@ -2029,12 +3809,41 @@ dependencies = [ "serde", ] +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "incrementalmerkletree" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5ad43a3f5795945459d577f6589cf62a476e92c79b75e70cd954364e14ce17b" +dependencies = [ + "serde", +] + [[package]] name = "indenter" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +[[package]] +name = "index-set" +version = "0.8.0" +source = "git+https://github.com/heliaxdev/index-set?tag=v0.8.1#b0d928f83cf0d465ccda299d131e8df2859b5184" +dependencies = [ + "borsh", + "serde", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -2045,6 +3854,17 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.2.4" +source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547bd6ab04bbb16e060326a50ddaeb6c909" +dependencies = [ + "borsh", + "equivalent", + "hashbrown 0.14.5", + "serde", +] + [[package]] name = "indexmap" version = "2.6.0" @@ -2065,6 +3885,42 @@ dependencies = [ "serde", ] +[[package]] +name = "init-once" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0863329819ed5ecf33446da6cb9104d2f8943ff8530d2b6c51adbc6be4f0632" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ipnet" version = "2.10.1" @@ -2077,6 +3933,24 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -2092,6 +3966,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.72" @@ -2101,6 +3984,47 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonwebtoken" +version = "8.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" +dependencies = [ + "base64 0.21.7", + "pem", + "ring 0.16.20", + "serde", + "serde_json", + "simple_asn1", +] + +[[package]] +name = "jubjub" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8499f7a74008aafbecb2a2e608a3e13e4dd3e84df198b604451efe93f2de6e61" +dependencies = [ + "bitvec", + "bls12_381 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff", + "group", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "jubjub" +version = "0.10.0" +source = "git+https://github.com/heliaxdev/jubjub.git?rev=a373686962f4e9d0edb3b4716f86ff6bbd9aa86c#a373686962f4e9d0edb3b4716f86ff6bbd9aa86c" +dependencies = [ + "bitvec", + "bls12_381 0.8.0 (git+https://github.com/heliaxdev/bls12_381.git?rev=d3ebe9dd6488fac1923db120a7498079e55dd838)", + "ff", + "group", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "k256" version = "0.13.4" @@ -2110,7 +4034,20 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", + "once_cell", + "serdect", "sha2 0.10.8", + "signature", +] + +[[package]] +name = "kdam" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "526586ea01a9a132b5f8d3a60f6d6b41b411550236f5ee057795f20b37316957" +dependencies = [ + "terminal_size", + "windows-sys 0.52.0", ] [[package]] @@ -2122,6 +4059,56 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "konst" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0964faf44d2c3e528ade7bd49c3544687cadcdee7641643469d43bd7259a5d88" +dependencies = [ + "const_panic", + "konst_kernel", + "typewit", +] + +[[package]] +name = "konst_kernel" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "722062725c1fc0d83cc017e873aac6a2a5ff16a88edfa190bdeb8bd393fcfd97" +dependencies = [ + "typewit", +] + +[[package]] +name = "lalrpop" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools 0.11.0", + "lalrpop-util", + "petgraph", + "regex", + "regex-syntax 0.8.5", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +dependencies = [ + "regex-automata 0.4.9", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -2134,6 +4121,12 @@ version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + [[package]] name = "libredox" version = "0.1.3" @@ -2172,6 +4165,71 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "masp_note_encryption" +version = "1.0.0" +source = "git+https://github.com/anoma/masp?rev=12ed8b060b295c06502a2ff8468e4a941cb7cca4#12ed8b060b295c06502a2ff8468e4a941cb7cca4" +dependencies = [ + "borsh", + "chacha20", + "chacha20poly1305", + "cipher", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "masp_primitives" +version = "1.0.0" +source = "git+https://github.com/anoma/masp?rev=12ed8b060b295c06502a2ff8468e4a941cb7cca4#12ed8b060b295c06502a2ff8468e4a941cb7cca4" +dependencies = [ + "aes", + "bip0039", + "bitvec", + "blake2b_simd", + "blake2s_simd", + "bls12_381 0.8.0 (git+https://github.com/heliaxdev/bls12_381.git?rev=d3ebe9dd6488fac1923db120a7498079e55dd838)", + "borsh", + "byteorder", + "ff", + "fpe", + "group", + "hex", + "incrementalmerkletree", + "jubjub 0.10.0 (git+https://github.com/heliaxdev/jubjub.git?rev=a373686962f4e9d0edb3b4716f86ff6bbd9aa86c)", + "lazy_static", + "masp_note_encryption", + "memuse", + "nonempty", + "num-traits 0.2.19 (git+https://github.com/heliaxdev/num-traits?rev=3f3657caa34b8e116fdf3f8a3519c4ac29f012fe)", + "rand 0.8.5", + "rand_core 0.6.4", + "sha2 0.10.8", + "subtle", + "zcash_encoding", +] + +[[package]] +name = "masp_proofs" +version = "1.0.0" +source = "git+https://github.com/anoma/masp?rev=12ed8b060b295c06502a2ff8468e4a941cb7cca4#12ed8b060b295c06502a2ff8468e4a941cb7cca4" +dependencies = [ + "bellman", + "blake2b_simd", + "bls12_381 0.8.0 (git+https://github.com/heliaxdev/bls12_381.git?rev=d3ebe9dd6488fac1923db120a7498079e55dd838)", + "directories", + "getrandom 0.2.15", + "group", + "itertools 0.11.0", + "jubjub 0.10.0 (git+https://github.com/heliaxdev/jubjub.git?rev=a373686962f4e9d0edb3b4716f86ff6bbd9aa86c)", + "lazy_static", + "masp_primitives", + "minreq", + "rand_core 0.6.4", + "redjubjub", + "tracing", +] + [[package]] name = "matchers" version = "0.1.0" @@ -2187,6 +4245,16 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + [[package]] name = "memchr" version = "2.7.4" @@ -2194,51 +4262,727 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +name = "memuse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2145869435ace5ea6ea3d35f59be559317ec9a0d04e1812d5f185a87b6d36f1a" + +[[package]] +name = "memzero" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93c0d11ac30a033511ae414355d80f70d9f29a44a49140face477117a1ee90db" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "minreq" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763d142cdff44aaadd9268bebddb156ef6c65a0e13486bb81673cf2d8739f9b0" +dependencies = [ + "log", + "once_cell", + "rustls 0.21.12", + "rustls-webpki 0.101.7", + "webpki-roots", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "moka" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "once_cell", + "parking_lot", + "quanta", + "rustc_version 0.4.1", + "smallvec", + "tagptr", + "thiserror", + "triomphe", + "uuid 1.11.0", +] + +[[package]] +name = "multimap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" + +[[package]] +name = "namada_account" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "namada_core", + "namada_macros", + "namada_storage", + "serde", +] + +[[package]] +name = "namada_controller" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "namada_core", + "smooth-operator", + "thiserror", +] + +[[package]] +name = "namada_core" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "bech32 0.8.1", + "borsh", + "borsh-ext", + "chrono", + "data-encoding", + "ed25519-consensus", + "ethabi", + "ethbridge-structs", + "eyre", + "ibc", + "ics23", + "impl-num-traits", + "index-set", + "indexmap 2.2.4", + "k256", + "lazy_static", + "masp_primitives", + "namada_macros", + "num-integer", + "num-rational", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num256", + "num_enum", + "primitive-types", + "prost-types 0.13.3", + "rand 0.8.5", + "rand_core 0.6.4", + "rayon", + "ripemd", + "serde", + "serde_json", + "sha2 0.9.9", + "smooth-operator", + "sparse-merkle-tree", + "tendermint 0.38.1", + "tendermint-proto 0.38.1", + "thiserror", + "tiny-keccak", + "tokio", + "tracing", + "uint", + "wasmtimer", + "zeroize", +] + +[[package]] +name = "namada_ethereum_bridge" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "ethers", + "eyre", + "itertools 0.12.1", + "konst", + "namada_core", + "namada_events", + "namada_macros", + "namada_parameters", + "namada_proof_of_stake", + "namada_state", + "namada_storage", + "namada_systems", + "namada_trans_token", + "namada_tx", + "namada_vote_ext", + "namada_vp_env", + "serde", + "smooth-operator", + "thiserror", + "tracing", +] + +[[package]] +name = "namada_events" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "namada_core", + "namada_macros", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "namada_gas" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "namada_core", + "namada_events", + "namada_macros", + "serde", + "thiserror", +] + +[[package]] +name = "namada_governance" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "itertools 0.12.1", + "konst", + "namada_account", + "namada_core", + "namada_events", + "namada_macros", + "namada_state", + "namada_systems", + "namada_tx", + "namada_vp_env", + "serde", + "serde_json", + "smooth-operator", + "thiserror", + "tracing", +] + +[[package]] +name = "namada_ibc" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "data-encoding", + "ibc", + "ibc-derive", + "ics23", + "konst", + "masp_primitives", + "namada_core", + "namada_events", + "namada_gas", + "namada_macros", + "namada_state", + "namada_systems", + "namada_tx", + "namada_vp", + "primitive-types", + "prost 0.13.3", + "serde", + "serde_json", + "sha2 0.9.9", + "smooth-operator", + "thiserror", + "tracing", +] + +[[package]] +name = "namada_io" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "async-trait", + "kdam", + "namada_core", + "tendermint-rpc 0.38.1", + "thiserror", + "tokio", +] + +[[package]] +name = "namada_macros" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "data-encoding", + "proc-macro2", + "quote", + "sha2 0.9.9", + "syn 1.0.109", +] + +[[package]] +name = "namada_merkle_tree" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "eyre", + "ics23", + "namada_core", + "namada_macros", + "prost 0.13.3", + "sparse-merkle-tree", + "thiserror", +] + +[[package]] +name = "namada_parameters" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "namada_core", + "namada_macros", + "namada_state", + "namada_systems", + "namada_tx", + "namada_vp_env", + "smooth-operator", + "thiserror", +] + +[[package]] +name = "namada_proof_of_stake" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "itertools 0.12.1", + "konst", + "namada_account", + "namada_controller", + "namada_core", + "namada_events", + "namada_macros", + "namada_state", + "namada_systems", + "namada_tx", + "namada_vp_env", + "once_cell", + "serde", + "smooth-operator", + "thiserror", + "tracing", +] + +[[package]] +name = "namada_replay_protection" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "namada_core", +] + +[[package]] +name = "namada_sdk" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "async-trait", + "bimap", + "borsh", + "borsh-ext", + "circular-queue", + "clap 4.5.21", + "data-encoding", + "duration-str", + "either", + "ethbridge-bridge-contract", + "ethers", + "eyre", + "fd-lock", + "futures", + "init-once", + "itertools 0.12.1", + "lazy_static", + "masp_primitives", + "masp_proofs", + "namada_account", + "namada_core", + "namada_ethereum_bridge", + "namada_events", + "namada_gas", + "namada_governance", + "namada_ibc", + "namada_io", + "namada_macros", + "namada_parameters", + "namada_proof_of_stake", + "namada_state", + "namada_storage", + "namada_token", + "namada_tx", + "namada_vm", + "namada_vote_ext", + "namada_vp", + "namada_wallet", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num256", + "owo-colors", + "paste", + "patricia_tree", + "prost 0.13.3", + "rand 0.8.5", + "rand_core 0.6.4", + "rayon", + "regex", + "reqwest", + "rustversion", + "serde", + "serde_json", + "sha2 0.9.9", + "smooth-operator", + "tempfile", + "tendermint-rpc 0.38.1", + "thiserror", + "tiny-bip39 0.8.2", + "tokio", + "toml 0.5.11", + "tracing", + "xorf", + "zeroize", +] + +[[package]] +name = "namada_shielded_token" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "async-trait", + "borsh", + "eyre", + "flume", + "futures", + "itertools 0.12.1", + "lazy_static", + "masp_primitives", + "masp_proofs", + "namada_account", + "namada_controller", + "namada_core", + "namada_events", + "namada_gas", + "namada_io", + "namada_macros", + "namada_state", + "namada_systems", + "namada_tx", + "namada_vp_env", + "namada_wallet", + "rand 0.8.5", + "rand_core 0.6.4", + "rayon", + "ripemd", + "serde", + "serde_json", + "sha2 0.9.9", + "smooth-operator", + "tempfile", + "thiserror", + "tracing", + "typed-builder", + "xorf", +] + +[[package]] +name = "namada_state" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "clru", + "itertools 0.12.1", + "namada_core", + "namada_events", + "namada_gas", + "namada_macros", + "namada_merkle_tree", + "namada_replay_protection", + "namada_storage", + "namada_systems", + "namada_tx", + "patricia_tree", + "smooth-operator", + "thiserror", + "tracing", +] + +[[package]] +name = "namada_storage" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "itertools 0.12.1", + "namada_core", + "namada_gas", + "namada_macros", + "namada_merkle_tree", + "namada_replay_protection", + "regex", + "serde", + "smooth-operator", + "thiserror", + "tracing", +] + +[[package]] +name = "namada_systems" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "namada_core", + "namada_events", + "namada_storage", +] + +[[package]] +name = "namada_token" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "namada_core", + "namada_events", + "namada_macros", + "namada_shielded_token", + "namada_storage", + "namada_systems", + "namada_trans_token", + "namada_tx", + "namada_tx_env", + "serde", +] + +[[package]] +name = "namada_trans_token" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "konst", + "namada_core", + "namada_events", + "namada_state", + "namada_systems", + "namada_tx", + "namada_tx_env", + "namada_vp_env", + "thiserror", + "tracing", +] + +[[package]] +name = "namada_tx" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "ark-bls12-381", + "bitflags 2.6.0", + "borsh", + "data-encoding", + "either", + "konst", + "masp_primitives", + "namada_account", + "namada_core", + "namada_events", + "namada_gas", + "namada_macros", + "num-derive 0.4.2", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "prost 0.13.3", + "prost-types 0.13.3", + "rand_core 0.6.4", + "serde", + "serde_json", + "sha2 0.9.9", + "thiserror", + "tonic-build", +] + +[[package]] +name = "namada_tx_env" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "namada_core", + "namada_events", + "namada_storage", +] + +[[package]] +name = "namada_vm" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "clru", + "namada_account", + "namada_core", + "namada_events", + "namada_gas", + "namada_parameters", + "namada_state", + "namada_token", + "namada_tx", + "namada_vp", + "smooth-operator", + "thiserror", + "tracing", + "wasmparser", +] + +[[package]] +name = "namada_vote_ext" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "borsh", + "namada_core", + "namada_macros", + "namada_tx", + "serde", +] + +[[package]] +name = "namada_vp" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "namada_core", + "namada_events", + "namada_gas", + "namada_state", + "namada_tx", + "namada_vp_env", + "smooth-operator", + "thiserror", + "tracing", +] + +[[package]] +name = "namada_vp_env" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "derivative", + "masp_primitives", + "namada_core", + "namada_events", + "namada_gas", + "namada_storage", + "namada_tx", + "smooth-operator", +] + +[[package]] +name = "namada_wallet" +version = "0.46.1" +source = "git+https://github.com/anoma/namada?tag=v0.46.1#b24938efd948cb43fc996a729138cb099abcadc0" +dependencies = [ + "bimap", + "borsh", + "borsh-ext", + "data-encoding", + "derivation-path", + "fd-lock", + "itertools 0.12.1", + "masp_primitives", + "namada_core", + "namada_ibc", + "namada_macros", + "orion", + "rand 0.8.5", + "rand_core 0.6.4", + "serde", + "slip10_ed25519", + "smooth-operator", + "thiserror", + "tiny-bip39 0.8.2", + "tiny-hderive", + "toml 0.5.11", + "zeroize", +] [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "nanorand" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" dependencies = [ - "adler", + "getrandom 0.2.15", ] [[package]] -name = "mio" -version = "1.0.2" +name = "native-tls" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "hermit-abi 0.3.9", "libc", - "wasi", - "windows-sys 0.52.0", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] -name = "moka" -version = "0.12.8" +name = "new_debug_unreachable" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" -dependencies = [ - "crossbeam-channel", - "crossbeam-epoch", - "crossbeam-utils", - "once_cell", - "parking_lot", - "quanta", - "rustc_version", - "smallvec", - "tagptr", - "thiserror", - "triomphe", - "uuid", -] +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nonempty" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" [[package]] name = "nu-ansi-term" @@ -2250,6 +4994,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -2257,23 +5015,65 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", - "num-traits", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "num-integer" version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "num-traits", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2284,7 +5084,7 @@ checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde", ] @@ -2295,6 +5095,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "git+https://github.com/heliaxdev/num-traits?rev=3f3657caa34b8e116fdf3f8a3519c4ac29f012fe#3f3657caa34b8e116fdf3f8a3519c4ac29f012fe" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num256" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9b5179e82f0867b23e0b9b822493821f9345561f271364f409c8e4a058367d" +dependencies = [ + "lazy_static", + "num", + "num-derive 0.3.3", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", + "serde_derive", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.9", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.89", ] [[package]] @@ -2327,12 +5181,75 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags 2.6.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.89", +] + [[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.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "opentelemetry" version = "0.19.0" @@ -2386,10 +5303,28 @@ dependencies = [ "once_cell", "opentelemetry_api", "percent-encoding", - "rand", + "rand 0.8.5", "thiserror", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "orion" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6624905ddd92e460ff0685567539ed1ac985b2dee4c92c7edcd64fce905b00c" +dependencies = [ + "ct-codecs", + "getrandom 0.2.15", + "subtle", + "zeroize", +] + [[package]] name = "os_str_bytes" version = "6.6.1" @@ -2408,6 +5343,42 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "pairing" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" +dependencies = [ + "group", +] + +[[package]] +name = "parity-scale-codec" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be4817d39f3272f69c59fe05d0535ae6456c2dc2fa1ba02910296c7e0a5c590" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8781a75c6205af67215f382092b6e0a4ff3734798523e69073d4bcd294ec767b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -2431,19 +5402,92 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "pasta_curves" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +dependencies = [ + "ff", + "group", + "rand 0.8.5", + "static_assertions", + "subtle", +] + [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "path-slash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" + +[[package]] +name = "patricia_tree" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f2f4539bffe53fc4b4da301df49d114b845b077bd5727b7fe2bd9d8df2ae68" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "pbkdf2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +dependencies = [ + "crypto-mac", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", + "hmac 0.12.1", + "password-hash 0.4.2", + "sha2 0.10.8", +] + [[package]] name = "pbkdf2" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", + "hmac 0.12.1", + "password-hash 0.5.0", ] [[package]] @@ -2473,12 +5517,103 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3aeb8f54c078314c2065ee649a7241f46b9d8e418e1a9581ba0546657d7aa3a" +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.6.0", +] + +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version 0.4.1", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.89", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.7" @@ -2496,7 +5631,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2521,6 +5656,29 @@ dependencies = [ "spki", ] +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + [[package]] name = "powerfmt" version = "0.2.0" @@ -2536,6 +5694,22 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn 2.0.89", +] + [[package]] name = "primitive-types" version = "0.12.2" @@ -2543,10 +5717,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", + "impl-codec", + "impl-rlp", "impl-serde", + "scale-info", "uint", ] +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2573,9 +5759,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2595,6 +5781,32 @@ dependencies = [ "thiserror", ] +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bitflags 2.6.0", + "lazy_static", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift", + "regex-syntax 0.8.5", + "unarray", +] + +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive 0.12.6", +] + [[package]] name = "prost" version = "0.13.3" @@ -2602,7 +5814,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.13.3", +] + +[[package]] +name = "prost-build" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +dependencies = [ + "bytes", + "heck 0.4.1", + "itertools 0.12.1", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost 0.12.6", + "prost-types 0.12.6", + "regex", + "syn 2.0.89", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.89", ] [[package]] @@ -2612,10 +5858,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost 0.12.6", +] + +[[package]] +name = "prost-types" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +dependencies = [ + "prost 0.13.3", ] [[package]] @@ -2634,7 +5898,7 @@ dependencies = [ "libc", "once_cell", "raw-cpuid", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "web-sys", "winapi", ] @@ -2648,6 +5912,25 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -2655,8 +5938,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -2666,7 +5959,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -2675,7 +5977,25 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", ] [[package]] @@ -2687,6 +6007,57 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "reddsa" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a5191930e84973293aa5f532b513404460cd2216c1cfb76d08748c15b40b02" +dependencies = [ + "blake2b_simd", + "byteorder", + "group", + "hex", + "jubjub 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pasta_curves", + "rand_core 0.6.4", + "serde", + "thiserror", + "zeroize", +] + +[[package]] +name = "redjubjub" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a60db2c3bc9c6fd1e8631fee75abc008841d27144be744951d6b9b75f9b569c" +dependencies = [ + "rand_core 0.6.4", + "reddsa", + "serde", + "thiserror", + "zeroize", +] + [[package]] name = "redox_syscall" version = "0.5.7" @@ -2702,7 +6073,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libredox", "thiserror", ] @@ -2767,10 +6138,12 @@ dependencies = [ "http-body 0.4.6", "hyper 0.14.31", "hyper-rustls", + "hyper-tls", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -2783,12 +6156,14 @@ dependencies = [ "sync_wrapper 0.1.2", "system-configuration", "tokio", + "tokio-native-tls", "tokio-rustls 0.24.1", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "winreg", ] @@ -2804,10 +6179,25 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac", + "hmac 0.12.1", "subtle", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + [[package]] name = "ring" version = "0.17.8" @@ -2816,10 +6206,10 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.15", "libc", - "spin", - "untrusted", + "spin 0.9.8", + "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -2827,9 +6217,51 @@ dependencies = [ name = "ripemd" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rlp-derive", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rpassword" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "rust_decimal" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ - "digest 0.10.7", + "arrayvec", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2844,13 +6276,28 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.23", ] [[package]] @@ -2873,7 +6320,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring", + "ring 0.17.8", "rustls-webpki 0.101.7", "sct", ] @@ -2885,7 +6332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", - "ring", + "ring 0.17.8", "rustls-pki-types", "rustls-webpki 0.102.8", "subtle", @@ -2900,7 +6347,7 @@ checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e" dependencies = [ "log", "once_cell", - "ring", + "ring 0.17.8", "rustls-pki-types", "rustls-webpki 0.102.8", "subtle", @@ -2975,8 +6422,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -2985,9 +6432,9 @@ version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ - "ring", + "ring 0.17.8", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -3002,6 +6449,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -3011,6 +6467,30 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "cfg-if", + "derive_more 1.0.0", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "scc" version = "2.2.5" @@ -3029,20 +6509,56 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.89", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" +dependencies = [ + "hmac 0.12.1", + "pbkdf2 0.11.0", + "salsa20", + "sha2 0.10.8", +] + [[package]] name = "sct" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -3061,6 +6577,7 @@ dependencies = [ "der", "generic-array", "pkcs8", + "serdect", "subtle", "zeroize", ] @@ -3072,7 +6589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ "bitcoin_hashes", - "rand", + "rand 0.8.5", "secp256k1-sys", "serde", ] @@ -3119,6 +6636,15 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.23" @@ -3128,6 +6654,27 @@ dependencies = [ "serde", ] +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + +[[package]] +name = "send_wrapper" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" + +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" version = "1.0.215" @@ -3137,6 +6684,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-json-wasm" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" +dependencies = [ + "serde", +] + [[package]] name = "serde_bytes" version = "0.11.15" @@ -3164,7 +6720,18 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", ] [[package]] @@ -3197,7 +6764,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3234,6 +6801,16 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "serial_test" version = "3.2.0" @@ -3256,7 +6833,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3351,7 +6928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3360,6 +6937,24 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e2accd2c41a0e920d2abd91b2badcfa1da784662f54fbc47e0e3a51f1e2e1cf" +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror", + "time", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.9" @@ -3369,12 +6964,39 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slip10_ed25519" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be0ff28bf14f9610a342169084e87a4f435ad798ec528dc7579a3678fa9dc9a" +dependencies = [ + "hmac-sha512", +] + [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "smooth-operator" +version = "0.7.0" +source = "git+https://github.com/heliaxdev/smooth-operator?tag=v0.7.0#0e182707f5e5bb9c6e0efa2d235dc9efd715d0a1" +dependencies = [ + "smooth-operator-impl", +] + +[[package]] +name = "smooth-operator-impl" +version = "0.7.0" +source = "git+https://github.com/heliaxdev/smooth-operator?tag=v0.7.0#0e182707f5e5bb9c6e0efa2d235dc9efd715d0a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "socket2" version = "0.5.7" @@ -3385,11 +7007,46 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "solang-parser" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c425ce1c59f4b154717592f0bdf4715c3a1d55058883622d3157e1f0908a5b26" +dependencies = [ + "itertools 0.11.0", + "lalrpop", + "lalrpop-util", + "phf", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "sparse-merkle-tree" +version = "0.3.1-pre" +source = "git+https://github.com/heliaxdev/sparse-merkle-tree?rev=a93c55ccd47840ee0967eee237e47d9245478594#a93c55ccd47840ee0967eee237e47d9245478594" +dependencies = [ + "borsh", + "cfg-if", + "ics23", + "itertools 0.12.1", + "sha2 0.9.9", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -3413,6 +7070,19 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", +] + [[package]] name = "strsim" version = "0.10.0" @@ -3425,7 +7095,16 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" dependencies = [ - "strum_macros", + "strum_macros 0.25.3", +] + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", ] [[package]] @@ -3434,11 +7113,24 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ - "heck", + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.89", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3462,6 +7154,26 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" +[[package]] +name = "svm-rs" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11297baafe5fa0c99d5722458eac6a5e25c01eb1b8e5cd137f54079093daa7a4" +dependencies = [ + "dirs", + "fs2", + "hex", + "once_cell", + "reqwest", + "semver 1.0.23", + "serde", + "serde_json", + "sha2 0.10.8", + "thiserror", + "url", + "zip", +] + [[package]] name = "syn" version = "1.0.109" @@ -3475,9 +7187,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -3516,7 +7228,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3546,6 +7258,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.14.0" @@ -3559,6 +7277,37 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "tendermint" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d9d6ffeb83b1de47c307c6e0d2dff56c6256989299010ad03cd80a8491e97" +dependencies = [ + "bytes", + "digest 0.10.7", + "ed25519", + "ed25519-consensus", + "flex-error", + "futures", + "k256", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell", + "prost 0.13.3", + "prost-types 0.13.3", + "ripemd", + "serde", + "serde_bytes", + "serde_json", + "serde_repr", + "sha2 0.10.8", + "signature", + "subtle", + "subtle-encoding", + "tendermint-proto 0.38.1", + "time", + "zeroize", +] + [[package]] name = "tendermint" version = "0.40.0" @@ -3572,9 +7321,9 @@ dependencies = [ "flex-error", "futures", "k256", - "num-traits", + "num-traits 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell", - "prost", + "prost 0.13.3", "ripemd", "serde", "serde_bytes", @@ -3584,11 +7333,25 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto", + "tendermint-proto 0.40.0", "time", "zeroize", ] +[[package]] +name = "tendermint-config" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de111ea653b2adaef627ac2452b463c77aa615c256eaaddf279ec5a1cf9775f" +dependencies = [ + "flex-error", + "serde", + "serde_json", + "tendermint 0.38.1", + "toml 0.8.19", + "url", +] + [[package]] name = "tendermint-config" version = "0.40.0" @@ -3598,7 +7361,7 @@ dependencies = [ "flex-error", "serde", "serde_json", - "tendermint", + "tendermint 0.40.0", "toml 0.8.19", "url", ] @@ -3611,7 +7374,7 @@ checksum = "3e88c08a112db05101396a79f71c017d7dbf548dc21614f82251f17ecbe5d5e8" dependencies = [ "contracts", "crossbeam-channel", - "derive_more", + "derive_more 0.99.18", "flex-error", "futures", "regex", @@ -3620,9 +7383,9 @@ dependencies = [ "serde_derive", "serde_json", "static_assertions", - "tendermint", - "tendermint-light-client-verifier", - "tendermint-rpc", + "tendermint 0.40.0", + "tendermint-light-client-verifier 0.40.0", + "tendermint-rpc 0.40.0", "time", "tokio", "tracing", @@ -3635,7 +7398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d48a431ea923182c37ca9f3cc8333490ac6746a64520d1c4a3dd18c08b0806ac" dependencies = [ "crossbeam-channel", - "derive_more", + "derive_more 0.99.18", "flex-error", "futures", "serde", @@ -3643,40 +7406,103 @@ dependencies = [ "serde_derive", "serde_json", "static_assertions", - "tendermint", + "tendermint 0.40.0", "tendermint-light-client", - "tendermint-proto", - "tendermint-rpc", + "tendermint-proto 0.40.0", + "tendermint-rpc 0.40.0", + "time", + "tracing", +] + +[[package]] +name = "tendermint-light-client-verifier" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2674adbf0dc51aa0c8eaf8462c7d6692ec79502713e50ed5432a442002be90" +dependencies = [ + "derive_more 0.99.18", + "flex-error", + "serde", + "tendermint 0.38.1", + "time", +] + +[[package]] +name = "tendermint-light-client-verifier" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7affc5fffe9df158185e15bce3e47fc3a0c901e6708f3b7d33f0867d7aef8ce1" +dependencies = [ + "derive_more 0.99.18", + "flex-error", + "serde", + "tendermint 0.40.0", + "time", +] + +[[package]] +name = "tendermint-proto" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed14abe3b0502a3afe21ca74ca5cdd6c7e8d326d982c26f98a394445eb31d6e" +dependencies = [ + "bytes", + "flex-error", + "prost 0.13.3", + "prost-types 0.13.3", + "serde", + "serde_bytes", + "subtle-encoding", "time", - "tracing", ] [[package]] -name = "tendermint-light-client-verifier" +name = "tendermint-proto" version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7affc5fffe9df158185e15bce3e47fc3a0c901e6708f3b7d33f0867d7aef8ce1" +checksum = "c81ba1b023ec00763c3bc4f4376c67c0047f185cccf95c416c7a2f16272c4cbb" dependencies = [ - "derive_more", + "bytes", "flex-error", + "prost 0.13.3", "serde", - "tendermint", + "serde_bytes", + "subtle-encoding", "time", ] [[package]] -name = "tendermint-proto" -version = "0.40.0" +name = "tendermint-rpc" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c81ba1b023ec00763c3bc4f4376c67c0047f185cccf95c416c7a2f16272c4cbb" +checksum = "02f96a2b8a0d3d0b59e4024b1a6bdc1589efc6af4709d08a480a20cc4ba90f63" dependencies = [ + "async-trait", + "async-tungstenite", "bytes", "flex-error", - "prost", + "futures", + "getrandom 0.2.15", + "peg", + "pin-project", + "rand 0.8.5", + "reqwest", + "semver 1.0.23", "serde", "serde_bytes", + "serde_json", + "subtle", "subtle-encoding", + "tendermint 0.38.1", + "tendermint-config 0.38.1", + "tendermint-proto 0.38.1", + "thiserror", "time", + "tokio", + "tracing", + "url", + "uuid 1.11.0", + "walkdir", ] [[package]] @@ -3690,26 +7516,26 @@ dependencies = [ "bytes", "flex-error", "futures", - "getrandom", + "getrandom 0.2.15", "peg", "pin-project", - "rand", + "rand 0.8.5", "reqwest", - "semver", + "semver 1.0.23", "serde", "serde_bytes", "serde_json", "subtle", "subtle-encoding", - "tendermint", - "tendermint-config", - "tendermint-proto", + "tendermint 0.40.0", + "tendermint-config 0.40.0", + "tendermint-proto 0.40.0", "thiserror", "time", "tokio", "tracing", "url", - "uuid", + "uuid 1.11.0", "walkdir", ] @@ -3725,10 +7551,21 @@ dependencies = [ "serde_json", "simple-error", "tempfile", - "tendermint", + "tendermint 0.40.0", "time", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -3738,6 +7575,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "test-log" version = "0.2.16" @@ -3757,7 +7604,7 @@ checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3783,7 +7630,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3803,6 +7650,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", "serde", @@ -3826,6 +7674,24 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-bip39" +version = "0.8.2" +source = "git+https://github.com/anoma/tiny-bip39.git?rev=bf0f6d8713589b83af7a917366ec31f5275c0e57#bf0f6d8713589b83af7a917366ec31f5275c0e57" +dependencies = [ + "anyhow", + "hmac 0.8.1", + "once_cell", + "pbkdf2 0.4.0", + "rand 0.7.3", + "rustc-hash", + "sha2 0.9.9", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + [[package]] name = "tiny-bip39" version = "1.0.0" @@ -3833,10 +7699,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" dependencies = [ "anyhow", - "hmac", + "hmac 0.12.1", "once_cell", - "pbkdf2", - "rand", + "pbkdf2 0.11.0", + "rand 0.8.5", "rustc-hash", "sha2 0.10.8", "thiserror", @@ -3845,6 +7711,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "tiny-hderive" +version = "0.3.0" +source = "git+https://github.com/heliaxdev/tiny-hderive.git?rev=173ae03abed0cd25d88a5a13efac00af96b75b87#173ae03abed0cd25d88a5a13efac00af96b75b87" +dependencies = [ + "base58", + "hmac 0.12.1", + "k256", + "memzero", + "sha2 0.10.8", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -3905,7 +7783,17 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", +] + +[[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]] @@ -3951,6 +7839,21 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", + "tungstenite 0.20.1", + "webpki-roots", +] + [[package]] name = "tokio-util" version = "0.7.12" @@ -4027,7 +7930,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost", + "prost 0.13.3", "rustls-native-certs 0.8.0", "rustls-pemfile 2.2.0", "socket2", @@ -4040,6 +7943,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "tonic-build" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "quote", + "syn 2.0.89", +] + [[package]] name = "tower" version = "0.4.13" @@ -4051,7 +7967,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand", + "rand 0.8.5", "slab", "tokio", "tokio-util", @@ -4106,7 +8022,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4129,6 +8045,16 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "tracing-log" version = "0.1.4" @@ -4194,6 +8120,26 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 0.2.12", + "httparse", + "log", + "rand 0.8.5", + "rustls 0.21.12", + "sha1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "tungstenite" version = "0.21.0" @@ -4206,7 +8152,7 @@ dependencies = [ "http 1.1.0", "httparse", "log", - "rand", + "rand 0.8.5", "rustls 0.22.4", "rustls-pki-types", "sha1", @@ -4215,12 +8161,53 @@ dependencies = [ "utf-8", ] +[[package]] +name = "typed-builder" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06fbd5b8de54c5f7c91f6fe4cebb949be2125d7758e630bb58b1d831dbce600" +dependencies = [ + "typed-builder-macro", +] + +[[package]] +name = "typed-builder-macro" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9534daa9fd3ed0bd911d462a37f172228077e7abf18c18a5f67199d959205f8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "typewit" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fb9ae6a3cafaf0a5d14c2302ca525f9ae8e07a0f0e6949de88d882c37a6e24" +dependencies = [ + "typewit_proc_macros", +] + +[[package]] +name = "typewit_proc_macros" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36a83ea2b3c704935a01b4642946aadd445cea40b10935e3f8bd8052b8193d6" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "uint" version = "0.9.5" @@ -4233,6 +8220,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-ident" version = "1.0.13" @@ -4260,12 +8253,28 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "unsafe-libyaml" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -4319,13 +8328,23 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.15", + "serde", +] + [[package]] name = "uuid" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -4334,6 +8353,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[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.5" @@ -4368,6 +8393,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4396,7 +8427,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "wasm-bindgen-shared", ] @@ -4430,7 +8461,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4441,6 +8472,30 @@ version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +[[package]] +name = "wasmparser" +version = "0.107.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +dependencies = [ + "indexmap 1.9.3", + "semver 1.0.23", +] + +[[package]] +name = "wasmtimer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7ed9d8b15c7fb594d72bfb4b5a276f3d2029333cd93a932f376f5937f6f80ee" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "web-sys" version = "0.3.72" @@ -4451,6 +8506,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + [[package]] name = "winapi" version = "0.3.9" @@ -4670,6 +8731,51 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "ws_stream_wasm" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +dependencies = [ + "async_io_stream", + "futures", + "js-sys", + "log", + "pharos", + "rustc_version 0.4.1", + "send_wrapper 0.6.0", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "xorf" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf24c008fe464f5d8f58b8d16a1ab7e930bd73b2a6933ff8704c414b2bed7f92" +dependencies = [ + "libm", + "rand 0.8.5", + "serde", +] + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "yoke" version = "0.7.4" @@ -4690,10 +8796,19 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "synstructure 0.13.1", ] +[[package]] +name = "zcash_encoding" +version = "0.2.0" +source = "git+https://github.com/zcash/librustzcash?rev=bd7f9d7#bd7f9d7c3ce5cfd14af169ffe0e1c5c903162f46" +dependencies = [ + "byteorder", + "nonempty", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -4712,7 +8827,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4732,7 +8847,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "synstructure 0.13.1", ] @@ -4753,7 +8868,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4775,5 +8890,54 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", +] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq 0.1.5", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac 0.12.1", + "pbkdf2 0.11.0", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index 76395a86b7..84fb6e70aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,12 @@ tendermint-proto = { version = "0.40.0" } tendermint-rpc = { version = "0.40.0" } tendermint-testgen = { version = "0.40.0" } +# Namada dependencies +namada_sdk = { git = "https://github.com/anoma/namada", tag = "v0.46.1" } +# Different tendermint-rs version for Namada +namada-tendermint = { package = "tendermint", version = "0.38.0", default-features = false } +namada-tendermint-proto = { package = "tendermint-proto", version = "0.38.0" } +namada-tendermint-rpc = { package = "tendermint-rpc", version = "0.38.0" } # Other dependencies abscissa_core = "=0.6.0" @@ -93,6 +99,7 @@ regex = "1.11.1" reqwest = { version = "0.11.27", default-features = false } retry = { version = "2.0.0", default-features = false } ripemd = "0.1.3" +rpassword = "5.0.1" secp256k1 = "0.28.2" semver = "1.0.21" serde = "1.0.214" diff --git a/ci/release/hermes.Dockerfile b/ci/release/hermes.Dockerfile index 8540b2446b..105b9b2dd8 100644 --- a/ci/release/hermes.Dockerfile +++ b/ci/release/hermes.Dockerfile @@ -6,9 +6,23 @@ FROM rust:1-buster AS build-env ARG TAG +ARG PROTOC_VERSION=28.3 WORKDIR /root +# Install protoc +RUN ARCH=$(uname -m) && \ + if [ "$ARCH" = "x86_64" ]; then \ + ARCH=x86_64; \ + elif [ "$ARCH" = "aarch64" ]; then \ + ARCH=aarch_64;\ + else \ + echo "Unsupported architecture: $ARCH"; exit 1; \ + fi && \ + wget https://github.com/protocolbuffers/protobuf/releases/download/v$PROTOC_VERSION/protoc-$PROTOC_VERSION-linux-$ARCH.zip -O /tmp/protoc.zip && \ + unzip /tmp/protoc.zip -d /usr/local && \ + rm -rf /tmp/protoc.zip + COPY . . RUN cargo build --release @@ -17,12 +31,24 @@ LABEL maintainer="hello@informal.systems" ARG UID=2000 ARG GID=2000 -RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates wget RUN update-ca-certificates RUN groupadd -g ${GID} hermes && useradd -l -m hermes -s /bin/bash -u ${UID} -g ${GID} WORKDIR /home/hermes + +RUN ARCH=$(uname -m) && \ + if [ "$ARCH" = "x86_64" ]; then \ + DEB_URL=http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.23_amd64.deb; \ + elif [ "$ARCH" = "aarch64" ]; then \ + DEB_URL=http://ports.ubuntu.com/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_arm64.deb; \ + else \ + echo "Unsupported architecture: $ARCH"; exit 1; \ + fi && \ + wget $DEB_URL -O /tmp/libssl1.1.deb && \ + dpkg -i /tmp/libssl1.1.deb && \ + rm -rf /tmp/libssl1.1.deb + USER hermes:hermes ENTRYPOINT ["/usr/bin/hermes"] - COPY --chown=hermes:hermes --from=build-env /root/target/release/hermes /usr/bin/hermes diff --git a/clippy.toml b/clippy.toml index 7372c60ff2..4233c8791a 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.76.0" +msrv = "1.79.0" diff --git a/config.toml b/config.toml index aeb2eff924..224d49af7c 100644 --- a/config.toml +++ b/config.toml @@ -158,7 +158,7 @@ port = 5555 # Specify the chain ID. Required id = 'ibc-0' -# Specify the chain type, currently only `CosmosSdk` is supported. +# Specify the chain type, currently `CosmosSdk` and `Namada` are supported. # Default: CosmosSdk type = "CosmosSdk" diff --git a/crates/chain-registry/Cargo.toml b/crates/chain-registry/Cargo.toml index 2b04a2096b..00bf1ce92c 100644 --- a/crates/chain-registry/Cargo.toml +++ b/crates/chain-registry/Cargo.toml @@ -6,7 +6,7 @@ license = "Apache-2.0" keywords = ["cosmos", "ibc", "relayer", "chain", "registry"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.76.0" +rust-version = "1.79.0" description = """ Service to fetch data from the chain-registry """ diff --git a/crates/relayer-cli/Cargo.toml b/crates/relayer-cli/Cargo.toml index 4af2c123a4..69eb9996ad 100644 --- a/crates/relayer-cli/Cargo.toml +++ b/crates/relayer-cli/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] homepage = "https://hermes.informal.systems/" repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.76.0" +rust-version = "1.79.0" description = """ Hermes is an IBC Relayer written in Rust """ diff --git a/crates/relayer-cli/src/commands/keys/add.rs b/crates/relayer-cli/src/commands/keys/add.rs index b24514d00a..30f7c4d055 100644 --- a/crates/relayer-cli/src/commands/keys/add.rs +++ b/crates/relayer-cli/src/commands/keys/add.rs @@ -10,9 +10,11 @@ use abscissa_core::{Command, Runnable}; use eyre::eyre; use hdpath::StandardHDPath; use ibc_relayer::{ + chain::namada::wallet::CliWalletUtils, config::{ChainConfig, Config}, keyring::{ - AnySigningKeyPair, KeyRing, Secp256k1KeyPair, SigningKeyPair, SigningKeyPairSized, Store, + AnySigningKeyPair, KeyRing, NamadaKeyPair, Secp256k1KeyPair, SigningKeyPair, + SigningKeyPairSized, Store, }, }; use ibc_relayer_types::core::ics24_host::identifier::ChainId; @@ -220,6 +222,36 @@ pub fn add_key( keyring.add_key(key_name, key_pair.clone())?; key_pair.into() } + ChainConfig::Namada(config) => { + let mut keyring = + KeyRing::new_namada(Store::Test, &config.id, &config.key_store_folder)?; + + check_key_exists(&keyring, key_name, overwrite); + + let path = if file.is_file() { + file.parent().ok_or(eyre!("invalid Namada wallet path"))? + } else { + file + }; + let mut wallet = CliWalletUtils::new(path.to_path_buf()); + wallet + .load() + .map_err(|e| eyre!("error loading Namada wallet: {e}"))?; + + let secret_key = wallet + .find_secret_key(key_name, None) + .map_err(|e| eyre!("error loading the key from Namada wallet: {e}"))?; + let address = wallet + .find_address(key_name) + .ok_or_else(|| eyre!("error loading the address from Namada wallet"))?; + let namada_key = NamadaKeyPair { + alias: key_name.to_string(), + address: address.into_owned(), + secret_key: secret_key.clone(), + }; + keyring.add_key(key_name, namada_key.clone())?; + namada_key.into() + } }; Ok(key_pair) @@ -256,6 +288,11 @@ pub fn restore_key( keyring.add_key(key_name, key_pair.clone())?; key_pair.into() } + ChainConfig::Namada(_) => { + return Err(eyre!( + "Namada key can't be restored here. Use Namada wallet." + )); + } }; Ok(key_pair) diff --git a/crates/relayer-cli/src/commands/keys/balance.rs b/crates/relayer-cli/src/commands/keys/balance.rs index b3c1edd90d..b3c9851bb9 100644 --- a/crates/relayer-cli/src/commands/keys/balance.rs +++ b/crates/relayer-cli/src/commands/keys/balance.rs @@ -77,7 +77,9 @@ fn get_balance(chain: impl ChainHandle, key_name: Option, denom: Option< let key_name = key_name.unwrap_or_else(|| { let chain_config = chain.config().unwrap_or_else(exit_with_unrecoverable_error); match chain_config { - ChainConfig::CosmosSdk(chain_config) => chain_config.key_name, + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { + chain_config.key_name + } } }); @@ -99,7 +101,9 @@ fn get_balances(chain: impl ChainHandle, key_name: Option) { let key_name = key_name.unwrap_or_else(|| { let chain_config = chain.config().unwrap_or_else(exit_with_unrecoverable_error); match chain_config { - ChainConfig::CosmosSdk(chain_config) => chain_config.key_name, + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { + chain_config.key_name + } } }); diff --git a/crates/relayer-cli/src/commands/keys/delete.rs b/crates/relayer-cli/src/commands/keys/delete.rs index fe25e8a056..aef00748d0 100644 --- a/crates/relayer-cli/src/commands/keys/delete.rs +++ b/crates/relayer-cli/src/commands/keys/delete.rs @@ -123,6 +123,11 @@ pub fn delete_key(config: &ChainConfig, key_name: &str) -> eyre::Result<()> { )?; keyring.remove_key(key_name)?; } + ChainConfig::Namada(config) => { + let mut keyring = + KeyRing::new_namada(Store::Test, &config.id, &config.key_store_folder)?; + keyring.remove_key(key_name)?; + } } Ok(()) } @@ -141,6 +146,14 @@ pub fn delete_all_keys(config: &ChainConfig) -> eyre::Result<()> { keyring.remove_key(&key_name)?; } } + ChainConfig::Namada(config) => { + let mut keyring = + KeyRing::new_namada(Store::Test, &config.id, &config.key_store_folder)?; + let keys = keyring.keys()?; + for (key_name, _) in keys { + keyring.remove_key(&key_name)?; + } + } } Ok(()) } diff --git a/crates/relayer-cli/src/commands/listen.rs b/crates/relayer-cli/src/commands/listen.rs index ea8bd979cb..f922aa562c 100644 --- a/crates/relayer-cli/src/commands/listen.rs +++ b/crates/relayer-cli/src/commands/listen.rs @@ -146,7 +146,7 @@ fn subscribe( // Q: Should this be restricted only to backends that support it, // or are all backends expected to support subscriptions? match chain_config { - ChainConfig::CosmosSdk(config) => { + ChainConfig::CosmosSdk(config) | ChainConfig::Namada(config) => { let (event_source, monitor_tx) = match &config.event_source { EventSourceMode::Push { url, batch_delay } => EventSource::websocket( chain_config.id().clone(), @@ -189,7 +189,7 @@ fn detect_compatibility_mode( ) -> eyre::Result { // TODO(erwan): move this to the cosmos sdk endpoint implementation let rpc_addr = match config { - ChainConfig::CosmosSdk(config) => config.rpc_addr.clone(), + ChainConfig::CosmosSdk(config) | ChainConfig::Namada(config) => config.rpc_addr.clone(), }; let client = HttpClient::builder(rpc_addr.try_into()?) @@ -197,7 +197,9 @@ fn detect_compatibility_mode( .build()?; let compat_mode = match config { - ChainConfig::CosmosSdk(config) => rt.block_on(fetch_compat_mode(&client, config))?, + ChainConfig::CosmosSdk(config) | ChainConfig::Namada(config) => { + rt.block_on(fetch_compat_mode(&client, config))? + } }; Ok(compat_mode) diff --git a/crates/relayer-cli/src/commands/tx/client.rs b/crates/relayer-cli/src/commands/tx/client.rs index 827d1c5cc1..9f7edc9556 100644 --- a/crates/relayer-cli/src/commands/tx/client.rs +++ b/crates/relayer-cli/src/commands/tx/client.rs @@ -206,7 +206,7 @@ impl Runnable for TxUpdateClientCmd { if let Some(restart_params) = self.genesis_restart_params() { match config.find_chain_mut(&reference_chain_id) { Some(chain_config) => match chain_config { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.genesis_restart = Some(restart_params) } }, @@ -341,7 +341,7 @@ impl Runnable for TxUpgradeClientCmd { reference_application_latest_height ); - while reference_application_latest_height != target_reference_application_height { + while reference_application_latest_height < target_reference_application_height { thread::sleep(Duration::from_millis(500)); reference_application_latest_height = match client.src_chain().query_latest_height() { diff --git a/crates/relayer-cli/src/commands/tx/upgrade.rs b/crates/relayer-cli/src/commands/tx/upgrade.rs index d41bf6ce1e..5c0773a82b 100644 --- a/crates/relayer-cli/src/commands/tx/upgrade.rs +++ b/crates/relayer-cli/src/commands/tx/upgrade.rs @@ -127,7 +127,9 @@ impl Runnable for TxIbcUpgradeChainCmd { let reference_chain = spawn_chain_runtime(&config, &self.reference_chain_id) .unwrap_or_else(exit_with_unrecoverable_error); - let gov_account = if requires_legacy_upgrade_proposal(reference_chain.clone()) { + let gov_account = if requires_legacy_upgrade_proposal(reference_chain.clone()) + .unwrap_or_else(exit_with_unrecoverable_error) + { "".to_string() } else if let Some(gov_account) = &self.gov_account { gov_account.clone() diff --git a/crates/relayer-rest/Cargo.toml b/crates/relayer-rest/Cargo.toml index 70eaee0b78..8f4e14c84d 100644 --- a/crates/relayer-rest/Cargo.toml +++ b/crates/relayer-rest/Cargo.toml @@ -8,7 +8,7 @@ readme = "README.md" keywords = ["ibc", "rest", "api", "cosmos", "tendermint"] homepage = "https://hermes.informal.systems/" repository = "https://github.com/informalsystems/hermes" -rust-version = "1.76.0" +rust-version = "1.79.0" description = """ Rust implementation of a RESTful API server for Hermes """ @@ -24,5 +24,6 @@ tokio = { workspace = true } tracing = { workspace = true } [dev-dependencies] -reqwest = { workspace = true, features = ["json"] } -toml = { workspace = true } +reqwest = { workspace = true, features = ["json"] } +serde_json = { workspace = true } +toml = { workspace = true } diff --git a/crates/relayer-rest/tests/mock.rs b/crates/relayer-rest/tests/mock.rs index 21dfd19ea9..4755812414 100644 --- a/crates/relayer-rest/tests/mock.rs +++ b/crates/relayer-rest/tests/mock.rs @@ -46,9 +46,12 @@ where let response = reqwest::get(&format!("http://127.0.0.1:{port}{path}")) .await .unwrap() - .json::() + .json() .await .unwrap(); + // Workaround for serde_json deserialization failure + // from_str/from_slice() failed for ChainConfig + let response = serde_json::from_value::(response).unwrap(); assert_eq!(response, expected); diff --git a/crates/relayer-types/Cargo.toml b/crates/relayer-types/Cargo.toml index 5c3e998ce2..5f19dfc2be 100644 --- a/crates/relayer-types/Cargo.toml +++ b/crates/relayer-types/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.76.0" +rust-version = "1.79.0" description = """ Implementation of the Inter-Blockchain Communication Protocol (IBC). This crate comprises the main data structures and on-chain logic. diff --git a/crates/relayer-types/src/core/ics03_connection/events.rs b/crates/relayer-types/src/core/ics03_connection/events.rs index 5fddc6cfad..e91b7e7ed6 100644 --- a/crates/relayer-types/src/core/ics03_connection/events.rs +++ b/crates/relayer-types/src/core/ics03_connection/events.rs @@ -4,6 +4,7 @@ use serde_derive::{Deserialize, Serialize}; use std::fmt::{Display, Error as FmtError, Formatter}; use tendermint::abci; +use crate::core::ics04_channel::events::EventType; use crate::core::ics24_host::identifier::{ClientId, ConnectionId}; use crate::events::{IbcEvent, IbcEventType}; @@ -68,6 +69,12 @@ impl OpenInit { } } +impl EventType for OpenInit { + fn event_type() -> IbcEventType { + IbcEventType::OpenInitConnection + } +} + impl Display for OpenInit { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { write!(f, "OpenInit {{ {} }}", self.0) @@ -107,6 +114,12 @@ impl OpenTry { } } +impl EventType for OpenTry { + fn event_type() -> IbcEventType { + IbcEventType::OpenTryConnection + } +} + impl Display for OpenTry { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { write!(f, "OpenTry {{ {} }}", self.0) @@ -146,6 +159,12 @@ impl OpenAck { } } +impl EventType for OpenAck { + fn event_type() -> IbcEventType { + IbcEventType::OpenAckConnection + } +} + impl Display for OpenAck { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { write!(f, "OpenAck {{ {} }}", self.0) @@ -185,6 +204,12 @@ impl OpenConfirm { } } +impl EventType for OpenConfirm { + fn event_type() -> IbcEventType { + IbcEventType::OpenConfirmConnection + } +} + impl Display for OpenConfirm { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { write!(f, "OpenConfirm {{ {} }}", self.0) diff --git a/crates/relayer-types/src/events.rs b/crates/relayer-types/src/events.rs index 7ceb45d5c2..1d27cc337a 100644 --- a/crates/relayer-types/src/events.rs +++ b/crates/relayer-types/src/events.rs @@ -282,7 +282,7 @@ impl FromStr for IbcEventType { } /// Events created by the IBC component of a chain, destined for a relayer. -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq)] pub enum IbcEvent { NewBlock(NewBlock), diff --git a/crates/relayer/Cargo.toml b/crates/relayer/Cargo.toml index d74325dba1..1a910200cf 100644 --- a/crates/relayer/Cargo.toml +++ b/crates/relayer/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.76.0" +rust-version = "1.79.0" description = """ Implementation of an IBC Relayer in Rust, as a library """ @@ -46,6 +46,10 @@ humantime = { workspace = true } humantime-serde = { workspace = true } itertools = { workspace = true } moka = { workspace = true, features = ["sync"] } +namada_sdk = { workspace = true } +namada-tendermint = { workspace = true } +namada-tendermint-proto = { workspace = true } +namada-tendermint-rpc = { workspace = true, features = ["http-client", "websocket-client"] } num-bigint = { workspace = true, features = ["serde"] } num-rational = { workspace = true, features = ["num-bigint", "serde"] } once_cell = { workspace = true } @@ -54,6 +58,7 @@ regex = { workspace = true } reqwest = { workspace = true, features = ["rustls-tls-native-roots", "json"] } retry = { workspace = true } ripemd = { workspace = true } +rpassword = { workspace = true } secp256k1 = { workspace = true, features = ["rand-std"] } semver = { workspace = true } serde = { workspace = true } diff --git a/crates/relayer/src/chain.rs b/crates/relayer/src/chain.rs index bcca34e85f..9512e3865e 100644 --- a/crates/relayer/src/chain.rs +++ b/crates/relayer/src/chain.rs @@ -3,6 +3,8 @@ pub mod cosmos; pub mod counterparty; pub mod endpoint; pub mod handle; +pub mod namada; pub mod requests; pub mod runtime; pub mod tracking; +pub mod version; diff --git a/crates/relayer/src/chain/client.rs b/crates/relayer/src/chain/client.rs index 6f00ec8df9..54341c525d 100644 --- a/crates/relayer/src/chain/client.rs +++ b/crates/relayer/src/chain/client.rs @@ -27,9 +27,12 @@ impl ClientSettings { // // TODO: extract Tendermint-related configs into a separate substructure // that can be used both by CosmosSdkConfig and configs for nonSDK chains. - use ChainConfig::CosmosSdk as Csdk; + use ChainConfig::{CosmosSdk as Csdk, Namada}; match (src_chain_config, dst_chain_config) { - (Csdk(src_chain_config), Csdk(dst_chain_config)) => { + (Csdk(src_chain_config), Csdk(dst_chain_config)) + | (Namada(src_chain_config), Namada(dst_chain_config)) + | (Csdk(src_chain_config), Namada(dst_chain_config)) + | (Namada(src_chain_config), Csdk(dst_chain_config)) => { ClientSettings::Tendermint(cosmos::client::Settings::for_create_command( options, src_chain_config, diff --git a/crates/relayer/src/chain/cosmos.rs b/crates/relayer/src/chain/cosmos.rs index 1dc99d6923..f6e00232bd 100644 --- a/crates/relayer/src/chain/cosmos.rs +++ b/crates/relayer/src/chain/cosmos.rs @@ -98,6 +98,7 @@ use crate::chain::endpoint::{ChainEndpoint, ChainStatus, HealthCheck}; use crate::chain::handle::Subscription; use crate::chain::requests::*; use crate::chain::tracking::TrackedMsgs; +use crate::chain::version::Specs; use crate::client_state::{AnyClientState, IdentifiedAnyClientState}; use crate::config::Error as ConfigError; use crate::config::{parse_gas_prices, ChainConfig, GasPrice}; @@ -119,7 +120,6 @@ use crate::HERMES_VERSION; use self::gas::dynamic_gas_price; use self::types::gas::GasConfig; -use self::version::Specs; pub mod batch; pub mod client; @@ -1119,8 +1119,7 @@ impl ChainEndpoint for CosmosSdkChain { &self.rpc_client, &self.config.rpc_addr, ))?; - - Ok(version_specs) + Ok(Specs::Cosmos(version_specs)) } fn query_balance(&self, key_name: Option<&str>, denom: Option<&str>) -> Result { diff --git a/crates/relayer/src/chain/cosmos/batch.rs b/crates/relayer/src/chain/cosmos/batch.rs index 3e52f52aec..bf55a4ec27 100644 --- a/crates/relayer/src/chain/cosmos/batch.rs +++ b/crates/relayer/src/chain/cosmos/batch.rs @@ -209,7 +209,7 @@ async fn sequential_send_messages_as_batches( Ok(tx_sync_results) } -fn response_to_tx_sync_result( +pub fn response_to_tx_sync_result( chain_id: &ChainId, message_count: usize, response: Response, diff --git a/crates/relayer/src/chain/cosmos/config.rs b/crates/relayer/src/chain/cosmos/config.rs index 911e147f32..1a58cc27ac 100644 --- a/crates/relayer/src/chain/cosmos/config.rs +++ b/crates/relayer/src/chain/cosmos/config.rs @@ -167,7 +167,7 @@ impl CosmosSdkConfig { /// a) non-zero /// b) greater or equal to 1/3 /// c) strictly less than 1 -fn validate_trust_threshold( +pub fn validate_trust_threshold( id: &ChainId, trust_threshold: TrustThreshold, ) -> Result<(), Diagnostic> { diff --git a/crates/relayer/src/chain/cosmos/gas.rs b/crates/relayer/src/chain/cosmos/gas.rs index 2106da3375..76ad0adcb3 100644 --- a/crates/relayer/src/chain/cosmos/gas.rs +++ b/crates/relayer/src/chain/cosmos/gas.rs @@ -117,16 +117,16 @@ pub fn mul_floor(a: u64, f: f64) -> BigInt { (f * a).floor().to_integer() } -struct AdjustGas { - gas_multiplier: f64, - max_gas: u64, - gas_amount: u64, +pub struct AdjustGas { + pub gas_multiplier: f64, + pub max_gas: u64, + pub gas_amount: u64, } /// Adjusts the fee based on the configured `gas_multiplier` to prevent out of gas errors. /// The actual gas cost, when a transaction is executed, may be slightly higher than the /// one returned by the simulation. -fn adjust_estimated_gas( +pub fn adjust_estimated_gas( AdjustGas { gas_multiplier, max_gas, diff --git a/crates/relayer/src/chain/cosmos/types/events/channel.rs b/crates/relayer/src/chain/cosmos/types/events/channel.rs index 7a1313ae00..5c3279987a 100644 --- a/crates/relayer/src/chain/cosmos/types/events/channel.rs +++ b/crates/relayer/src/chain/cosmos/types/events/channel.rs @@ -1,5 +1,3 @@ -use alloc::collections::btree_map::BTreeMap as HashMap; - use ibc_relayer_types::applications::ics31_icq::events::CrossChainQueryPacket; use ibc_relayer_types::core::ics02_client::height::HeightErrorDetail; use ibc_relayer_types::core::ics04_channel::error::Error; @@ -18,6 +16,10 @@ use ibc_relayer_types::core::ics24_host::identifier::ChainId; use ibc_relayer_types::events::Error as EventError; use ibc_relayer_types::Height; +use crate::chain::cosmos::types::events::raw_object::extract_attribute; +use crate::chain::cosmos::types::events::raw_object::maybe_extract_attribute; +use crate::chain::cosmos::types::events::raw_object::RawObject; + fn extract_attributes(object: &RawObject<'_>, namespace: &str) -> Result { Ok(Attributes { port_id: extract_attribute(object, &format!("{namespace}.port_id"))? @@ -248,41 +250,3 @@ impl TryFrom> for CrossChainQueryPacket { }) } } - -#[derive(Debug, Clone)] -pub struct RawObject<'a> { - pub height: Height, - pub action: String, - pub idx: usize, - pub events: &'a HashMap>, -} - -impl<'a> RawObject<'a> { - pub fn new( - height: Height, - action: String, - idx: usize, - events: &'a HashMap>, - ) -> RawObject<'a> { - RawObject { - height, - action, - idx, - events, - } - } -} - -pub fn extract_attribute(object: &RawObject<'_>, key: &str) -> Result { - let value = object - .events - .get(key) - .ok_or_else(|| EventError::missing_key(key.to_string()))?[object.idx] - .clone(); - - Ok(value) -} - -pub fn maybe_extract_attribute(object: &RawObject<'_>, key: &str) -> Option { - object.events.get(key).map(|tags| tags[object.idx].clone()) -} diff --git a/crates/relayer/src/chain/cosmos/types/events/connection.rs b/crates/relayer/src/chain/cosmos/types/events/connection.rs new file mode 100644 index 0000000000..d629ec5506 --- /dev/null +++ b/crates/relayer/src/chain/cosmos/types/events/connection.rs @@ -0,0 +1,68 @@ +use ibc_relayer_types::core::ics03_connection::events::Attributes; +use ibc_relayer_types::core::ics03_connection::events::OpenAck; +use ibc_relayer_types::core::ics03_connection::events::OpenConfirm; +use ibc_relayer_types::core::ics03_connection::events::OpenInit; +use ibc_relayer_types::core::ics03_connection::events::OpenTry; +use ibc_relayer_types::core::ics04_channel::events::EventType; +use ibc_relayer_types::events::Error as EventError; + +use crate::chain::cosmos::types::events::raw_object::extract_attribute; +use crate::chain::cosmos::types::events::raw_object::maybe_extract_attribute; +use crate::chain::cosmos::types::events::raw_object::RawObject; + +fn extract_attributes(object: &RawObject<'_>, namespace: &str) -> Result { + Ok(Attributes { + client_id: extract_attribute(object, &format!("{namespace}.client_id"))? + .parse() + .map_err(EventError::parse)?, + counterparty_connection_id: maybe_extract_attribute( + object, + &format!("{namespace}.counterparty_connection_id"), + ) + .and_then(|v| v.parse().ok()), + counterparty_client_id: extract_attribute( + object, + &format!("{namespace}.counterparty_client_id"), + )? + .parse() + .map_err(EventError::parse)?, + connection_id: maybe_extract_attribute(object, &format!("{namespace}.connection_id")) + .and_then(|v| v.parse().ok()), + }) +} + +impl TryFrom> for OpenInit { + type Error = EventError; + + fn try_from(value: RawObject<'_>) -> Result { + let attributes = extract_attributes(&value, Self::event_type().as_str())?; + Ok(OpenInit(attributes)) + } +} + +impl TryFrom> for OpenTry { + type Error = EventError; + + fn try_from(value: RawObject<'_>) -> Result { + let attributes = extract_attributes(&value, Self::event_type().as_str())?; + Ok(OpenTry(attributes)) + } +} + +impl TryFrom> for OpenAck { + type Error = EventError; + + fn try_from(value: RawObject<'_>) -> Result { + let attributes = extract_attributes(&value, Self::event_type().as_str())?; + Ok(OpenAck(attributes)) + } +} + +impl TryFrom> for OpenConfirm { + type Error = EventError; + + fn try_from(value: RawObject<'_>) -> Result { + let attributes = extract_attributes(&value, Self::event_type().as_str())?; + Ok(OpenConfirm(attributes)) + } +} diff --git a/crates/relayer/src/chain/cosmos/types/events/mod.rs b/crates/relayer/src/chain/cosmos/types/events/mod.rs index e96cafdfca..a07702ad2c 100644 --- a/crates/relayer/src/chain/cosmos/types/events/mod.rs +++ b/crates/relayer/src/chain/cosmos/types/events/mod.rs @@ -4,7 +4,9 @@ use tendermint::abci; use crate::event::{ibc_event_try_from_abci_event, IbcEventWithHeight}; pub mod channel; +pub mod connection; pub mod fee; +pub mod raw_object; pub fn from_tx_response_event(height: Height, event: &abci::Event) -> Option { ibc_event_try_from_abci_event(event) diff --git a/crates/relayer/src/chain/cosmos/types/events/raw_object.rs b/crates/relayer/src/chain/cosmos/types/events/raw_object.rs new file mode 100644 index 0000000000..670d4c96c1 --- /dev/null +++ b/crates/relayer/src/chain/cosmos/types/events/raw_object.rs @@ -0,0 +1,42 @@ +use alloc::collections::btree_map::BTreeMap as HashMap; + +use ibc_relayer_types::events::Error as EventError; +use ibc_relayer_types::Height; + +#[derive(Debug, Clone)] +pub struct RawObject<'a> { + pub height: Height, + pub action: String, + pub idx: usize, + pub events: &'a HashMap>, +} + +impl<'a> RawObject<'a> { + pub fn new( + height: Height, + action: String, + idx: usize, + events: &'a HashMap>, + ) -> RawObject<'a> { + RawObject { + height, + action, + idx, + events, + } + } +} + +pub fn extract_attribute(object: &RawObject<'_>, key: &str) -> Result { + let value = object + .events + .get(key) + .ok_or_else(|| EventError::missing_key(key.to_string()))?[object.idx] + .clone(); + + Ok(value) +} + +pub fn maybe_extract_attribute(object: &RawObject<'_>, key: &str) -> Option { + object.events.get(key).map(|tags| tags[object.idx].clone()) +} diff --git a/crates/relayer/src/chain/cosmos/types/gas.rs b/crates/relayer/src/chain/cosmos/types/gas.rs index e472eb91af..b8944d373f 100644 --- a/crates/relayer/src/chain/cosmos/types/gas.rs +++ b/crates/relayer/src/chain/cosmos/types/gas.rs @@ -48,6 +48,11 @@ pub fn max_gas_from_config(config: &CosmosSdkConfig) -> u64 { config.max_gas.unwrap_or(DEFAULT_MAX_GAS) } +/// The maximum amount of gas the relayer is willing to pay for a transaction +pub fn max_gas_from_config_opt(config: &CosmosSdkConfig) -> Option { + config.max_gas +} + /// The gas multiplier pub fn gas_multiplier_from_config(config: &CosmosSdkConfig) -> f64 { config.gas_multiplier.unwrap_or_default().to_f64() diff --git a/crates/relayer/src/chain/cosmos/version.rs b/crates/relayer/src/chain/cosmos/version.rs index 5db1b56961..d9c2b3b658 100644 --- a/crates/relayer/src/chain/cosmos/version.rs +++ b/crates/relayer/src/chain/cosmos/version.rs @@ -9,6 +9,8 @@ use tracing::trace; use ibc_proto::cosmos::base::tendermint::v1beta1::{Module, VersionInfo}; +use crate::chain::version::ConsensusVersion; + /// Specifies the SDK, IBC-go, and Tendermint modules path, as expected /// to appear in the application version information of a /// Cosmos-SDK network. @@ -27,12 +29,6 @@ const IBC_GO_MODULE_PREFIX: &str = "github.com/cosmos/ibc-go/v"; const TENDERMINT_MODULE_NAME: &str = "github.com/tendermint/tendermint"; const COMET_MODULE_NAME: &str = "github.com/cometbft/cometbft"; -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum ConsensusVersion { - Tendermint(semver::Version), - Comet(semver::Version), -} - /// Captures the version(s) specification of different modules of a network. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Specs { @@ -56,8 +52,7 @@ impl Display for Specs { .unwrap_or_else(|| "UNKNOWN".to_string()); let consensus = match self.consensus { - Some(ConsensusVersion::Tendermint(ref v)) => format!("Tendermint {v}"), - Some(ConsensusVersion::Comet(ref v)) => format!("CometBFT {v}"), + Some(ref v) => v.to_string(), None => "Tendermint: UNKNOWN, CometBFT: UNKNOWN".to_string(), }; diff --git a/crates/relayer/src/chain/cosmos/wait.rs b/crates/relayer/src/chain/cosmos/wait.rs index 9ff26b2cce..06d2b3f3b6 100644 --- a/crates/relayer/src/chain/cosmos/wait.rs +++ b/crates/relayer/src/chain/cosmos/wait.rs @@ -117,7 +117,7 @@ async fn update_tx_sync_result( Ok(()) } -fn all_tx_results_found(tx_sync_results: &[TxSyncResult]) -> bool { +pub fn all_tx_results_found(tx_sync_results: &[TxSyncResult]) -> bool { tx_sync_results .iter() .all(|r| matches!(r.status, TxStatus::ReceivedResponse)) diff --git a/crates/relayer/src/chain/endpoint.rs b/crates/relayer/src/chain/endpoint.rs index 387ff0b8d6..ff33a4b815 100644 --- a/crates/relayer/src/chain/endpoint.rs +++ b/crates/relayer/src/chain/endpoint.rs @@ -36,10 +36,10 @@ use tendermint_rpc::endpoint::broadcast::tx_sync::Response as TxResponse; use crate::account::Balance; use crate::chain::client::ClientSettings; -use crate::chain::cosmos::version::Specs; use crate::chain::handle::Subscription; use crate::chain::requests::*; use crate::chain::tracking::TrackedMsgs; +use crate::chain::version::Specs; use crate::client_state::{AnyClientState, IdentifiedAnyClientState}; use crate::config::ChainConfig; use crate::connection::ConnectionMsgType; diff --git a/crates/relayer/src/chain/handle.rs b/crates/relayer/src/chain/handle.rs index b4aae48916..bd356fb030 100644 --- a/crates/relayer/src/chain/handle.rs +++ b/crates/relayer/src/chain/handle.rs @@ -48,10 +48,10 @@ use crate::{ use super::{ client::ClientSettings, - cosmos::version::Specs, endpoint::{ChainStatus, HealthCheck}, requests::*, tracking::TrackedMsgs, + version::Specs, }; mod base; diff --git a/crates/relayer/src/chain/handle/base.rs b/crates/relayer/src/chain/handle/base.rs index 64d7d7d30e..00f54c6faf 100644 --- a/crates/relayer/src/chain/handle/base.rs +++ b/crates/relayer/src/chain/handle/base.rs @@ -34,8 +34,8 @@ use ibc_relayer_types::{ use crate::{ account::Balance, chain::{ - client::ClientSettings, cosmos::version::Specs, endpoint::ChainStatus, requests::*, - tracking::TrackedMsgs, + client::ClientSettings, endpoint::ChainStatus, requests::*, tracking::TrackedMsgs, + version::Specs, }, client_state::{AnyClientState, IdentifiedAnyClientState}, config::ChainConfig, diff --git a/crates/relayer/src/chain/handle/cache.rs b/crates/relayer/src/chain/handle/cache.rs index 403fee0bb2..0c692424e4 100644 --- a/crates/relayer/src/chain/handle/cache.rs +++ b/crates/relayer/src/chain/handle/cache.rs @@ -30,11 +30,11 @@ use ibc_relayer_types::Height; use crate::account::Balance; use crate::cache::{Cache, CacheStatus}; use crate::chain::client::ClientSettings; -use crate::chain::cosmos::version::Specs; use crate::chain::endpoint::{ChainStatus, HealthCheck}; use crate::chain::handle::{ChainHandle, ChainRequest, Subscription}; use crate::chain::requests::*; use crate::chain::tracking::TrackedMsgs; +use crate::chain::version::Specs; use crate::client_state::{AnyClientState, IdentifiedAnyClientState}; use crate::config::ChainConfig; use crate::connection::ConnectionMsgType; diff --git a/crates/relayer/src/chain/handle/counting.rs b/crates/relayer/src/chain/handle/counting.rs index 4fe7685a9e..886372ca4f 100644 --- a/crates/relayer/src/chain/handle/counting.rs +++ b/crates/relayer/src/chain/handle/counting.rs @@ -31,11 +31,11 @@ use ibc_relayer_types::Height; use crate::account::Balance; use crate::chain::client::ClientSettings; -use crate::chain::cosmos::version::Specs; use crate::chain::endpoint::{ChainStatus, HealthCheck}; use crate::chain::handle::{ChainHandle, ChainRequest, Subscription}; use crate::chain::requests::*; use crate::chain::tracking::TrackedMsgs; +use crate::chain::version::Specs; use crate::client_state::{AnyClientState, IdentifiedAnyClientState}; use crate::config::ChainConfig; use crate::connection::ConnectionMsgType; diff --git a/crates/relayer/src/chain/namada.rs b/crates/relayer/src/chain/namada.rs new file mode 100644 index 0000000000..4a362764d1 --- /dev/null +++ b/crates/relayer/src/chain/namada.rs @@ -0,0 +1,1408 @@ +use alloc::sync::Arc; +use core::str::FromStr; +use prost::Message; +use std::thread; +use tracing::debug; + +use core::time::Duration; + +use ibc_proto::ibc::applications::fee::v1::{ + QueryIncentivizedPacketRequest, QueryIncentivizedPacketResponse, +}; +use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; +use ibc_relayer_types::applications::ics28_ccv::msgs::{ConsumerChain, ConsumerId}; +use ibc_relayer_types::applications::ics31_icq::response::CrossChainQueryResponse; +use ibc_relayer_types::clients::ics07_tendermint::client_state::{ + AllowUpdate, ClientState as TmClientState, +}; +use ibc_relayer_types::clients::ics07_tendermint::consensus_state::ConsensusState as TmConsensusState; +use ibc_relayer_types::clients::ics07_tendermint::header::Header as TmHeader; +use ibc_relayer_types::core::ics02_client::events::UpdateClient; +use ibc_relayer_types::core::ics03_connection::connection::{ + ConnectionEnd, IdentifiedConnectionEnd, +}; +use ibc_relayer_types::core::ics04_channel::channel::{ChannelEnd, IdentifiedChannelEnd}; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics04_channel::upgrade::{ErrorReceipt, Upgrade}; +use ibc_relayer_types::core::ics23_commitment::commitment::CommitmentPrefix; +use ibc_relayer_types::core::ics23_commitment::merkle::MerkleProof; +use ibc_relayer_types::core::ics24_host::identifier::{ + ChainId, ChannelId, ClientId, ConnectionId, PortId, +}; +use ibc_relayer_types::core::ics24_host::path::{ + AcksPath, ChannelEndsPath, ChannelUpgradeErrorPath, ChannelUpgradePath, + ClientConsensusStatePath, ClientStatePath, CommitmentsPath, ConnectionsPath, ReceiptsPath, + SeqRecvsPath, +}; +use ibc_relayer_types::signer::Signer; +use ibc_relayer_types::Height as ICSHeight; +use namada_sdk::address::{Address, InternalAddress}; +use namada_sdk::borsh::BorshDeserialize; +use namada_sdk::ibc::core::host::types::path::UPGRADED_IBC_STATE; +use namada_sdk::ibc::{storage, COMMITMENT_PREFIX}; +use namada_sdk::io::NullIo; +use namada_sdk::io::{Client, NamadaIo}; +use namada_sdk::masp::fs::FsShieldedUtils; +use namada_sdk::parameters::{storage as param_storage, EpochDuration}; +use namada_sdk::proof_of_stake::storage_key as pos_storage_key; +use namada_sdk::proof_of_stake::OwnedPosParams; +use namada_sdk::state::ics23_specs::ibc_proof_specs; +use namada_sdk::state::Sha256Hasher; +use namada_sdk::storage::{Key, KeySeg, PrefixValue}; +use namada_sdk::token::storage_key::{balance_key, denom_key, is_any_token_balance_key}; +use namada_sdk::token::{Amount, DenominatedAmount, Denomination}; +use namada_sdk::wallet::Store; +use namada_sdk::wallet::Wallet; +use namada_sdk::{rpc, Namada, NamadaImpl}; +use namada_tendermint::block::Height as TmHeight; +use namada_tendermint::{node, Time}; +use namada_tendermint_rpc::client::CompatMode; +use namada_tendermint_rpc::endpoint::broadcast::tx_sync::Response; +use namada_tendermint_rpc::{HttpClient, Url}; +use tendermint_proto::Protobuf as TmProtobuf; +use tokio::runtime::Runtime as TokioRuntime; + +use crate::account::Balance; +use crate::chain::client::ClientSettings; +use crate::chain::cosmos::batch::response_to_tx_sync_result; +use crate::chain::cosmos::config::CosmosSdkConfig; +use crate::chain::endpoint::{ChainEndpoint, ChainStatus, HealthCheck}; +use crate::chain::handle::Subscription; +use crate::chain::requests::*; +use crate::chain::tracking::TrackedMsgs; +use crate::chain::version::{ConsensusVersion, Specs}; +use crate::client_state::{AnyClientState, IdentifiedAnyClientState}; +use crate::config::error::Error as ConfigError; +use crate::config::ChainConfig; +use crate::consensus_state::AnyConsensusState; +use crate::denom::DenomTrace; +use crate::error::Error; +use crate::event::source::{EventSource, TxEventSourceCmd}; +use crate::event::IbcEventWithHeight; +use crate::keyring::{KeyRing, NamadaKeyPair, SigningKeyPair}; +use crate::light_client::tendermint::LightClient as TmLightClient; +use crate::light_client::{LightClient, Verified}; +use crate::misbehaviour::MisbehaviourEvidence; + +use self::error::Error as NamadaError; + +pub mod error; +pub mod key; +mod query; +mod tx; +pub mod version; +pub mod wallet; + +pub struct NamadaChain { + /// Reuse CosmosSdkConfig for tendermint's light clients + config: CosmosSdkConfig, + /// Namada context + ctx: NamadaImpl, + compat_mode: CompatMode, + light_client: TmLightClient, + rt: Arc, + keybase: KeyRing, + tx_monitor_cmd: Option, +} + +impl NamadaChain { + fn init_event_source(&mut self) -> Result { + crate::time!( + "init_event_source", + { + "src_chain": self.config.id.to_string(), + } + ); + + use crate::config::EventSourceMode as Mode; + let http_client = tendermint_rpc::HttpClient::new(self.config.rpc_addr.clone()) + .map_err(|e| Error::rpc(self.config.rpc_addr.clone(), e))?; + let compat_mode = self + .compat_mode + .to_string() + .parse() + .map_err(|e| Error::rpc(self.config.rpc_addr.clone(), e))?; + let (event_source, monitor_tx) = match &self.config.event_source { + Mode::Push { url, batch_delay } => EventSource::websocket( + self.config.id.clone(), + url.clone(), + compat_mode, + *batch_delay, + self.rt.clone(), + ), + Mode::Pull { + interval, + max_retries, + } => EventSource::rpc( + self.config.id.clone(), + http_client, + *interval, + *max_retries, + self.rt.clone(), + ), + } + .map_err(Error::event_source)?; + + thread::spawn(move || event_source.run()); + + Ok(monitor_tx) + } + + fn get_unbonding_time(&self) -> Result { + let key = pos_storage_key::params_key(); + let (value, _) = self.query(key, QueryHeight::Latest, IncludeProof::No)?; + let pos_params = + OwnedPosParams::try_from_slice(&value[..]).map_err(NamadaError::borsh_decode)?; + + let key = param_storage::get_epoch_duration_storage_key(); + let (value, _) = self.query(key, QueryHeight::Latest, IncludeProof::No)?; + let epoch_duration = + EpochDuration::try_from_slice(&value[..]).map_err(NamadaError::borsh_decode)?; + let unbonding_period = pos_params.pipeline_len * epoch_duration.min_duration.0; + Ok(Duration::from_secs(unbonding_period)) + } + + fn get_latest_block_time(&self) -> Result { + let status = self + .rt + .block_on(Client::status(self.ctx.client())) + .map_err(|e| NamadaError::rpc(self.config.rpc_addr.clone(), e))?; + let time = + tendermint::Time::parse_from_rfc3339(&status.sync_info.latest_block_time.to_rfc3339()) + .expect("Time should be parsable"); + Ok(time) + } +} + +impl ChainEndpoint for NamadaChain { + type LightBlock = tendermint_light_client::types::LightBlock; + type Header = TmHeader; + type ConsensusState = TmConsensusState; + type ClientState = TmClientState; + type Time = Time; + type SigningKeyPair = NamadaKeyPair; + + fn id(&self) -> &ChainId { + &self.config.id + } + + fn config(&self) -> ChainConfig { + ChainConfig::Namada(self.config.clone()) + } + + fn bootstrap(config: ChainConfig, rt: Arc) -> Result { + #[allow(irrefutable_let_patterns)] + let ChainConfig::Namada(config) = config + else { + return Err(Error::config(ConfigError::wrong_type())); + }; + + let rpc_addr = Url::from_str(&config.rpc_addr.to_string()) + .map_err(|e| NamadaError::rpc(config.rpc_addr.clone(), e))?; + let mut rpc_client = + HttpClient::new(rpc_addr).map_err(|e| NamadaError::rpc(config.rpc_addr.clone(), e))?; + let node_info = rt.block_on(fetch_node_info(&rpc_client, &config))?; + let compat_mode = CompatMode::from_version(node_info.version) + .ok() + .or_else(|| { + config.compat_mode.map(|mode| { + mode.to_string() + .parse() + .expect("compatMode should be parsable") + }) + }) + .unwrap_or(CompatMode::V0_37); + rpc_client.set_compat_mode(compat_mode); + + let node_info = rt.block_on(fetch_node_info(&rpc_client, &config))?; + let node_id = tendermint_light_client_verifier::types::PeerId::new( + node_info + .id + .as_bytes() + .try_into() + .expect("node ID should be able to converted"), + ); + let light_client = TmLightClient::from_cosmos_sdk_config(&config, node_id)?; + + let keybase = + KeyRing::new_namada(config.key_store_type, &config.id, &config.key_store_folder) + .map_err(Error::key_base)?; + + let shielded_dir = dirs_next::home_dir() + .expect("No home directory") + .join(".hermes/shielded") + .join(config.id.to_string()); + std::fs::create_dir_all(&shielded_dir).map_err(Error::io)?; + let shielded_ctx = FsShieldedUtils::new(shielded_dir); + + let mut store = Store::default(); + let key = keybase + .get_key(&config.key_name) + .map_err(|e| Error::key_not_found(config.key_name.clone(), e))?; + store.insert_keypair::( + config.key_name.clone().into(), + key.secret_key, + None, + Some(key.address), + None, + true, + ); + let wallet = Wallet::new(wallet::NullWalletUtils, store); + + let native_token = rt + .block_on(rpc::query_native_token(&rpc_client)) + .map_err(NamadaError::namada)?; + + // overwrite the proof spec + let config = CosmosSdkConfig { + proof_specs: Some(ibc_proof_specs::().into()), + ..config + }; + + let ctx = NamadaImpl::native_new(rpc_client, wallet, shielded_ctx, NullIo, native_token); + + Ok(Self { + config, + ctx, + compat_mode, + light_client, + rt, + keybase, + tx_monitor_cmd: None, + }) + } + + fn shutdown(self) -> Result<(), Error> { + if let Some(monitor_tx) = self.tx_monitor_cmd { + monitor_tx.shutdown().map_err(Error::event_source)?; + } + + Ok(()) + } + + fn health_check(&mut self) -> Result { + self.rt + .block_on(Client::health(self.ctx.client())) + .map_err(|e| { + NamadaError::health_check_json_rpc( + self.config.id.clone(), + self.config.rpc_addr.to_string(), + "/health".to_string(), + e, + ) + })?; + + Ok(HealthCheck::Healthy) + } + + fn subscribe(&mut self) -> Result { + let tx_monitor_cmd = match &self.tx_monitor_cmd { + Some(tx_monitor_cmd) => tx_monitor_cmd, + None => { + let tx_monitor_cmd = self.init_event_source()?; + self.tx_monitor_cmd = Some(tx_monitor_cmd); + self.tx_monitor_cmd.as_ref().unwrap() + } + }; + + let subscription = tx_monitor_cmd.subscribe().map_err(Error::event_source)?; + Ok(subscription) + } + + fn keybase(&self) -> &KeyRing { + &self.keybase + } + + fn keybase_mut(&mut self) -> &mut KeyRing { + &mut self.keybase + } + + fn get_key(&self) -> Result { + self.keybase + .get_key(&self.config.key_name) + .map_err(|e| Error::key_not_found(self.config.key_name.clone(), e)) + } + + fn get_signer(&self) -> Result { + let key = self + .keybase + .get_key(&self.config.key_name) + .map_err(|e| Error::key_not_found(self.config.key_name.clone(), e))?; + Ok(Signer::from_str(&key.account()).expect("The key name shouldn't be empty")) + } + + fn version_specs(&self) -> Result { + let status = self + .rt + .block_on(Client::status(self.ctx.client())) + .map_err(|e| NamadaError::rpc(self.config.rpc_addr.clone(), e))?; + + let cometbft_version = status.node_info.version.to_string(); + let cometbft_version = cometbft_version + .parse() + .map_err(|_| NamadaError::version(cometbft_version))?; + + let moniker = &status.node_info.moniker; + let namada_version = moniker + .to_string() + .split_once('-') + .and_then(|(_, version)| version.strip_prefix('v')) + .ok_or_else(|| NamadaError::version(moniker.to_string()))? + .parse() + .map_err(|_| NamadaError::version(moniker.to_string()))?; + + let specs = version::Specs { + namada: Some(namada_version), + consensus: Some(ConsensusVersion::Comet(cometbft_version)), + }; + Ok(Specs::Namada(specs)) + } + + fn send_messages_and_wait_commit( + &mut self, + tracked_msgs: TrackedMsgs, + ) -> Result, Error> { + crate::time!("send_messages_and_wait_commit"); + + let proto_msgs = tracked_msgs.messages(); + if proto_msgs.is_empty() { + return Ok(vec![]); + } + let max_msg_num = self.config.max_msg_num.to_usize(); + let msg_chunks = proto_msgs.chunks(max_msg_num); + let mut tx_sync_results = vec![]; + for msg_chunk in msg_chunks { + let response = self.batch_txs(msg_chunk)?; + tx_sync_results.push(response_to_tx_sync_result( + &self.config.id, + msg_chunk.len(), + into_tm_response(response), + )); + if self.config.sequential_batch_tx { + self.wait_for_block_commits(&mut tx_sync_results)?; + } + } + if !self.config.sequential_batch_tx { + self.wait_for_block_commits(&mut tx_sync_results)?; + } + + let events: Vec = tx_sync_results + .into_iter() + .flat_map(|el| el.events) + .collect(); + let mut dedup_events = vec![]; + for event in events { + if !dedup_events.contains(&event) { + dedup_events.push(event); + } + } + + Ok(dedup_events) + } + + fn send_messages_and_wait_check_tx( + &mut self, + tracked_msgs: TrackedMsgs, + ) -> Result, Error> { + crate::time!("send_messages_and_wait_check_tx"); + + let proto_msgs = tracked_msgs.messages(); + if proto_msgs.is_empty() { + return Ok(vec![]); + } + + let max_msg_num = self.config.max_msg_num.to_usize(); + let msg_chunks = proto_msgs.chunks(max_msg_num); + let mut responses = vec![]; + for msg_chunk in msg_chunks { + let resp = self.batch_txs(msg_chunk)?; + let response = into_tm_response(resp); + if response.code.is_err() { + return Err(Error::send_tx(response.log)); + } + responses.push(response); + } + + Ok(responses) + } + + fn verify_header( + &mut self, + trusted: ICSHeight, + target: ICSHeight, + client_state: &AnyClientState, + ) -> Result { + crate::time!( + "verify_header", + { + "src_chain": self.config.id.to_string(), + } + ); + + let now = self.get_latest_block_time()?; + self.light_client + .verify(trusted, target, client_state, now) + .map(|v| v.target) + } + + fn check_misbehaviour( + &mut self, + update: &UpdateClient, + client_state: &AnyClientState, + ) -> Result, Error> { + crate::time!( + "check_misbehaviour", + { + "src_chain": self.config.id.to_string(), + } + ); + + let now = self.get_latest_block_time()?; + self.light_client + .detect_misbehaviour(update, client_state, now) + } + + fn query_balance(&self, key_name: Option<&str>, denom: Option<&str>) -> Result { + // Given key_name and denom should be raw Namada addresses + let default_owner = self.get_signer()?; + let owner = key_name.unwrap_or(default_owner.as_ref()); + let owner = + Address::decode(owner).map_err(|_| NamadaError::address_decode(owner.to_string()))?; + + let default_token = self.ctx.native_token().to_string(); + let denom = denom.unwrap_or(&default_token); + let token = + Address::decode(denom).map_err(|_| NamadaError::address_decode(denom.to_string()))?; + + let balance_key = balance_key(&token, &owner); + let (value, _) = self.query(balance_key, QueryHeight::Latest, IncludeProof::No)?; + if value.is_empty() { + return Ok(Balance { + amount: "0".to_string(), + denom: denom.to_string(), + }); + } + let amount = Amount::try_from_slice(&value[..]).map_err(NamadaError::borsh_decode)?; + let denom_key = denom_key(&token); + let (value, _) = self.query(denom_key, QueryHeight::Latest, IncludeProof::No)?; + let denominated_amount = if value.is_empty() { + DenominatedAmount::new(amount, 0.into()) + } else { + let token_denom = + Denomination::try_from_slice(&value[..]).map_err(NamadaError::borsh_decode)?; + DenominatedAmount::new(amount, token_denom) + }; + + Ok(Balance { + amount: denominated_amount.to_string(), + denom: denom.to_string(), + }) + } + + fn query_all_balances(&self, key_name: Option<&str>) -> Result, Error> { + let default_owner = self.get_signer()?; + let owner = key_name.unwrap_or(default_owner.as_ref()); + let owner = + Address::decode(owner).map_err(|_| NamadaError::address_decode(owner.to_string()))?; + + let mut balances = vec![]; + let prefix = Key::from(Address::Internal(InternalAddress::Multitoken).to_db_key()); + for PrefixValue { key, value } in self.query_prefix(prefix)? { + if let Some([token, bal_owner]) = is_any_token_balance_key(&key) { + if owner == *bal_owner { + let amount = + Amount::try_from_slice(&value[..]).map_err(NamadaError::borsh_decode)?; + let denom_key = denom_key(token); + let (value, _) = + self.query(denom_key, QueryHeight::Latest, IncludeProof::No)?; + let denominated_amount = if value.is_empty() { + DenominatedAmount::new(amount, 0.into()) + } else { + let namada_denom = Denomination::try_from_slice(&value[..]) + .map_err(NamadaError::borsh_decode)?; + DenominatedAmount::new(amount, namada_denom) + }; + let balance = Balance { + amount: denominated_amount.to_string(), + denom: token.to_string(), + }; + balances.push(balance); + } + } + } + Ok(balances) + } + + // Query the denom trace with "{IbcToken}" address which has a hashed denom. + fn query_denom_trace(&self, hash: String) -> Result { + let denom = self.query_denom(hash)?; + match denom.rsplit_once('/') { + Some((path, base_denom)) => Ok(DenomTrace { + path: path.to_string(), + base_denom: base_denom.to_string(), + }), + None => Err(Error::query(format!( + "The denom is not a PrefixedDenom: denom {}", + denom + ))), + } + } + + fn query_commitment_prefix(&self) -> Result { + crate::time!( + "query_commitment_prefix", + { + "src_chain": self.config.id.to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_commitment_prefix"); + + CommitmentPrefix::try_from(b"ibc".to_vec()).map_err(Error::ics23) + } + + fn query_application_status(&self) -> Result { + crate::time!( + "query_application_status", + { + "src_chain": self.config.id.to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_application_status"); + + let status = self + .rt + .block_on(Client::status(self.ctx.client())) + .map_err(|e| NamadaError::rpc(self.config.rpc_addr.clone(), e))?; + + if status.sync_info.catching_up { + return Err(Error::chain_not_caught_up( + self.config.rpc_addr.to_string(), + self.config.id.clone(), + )); + } + + let time = self.get_latest_block_time()?; + let height = ICSHeight::new( + ChainId::chain_version(status.node_info.network.as_str()), + u64::from(status.sync_info.latest_block_height), + ) + .map_err(Error::ics02)?; + + Ok(ChainStatus { + height, + timestamp: time.into(), + }) + } + + fn query_clients( + &self, + _request: QueryClientStatesRequest, + ) -> Result, Error> { + crate::time!( + "query_clients", + { + "src_chain": self.config.id.to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_clients"); + + let prefix = storage::ibc_key("clients").expect("the path should be parsable"); + let mut states = vec![]; + for prefix_value in self.query_prefix(prefix)? { + let PrefixValue { key, value } = prefix_value; + if key.to_string().ends_with("clientState") { + let client_id = + storage::client_id(&key).map_err(|e| Error::query(e.to_string()))?; + let client_id = ClientId::from_str(&client_id.to_string()) + .expect("ibc-rs ClientId should be parsable with the relayer-types one"); + let client_state = AnyClientState::decode_vec(&value).map_err(Error::decode)?; + states.push(IdentifiedAnyClientState::new(client_id, client_state)); + } + } + + Ok(states) + } + + fn query_client_state( + &self, + request: QueryClientStateRequest, + include_proof: IncludeProof, + ) -> Result<(AnyClientState, Option), Error> { + crate::time!( + "query_client_state", + { + "src_chain": self.config.id.to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_client_state"); + + let path = ClientStatePath(request.client_id); + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + let (value, proof) = self.query(key, request.height, include_proof)?; + let client_state = AnyClientState::decode_vec(&value).map_err(Error::decode)?; + + Ok((client_state, proof)) + } + + fn query_consensus_state( + &self, + request: QueryConsensusStateRequest, + include_proof: IncludeProof, + ) -> Result<(AnyConsensusState, Option), Error> { + crate::time!( + "query_consensus_state", + { + "src_chain": self.config.id.to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_consensus_state"); + + let path = ClientConsensusStatePath { + client_id: request.client_id, + epoch: request.consensus_height.revision_number(), + height: request.consensus_height.revision_height(), + }; + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + let (value, proof) = self.query(key, request.query_height, include_proof)?; + let consensus_state = AnyConsensusState::decode_vec(&value).map_err(Error::decode)?; + Ok((consensus_state, proof)) + } + + fn query_consensus_state_heights( + &self, + request: QueryConsensusStateHeightsRequest, + ) -> Result, Error> { + let prefix = storage::ibc_key(format!("clients/{}", request.client_id)) + .expect("the path should be parsable"); + let mut heights = vec![]; + for prefix_value in self.query_prefix(prefix)? { + let PrefixValue { key, value: _ } = prefix_value; + match storage::consensus_height(&key) { + Ok(h) => { + let height = ICSHeight::new(h.revision_number(), h.revision_height()) + .expect("ibc-rs height should be parsable with the relayer-types one"); + heights.push(height); + } + Err(_) => { + debug!("The key {key} is not for a consensus state"); + continue; + } + } + } + Ok(heights) + } + + fn query_upgraded_client_state( + &self, + request: QueryUpgradedClientStateRequest, + ) -> Result<(AnyClientState, MerkleProof), Error> { + crate::time!( + "query_upgraded_client_state", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_upgraded_client_state"); + + let height = request + .upgrade_height + .to_string() + .parse() + .expect("height conversion is infallible"); + let query_height = request + .upgrade_height + .decrement() + .map_err(|_| Error::invalid_height_no_source())?; + let key = namada_sdk::ibc::storage::upgraded_client_state_key(height); + let (value, proof) = + self.query(key, QueryHeight::Specific(query_height), IncludeProof::Yes)?; + if let Some(proof) = proof { + let client_state = AnyClientState::decode_vec(&value).map_err(Error::decode)?; + Ok((client_state, proof)) + } else { + Err(Error::queried_proof_not_found()) + } + } + + fn query_upgraded_consensus_state( + &self, + request: QueryUpgradedConsensusStateRequest, + ) -> Result<(AnyConsensusState, MerkleProof), Error> { + crate::time!( + "query_upgraded_consensus_state", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_upgraded_consensus_state"); + + let height = request + .upgrade_height + .to_string() + .parse() + .expect("height conversion is infallible"); + let query_height = request + .upgrade_height + .decrement() + .map_err(|_| Error::invalid_height_no_source())?; + let key = namada_sdk::ibc::storage::upgraded_consensus_state_key(height); + let (value, proof) = + self.query(key, QueryHeight::Specific(query_height), IncludeProof::Yes)?; + if let Some(proof) = proof { + let client_state = AnyConsensusState::decode_vec(&value).map_err(Error::decode)?; + Ok((client_state, proof)) + } else { + Err(Error::queried_proof_not_found()) + } + } + + fn query_connections( + &self, + _request: QueryConnectionsRequest, + ) -> Result, Error> { + crate::time!( + "query_connections", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_connections"); + + let prefix = storage::ibc_key("connections").expect("the path should be parsable"); + let mut connections = vec![]; + for prefix_value in self.query_prefix(prefix)? { + let PrefixValue { key, value } = prefix_value; + // "connections/counter" should be skipped + if key == storage::connection_counter_key() { + continue; + } + let conn_id = storage::connection_id(&key).map_err(|e| Error::query(e.to_string()))?; + let connection_id = conn_id + .as_str() + .parse() + .expect("The connection ID should be parsable"); + let connection = ConnectionEnd::decode_vec(&value).map_err(Error::decode)?; + connections.push(IdentifiedConnectionEnd::new(connection_id, connection)); + } + + Ok(connections) + } + + fn query_client_connections( + &self, + request: QueryClientConnectionsRequest, + ) -> Result, Error> { + crate::time!( + "query_client_connections", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_client_connections"); + + let query_request = QueryConnectionsRequest { pagination: None }; + let connections = self.query_connections(query_request)?; + let ids = connections + .iter() + .filter(|c| *c.connection_end.client_id() == request.client_id) + .map(|c| c.connection_id.clone()) + .collect(); + Ok(ids) + } + + fn query_connection( + &self, + request: QueryConnectionRequest, + include_proof: IncludeProof, + ) -> Result<(ConnectionEnd, Option), Error> { + crate::time!( + "query_connection", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_connection"); + + let path = ConnectionsPath(request.connection_id); + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + let (value, proof) = self.query(key, request.height, include_proof)?; + let connection_end = ConnectionEnd::decode_vec(&value).map_err(Error::decode)?; + Ok((connection_end, proof)) + } + + fn query_connection_channels( + &self, + request: QueryConnectionChannelsRequest, + ) -> Result, Error> { + crate::time!( + "query_connection_channels", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_connection_channels"); + + let hops = vec![request.connection_id]; + let query_request = QueryChannelsRequest { pagination: None }; + let channels = self + .query_channels(query_request)? + .into_iter() + .filter(|c| c.channel_end.connection_hops_matches(&hops)) + .collect(); + + Ok(channels) + } + + fn query_channels( + &self, + _request: QueryChannelsRequest, + ) -> Result, Error> { + crate::time!( + "query_channels", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_channels"); + + let prefix = storage::ibc_key("channelEnds").expect("the path should be parsable"); + let mut channels = vec![]; + for prefix_value in self.query_prefix(prefix)? { + let PrefixValue { key, value } = prefix_value; + // "channelEnds/counter" should be skipped + if key == storage::channel_counter_key() { + continue; + } + let (port_id, channel_id) = + storage::port_channel_id(&key).map_err(|e| Error::query(e.to_string()))?; + let port_id = port_id + .as_ref() + .parse() + .expect("ibc-rs PortId should be parsable with the relayer-types one"); + let channel_id = channel_id + .as_ref() + .parse() + .expect("ibc-rs ChannelId should be parsable with the relayer-types one"); + let channel = ChannelEnd::decode_vec(&value).map_err(Error::decode)?; + channels.push(IdentifiedChannelEnd::new(port_id, channel_id, channel)) + } + + Ok(channels) + } + + fn query_channel( + &self, + request: QueryChannelRequest, + include_proof: IncludeProof, + ) -> Result<(ChannelEnd, Option), Error> { + crate::time!( + "query_channel", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_channel"); + + let path = ChannelEndsPath(request.port_id, request.channel_id); + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + let (value, proof) = self.query(key, request.height, include_proof)?; + let channel_end = ChannelEnd::decode_vec(&value).map_err(Error::decode)?; + Ok((channel_end, proof)) + } + + fn query_channel_client_state( + &self, + request: QueryChannelClientStateRequest, + ) -> Result, Error> { + crate::time!( + "query_channel_client_state", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_channel_client_state"); + + let request = QueryChannelRequest { + port_id: request.port_id, + channel_id: request.channel_id, + height: QueryHeight::Latest, + }; + let (channel_end, _) = self.query_channel(request, IncludeProof::No)?; + let connection_id = channel_end + .connection_hops() + .first() + .ok_or_else(|| Error::query("no connection ID in the channel end".to_string()))? + .clone(); + let request = QueryConnectionRequest { + connection_id, + height: QueryHeight::Latest, + }; + let (connection_end, _) = self.query_connection(request, IncludeProof::No)?; + let client_id = connection_end.client_id().clone(); + let request = QueryClientStateRequest { + client_id: client_id.clone(), + height: QueryHeight::Latest, + }; + let (client_state, _) = self.query_client_state(request, IncludeProof::No)?; + + Ok(Some(IdentifiedAnyClientState { + client_id, + client_state, + })) + } + + fn query_packet_commitment( + &self, + request: QueryPacketCommitmentRequest, + include_proof: IncludeProof, + ) -> Result<(Vec, Option), Error> { + let path = CommitmentsPath { + port_id: request.port_id, + channel_id: request.channel_id, + sequence: request.sequence, + }; + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + self.query(key, request.height, include_proof) + } + + fn query_packet_commitments( + &self, + request: QueryPacketCommitmentsRequest, + ) -> Result<(Vec, ICSHeight), Error> { + crate::time!( + "query_packet_commitments", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_packet_commitments"); + + let path = format!( + "commitments/ports/{}/channels/{}/sequences", + request.port_id, request.channel_id + ); + let prefix = storage::ibc_key(path).expect("the path should be parsable"); + let mut sequences = vec![]; + for prefix_value in self.query_prefix(prefix)? { + let PrefixValue { key, value: _ } = prefix_value; + let (_, _, sequence) = + storage::port_channel_sequence_id(&key).map_err(|e| Error::query(e.to_string()))?; + let sequence = u64::from(sequence).into(); + sequences.push(sequence); + } + + // NOTE the height might be mismatched with the previous query + let status = self.query_application_status()?; + + Ok((sequences, status.height)) + } + + fn query_packet_receipt( + &self, + request: QueryPacketReceiptRequest, + include_proof: IncludeProof, + ) -> Result<(Vec, Option), Error> { + let path = ReceiptsPath { + port_id: request.port_id, + channel_id: request.channel_id, + sequence: request.sequence, + }; + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + self.query(key, request.height, include_proof) + } + + fn query_unreceived_packets( + &self, + request: QueryUnreceivedPacketsRequest, + ) -> Result, Error> { + crate::time!( + "query_unreceived_packets", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_unreceived_packets"); + + let path = format!( + "receipts/ports/{}/channels/{}/sequences", + request.port_id, request.channel_id + ); + let prefix = storage::ibc_key(path).expect("the path should be parsable"); + let mut received_seqs = vec![]; + for prefix_value in self.query_prefix(prefix)? { + let (_, _, sequence) = storage::port_channel_sequence_id(&prefix_value.key) + .map_err(|e| Error::query(e.to_string()))?; + let sequence = u64::from(sequence).into(); + received_seqs.push(sequence) + } + + let unreceived_seqs = request + .packet_commitment_sequences + .into_iter() + .filter(|seq| !received_seqs.contains(seq)) + .collect(); + + Ok(unreceived_seqs) + } + + fn query_packet_acknowledgement( + &self, + request: QueryPacketAcknowledgementRequest, + include_proof: IncludeProof, + ) -> Result<(Vec, Option), Error> { + let path = AcksPath { + port_id: request.port_id, + channel_id: request.channel_id, + sequence: request.sequence, + }; + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + self.query(key, request.height, include_proof) + } + + fn query_packet_acknowledgements( + &self, + request: QueryPacketAcknowledgementsRequest, + ) -> Result<(Vec, ICSHeight), Error> { + crate::time!( + "query_packet_acknowledgements", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_packet_acknowledgements"); + + let path = format!( + "acks/ports/{}/channels/{}/sequences", + request.port_id, request.channel_id + ); + let prefix = storage::ibc_key(path).expect("the path should be parsable"); + let mut sequences = vec![]; + for prefix_value in self.query_prefix(prefix)? { + let PrefixValue { key, value: _ } = prefix_value; + let (_, _, sequence) = + storage::port_channel_sequence_id(&key).map_err(|e| Error::query(e.to_string()))?; + let sequence = u64::from(sequence).into(); + if request.packet_commitment_sequences.contains(&sequence) { + sequences.push(sequence); + } + } + + // NOTE the height might be mismatched with the previous query + let status = self.query_application_status()?; + Ok((sequences, status.height)) + } + + fn query_unreceived_acknowledgements( + &self, + request: QueryUnreceivedAcksRequest, + ) -> Result, Error> { + crate::time!( + "query_unreceived_acknowledgements", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_unreceived_acknowledgements"); + + let path = format!( + "commitments/ports/{}/channels/{}/sequences", + request.port_id, request.channel_id + ); + let prefix = storage::ibc_key(path).expect("the path should be parsable"); + let mut unreceived_seqs = vec![]; + for prefix_value in self.query_prefix(prefix)? { + let PrefixValue { key, value: _ } = prefix_value; + let (_, _, sequence) = + storage::port_channel_sequence_id(&key).map_err(|e| Error::query(e.to_string()))?; + let sequence = u64::from(sequence).into(); + if request.packet_ack_sequences.contains(&sequence) { + unreceived_seqs.push(sequence); + } + } + Ok(unreceived_seqs) + } + + fn query_next_sequence_receive( + &self, + request: QueryNextSequenceReceiveRequest, + include_proof: IncludeProof, + ) -> Result<(Sequence, Option), Error> { + crate::time!( + "query_next_sequence_receive", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_next_sequence_receive"); + + let path = SeqRecvsPath(request.port_id, request.channel_id); + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + let (value, proof) = self.query(key, request.height, include_proof)?; + + // As ibc-go, the sequence index is encoded with big-endian + let index: [u8; 8] = value + .try_into() + .map_err(|_| Error::query("Encoding u64 failed".to_owned()))?; + let sequence = u64::from_be_bytes(index).into(); + + Ok((sequence, proof)) + } + + fn query_txs(&self, request: QueryTxRequest) -> Result, Error> { + crate::time!("query_txs", + { + "src_chain": self.id().to_string(), + }); + crate::telemetry!(query, self.id(), "query_txs"); + + match request { + QueryTxRequest::Client(request) => { + crate::time!("query_txs: single client update event"); + match self.query_update_event(&request)? { + Some(event) => Ok(vec![event]), + None => Ok(vec![]), + } + } + QueryTxRequest::Transaction(tx) => { + let tm_hash = namada_tendermint::Hash::from_bytes( + namada_tendermint::hash::Algorithm::Sha256, + tx.0.as_bytes(), + ) + .expect("hash should be converted"); + + self.query_tx_events(&tm_hash) + } + } + } + + fn query_packet_events( + &self, + request: QueryPacketEventDataRequest, + ) -> Result, Error> { + crate::time!( + "query_packet_events", + { + "src_chain": self.id().to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_packet_events"); + self.query_packet_events_from_block(&request) + } + + fn query_host_consensus_state( + &self, + request: QueryHostConsensusStateRequest, + ) -> Result { + let height = match request.height { + QueryHeight::Latest => TmHeight::from(0u32), + QueryHeight::Specific(ibc_height) => TmHeight::try_from(ibc_height.revision_height()) + .map_err(NamadaError::invalid_height)?, + }; + + let rpc_call = match height.value() { + 0 => Client::latest_block(self.ctx.client()), + _ => Client::block(self.ctx.client(), height), + }; + let response = self + .rt + .block_on(rpc_call) + .map_err(|e| NamadaError::rpc(self.config.rpc_addr.clone(), e))?; + let raw_header = namada_tendermint_proto::v0_37::types::Header::from(response.block.header); + let encoded_header = raw_header.encode_to_vec(); + let raw_header: tendermint_proto::v0_37::types::Header = + prost::Message::decode(&encoded_header[..]) + .map_err(|e| Error::protobuf_decode("TmBlockHeader".to_string(), e))?; + let header: tendermint::block::Header = + raw_header.try_into().expect("header should be converted"); + Ok(Self::ConsensusState::from(header)) + } + + fn build_client_state( + &self, + height: ICSHeight, + settings: ClientSettings, + ) -> Result { + let ClientSettings::Tendermint(settings) = settings; + let unbonding_period = self.get_unbonding_time()?; + let trusting_period = settings.trusting_period.unwrap_or_else(|| { + self.config + .trusting_period + .unwrap_or(2 * unbonding_period / 3) + }); + TmClientState::new( + self.id().clone(), + settings.trust_threshold, + trusting_period, + unbonding_period, + settings.max_clock_drift, + height, + self.config + .proof_specs + .clone() + .expect("ProofSpecs should be set"), + vec![ + COMMITMENT_PREFIX.to_string(), + UPGRADED_IBC_STATE.to_string(), + ], + AllowUpdate { + after_expiry: true, + after_misbehaviour: true, + }, + ) + .map_err(Error::ics07) + } + + fn build_consensus_state( + &self, + light_block: Self::LightBlock, + ) -> Result { + crate::time!( + "build_consensus_state", + { + "src_chain": self.id().to_string(), + } + ); + + Ok(TmConsensusState::from(light_block.signed_header.header)) + } + + fn build_header( + &mut self, + trusted_height: ICSHeight, + target_height: ICSHeight, + client_state: &AnyClientState, + ) -> Result<(Self::Header, Vec), Error> { + crate::time!( + "build_header", + { + "src_chain": self.id().to_string(), + } + ); + + let now = self.get_latest_block_time()?; + // Get the light block at target_height from chain. + let Verified { target, supporting } = self.light_client.header_and_minimal_set( + trusted_height, + target_height, + client_state, + now, + )?; + + Ok((target, supporting)) + } + + fn maybe_register_counterparty_payee( + &mut self, + _channel_id: &ChannelId, + _port_id: &PortId, + _counterparty_payee: &Signer, + ) -> Result<(), Error> { + // not supported + unimplemented!() + } + + fn cross_chain_query( + &self, + _requests: Vec, + ) -> Result, Error> { + // not supported + unimplemented!() + } + + fn query_incentivized_packet( + &self, + _request: QueryIncentivizedPacketRequest, + ) -> Result { + // not supported + unimplemented!() + } + + fn query_consumer_chains(&self) -> Result, Error> { + // not supported + unimplemented!() + } + + fn query_upgrade( + &self, + request: QueryUpgradeRequest, + height: ICSHeight, + include_proof: IncludeProof, + ) -> Result<(Upgrade, Option), Error> { + let port_id = PortId::from_str(&request.port_id) + .map_err(|_| Error::invalid_port_string(request.port_id))?; + let channel_id = ChannelId::from_str(&request.channel_id) + .map_err(|_| Error::invalid_channel_string(request.channel_id))?; + let path = ChannelUpgradePath { + port_id, + channel_id, + }; + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + let (value, proof) = self.query(key, QueryHeight::Specific(height), include_proof)?; + + let upgrade = Upgrade::decode_vec(&value).map_err(Error::decode)?; + + Ok((upgrade, proof)) + } + + fn query_upgrade_error( + &self, + request: QueryUpgradeErrorRequest, + height: ICSHeight, + include_proof: IncludeProof, + ) -> Result<(ErrorReceipt, Option), Error> { + let port_id = PortId::from_str(&request.port_id) + .map_err(|_| Error::invalid_port_string(request.port_id))?; + let channel_id = ChannelId::from_str(&request.channel_id) + .map_err(|_| Error::invalid_channel_string(request.channel_id))?; + let path = ChannelUpgradeErrorPath { + port_id, + channel_id, + }; + let key = storage::ibc_key(path.to_string()).expect("the path should be parsable"); + let (value, proof) = self.query(key, QueryHeight::Specific(height), include_proof)?; + + let error_receipt = ErrorReceipt::decode_vec(&value).map_err(Error::decode)?; + + Ok((error_receipt, proof)) + } + + fn query_ccv_consumer_id(&self, _client_id: ClientId) -> Result { + // not supported + unimplemented!() + } +} + +/// Fetch the node info +async fn fetch_node_info( + rpc_client: &HttpClient, + config: &CosmosSdkConfig, +) -> Result { + crate::time!("fetch_node_info", + { + "src_chain": config.id.to_string(), + }); + + Client::status(rpc_client) + .await + .map(|s| s.node_info) + .map_err(|e| NamadaError::rpc(config.rpc_addr.clone(), e)) +} + +fn into_tm_response(response: Response) -> tendermint_rpc::endpoint::broadcast::tx_sync::Response { + let code = match response.code { + namada_tendermint::abci::Code::Ok => tendermint::abci::Code::Ok, + namada_tendermint::abci::Code::Err(c) => tendermint::abci::Code::Err(c), + }; + let hash = tendermint::Hash::from_bytes( + tendermint::hash::Algorithm::Sha256, + response.hash.as_bytes(), + ) + .expect("hash should be converted"); + tendermint_rpc::endpoint::broadcast::tx_sync::Response { + codespace: response.codespace, + code, + data: response.data, + log: response.log, + hash, + } +} diff --git a/crates/relayer/src/chain/namada/error.rs b/crates/relayer/src/chain/namada/error.rs new file mode 100644 index 0000000000..aa938dd154 --- /dev/null +++ b/crates/relayer/src/chain/namada/error.rs @@ -0,0 +1,71 @@ +use flex_error::{define_error, DisplayOnly, TraceError}; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; +use namada_tendermint::Error as TendermintError; +use namada_tendermint_proto::Error as TendermintProtoError; +use namada_tendermint_rpc::Error as TendermintRpcError; + +define_error! { + Error { + AddressDecode + { raw: String } + |e| { format!("Namada address decoding failed for {}", e.raw) }, + + DenomNotFound + { denom: String } + |e| { format!("No denom for {}", e.denom) }, + + Namada + [ TraceError ] + |_| { "Namada error" }, + + Rpc + { url: tendermint_rpc::Url } + [ TendermintRpcError ] + |e| { format!("RPC error to endpoint {}", e.url) }, + + HealthCheckJsonRpc + { + chain_id: ChainId, + address: String, + endpoint: String, + } + [ DisplayOnly ] + |e| { + format!("health check failed for endpoint {0} on the JSON-RPC interface of chain {1}:{2}", + e.endpoint, e.chain_id, e.address) + }, + + InvalidHeight + [ TendermintError ] + |_| { "invalid height" }, + + Decode + [ TendermintProtoError ] + |_| { "error decoding protobuf" }, + + Query + [ TraceError ] + |_| { "Query error" }, + + BorshDecode + [ TraceError ] + |_| { "borsh decoding failed" }, + + DryRun + { tx_result: namada_sdk::tx::data::TxResult } + |e| { format!("Dry run to simulate a transaction failed: {:?}", e.tx_result) }, + + Upgrade + |_| { "Namada doesn't support `MsgIbcSoftwareUpgrade` and `UpgradeProposal`" }, + + Version + { version: String } + |e| { format!("Parsing the version string failed: {}", e.version) }, + } +} + +impl From for crate::error::Error { + fn from(error: Error) -> Self { + Self::namada(error) + } +} diff --git a/crates/relayer/src/chain/namada/key.rs b/crates/relayer/src/chain/namada/key.rs new file mode 100644 index 0000000000..9f8486dc52 --- /dev/null +++ b/crates/relayer/src/chain/namada/key.rs @@ -0,0 +1,47 @@ +use core::any::Any; + +use namada_sdk::address::Address; +use namada_sdk::key::common::SecretKey; + +use crate::config::AddressType; +use crate::keyring::errors::Error; +use crate::keyring::{KeyFile, KeyType, SigningKeyPair}; +use hdpath::StandardHDPath; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NamadaKeyPair { + pub alias: String, + pub address: Address, + pub secret_key: SecretKey, +} + +impl SigningKeyPair for NamadaKeyPair { + const KEY_TYPE: KeyType = KeyType::Secp256k1; + type KeyFile = KeyFile; + + fn from_key_file(_key_file: Self::KeyFile, _hd_path: &StandardHDPath) -> Result { + unimplemented!("Namada key can't be restored from a KeyFile") + } + + fn from_mnemonic( + _mnemonic: &str, + _hd_path: &StandardHDPath, + _address_type: &AddressType, + _account_prefix: &str, + ) -> Result { + unimplemented!("Namada key can't be restored from a KeyFile") + } + + fn account(&self) -> String { + self.address.to_string() + } + + fn sign(&self, _message: &[u8]) -> Result, Error> { + unimplemented!("don't use this to sign a Namada transaction") + } + + fn as_any(&self) -> &dyn Any { + self + } +} diff --git a/crates/relayer/src/chain/namada/query.rs b/crates/relayer/src/chain/namada/query.rs new file mode 100644 index 0000000000..8953ac80a3 --- /dev/null +++ b/crates/relayer/src/chain/namada/query.rs @@ -0,0 +1,346 @@ +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics23_commitment::merkle::convert_tm_to_ics_merkle_proof; +use ibc_relayer_types::core::ics23_commitment::merkle::MerkleProof; +use ibc_relayer_types::events::IbcEvent; +use ibc_relayer_types::Height as ICSHeight; +use namada_sdk::address::{Address, InternalAddress}; +use namada_sdk::borsh::BorshDeserialize; +use namada_sdk::events::extend::Height as HeightAttr; +use namada_sdk::events::Event as NamadaEvent; +use namada_sdk::ibc::storage::{ibc_trace_key_prefix, is_ibc_trace_key}; +use namada_sdk::io::Client; +use namada_sdk::io::NamadaIo; +use namada_sdk::queries::RPC; +use namada_sdk::rpc; +use namada_sdk::storage::{BlockHeight, Epoch, Key, PrefixValue}; +use namada_sdk::tx::data::ResultCode; +use namada_sdk::tx::event::{Batch as BatchAttr, Code as CodeAttr}; +use namada_tendermint::block::Height as TmHeight; +use namada_tendermint::merkle::proof::ProofOps; +use namada_tendermint::Hash as TmHash; +use namada_tendermint_proto::v0_37::abci::Event as TmEvent; + +use crate::chain::endpoint::ChainEndpoint; +use crate::chain::requests::{ + IncludeProof, QueryClientEventRequest, QueryHeight, QueryPacketEventDataRequest, +}; +use crate::error::Error; +use crate::event::{ibc_event_try_from_abci_event, IbcEventWithHeight}; + +use super::error::Error as NamadaError; +use super::NamadaChain; + +impl NamadaChain { + pub fn query( + &self, + key: Key, + height: QueryHeight, + include_proof: IncludeProof, + ) -> Result<(Vec, Option), Error> { + let height = match height { + QueryHeight::Latest => None, + QueryHeight::Specific(h) => Some(BlockHeight(h.revision_height())), + }; + let is_proven = matches!(include_proof, IncludeProof::Yes); + let (value, proof) = self + .rt + .block_on(rpc::query_storage_value_bytes( + self.ctx.client(), + &key, + height, + is_proven, + )) + .map_err(NamadaError::namada)?; + + let proof = if is_proven { + let proof_ops = proof.ok_or_else(Error::empty_response_proof)?; + let tm_proof_ops = into_tm_proof(proof_ops); + let proof = convert_tm_to_ics_merkle_proof(&tm_proof_ops).map_err(Error::ics23)?; + Some(proof) + } else { + None + }; + // return an empty data for non-existence proof + Ok((value.unwrap_or_default(), proof)) + } + + pub fn query_prefix(&self, prefix: Key) -> Result, Error> { + let response = self + .rt + .block_on( + // We can't use rpc::query_storage_prefix` because we need byte data + RPC.shell() + .storage_prefix(self.ctx.client(), None, None, false, &prefix), + ) + .map_err(NamadaError::query)?; + Ok(response.data) + } + + pub fn query_epoch(&self) -> Result { + self.rt + .block_on(rpc::query_epoch(self.ctx.client())) + .map_err(|e| Error::namada(NamadaError::namada(e))) + } + + pub fn query_update_event( + &self, + request: &QueryClientEventRequest, + ) -> Result, Error> { + let height = BlockHeight(request.consensus_height.revision_height()); + let event = self + .rt + .block_on(RPC.shell().ibc_client_update( + self.ctx.client(), + &request.client_id.as_str().parse().unwrap(), + &height, + )) + .map_err(NamadaError::query)?; + match event { + Some(event) => { + let h = event + .read_attribute::() + .map_err(|_| Error::invalid_height_no_source())?; + let height = ICSHeight::new(self.config.id.version(), h.0) + .map_err(|_| Error::invalid_height_no_source())?; + let pb_abci_event = TmEvent::from(event); + let abci_event = into_abci_event(pb_abci_event); + match ibc_event_try_from_abci_event(&abci_event) { + Ok(event) => Ok(Some(IbcEventWithHeight { event, height })), + // non IBC event + Err(_) => Ok(None), + } + } + None => Ok(None), + } + } + + /// Get all IBC events when the tx has been applied + pub fn query_tx_events(&self, tx_hash: &TmHash) -> Result, Error> { + match self.query_applied_event(tx_hash)? { + Some(applied) => { + let h = applied + .read_attribute::() + .map_err(|_| Error::invalid_height_no_source())?; + let height = ICSHeight::new(self.config.id.version(), h.0) + .map_err(|_| Error::invalid_height_no_source())?; + // Check if the tx is valid + let tx_result = applied + .read_attribute::>() + .expect("The batch attribute should exist"); + let code = applied + .read_attribute::() + .expect("The code attribute should exist"); + if code != ResultCode::Ok { + return Ok(vec![IbcEventWithHeight::new( + IbcEvent::ChainError(format!( + "The transaction was invalid: TxResult {tx_result}", + )), + height, + )]); + } + let events = tx_result.iter().filter_map(|(_, r)| { + r.as_ref().map(|batched_tx_result| { + // Get IBC events when the transaction was accepted + if batched_tx_result.is_accepted() { + batched_tx_result.events.iter().filter_map(|event| { + let pb_abci_event = TmEvent::from(event.clone()); + let abci_event = into_abci_event(pb_abci_event); + ibc_event_try_from_abci_event(&abci_event).ok() + }).map(|ibc_event| IbcEventWithHeight::new(ibc_event, height)).collect() + } else { + vec![IbcEventWithHeight::new( + IbcEvent::ChainError(format!( + "The transaction was invalid: BatchedTxResult {batched_tx_result}", + )), + height, + )] + } + }).ok() + }).flatten().collect(); + Ok(events) + } + None => Ok(vec![]), + } + } + + fn query_applied_event(&self, tx_hash: &TmHash) -> Result, Error> { + self.rt + .block_on(RPC.shell().applied( + self.ctx.client(), + &tx_hash.as_ref().try_into().expect("Invalid tx hash"), + )) + .map_err(|e| Error::namada(NamadaError::query(e))) + } + + /// Get IBC packet events + pub fn query_packet_events_from_block( + &self, + request: &QueryPacketEventDataRequest, + ) -> Result, Error> { + let mut block_events = vec![]; + for seq in &request.sequences { + if let Some(response_height) = self.query_packet_height(request, *seq)? { + if let QueryHeight::Specific(query_height) = request.height.get() { + if response_height > query_height { + continue; + } + } + let events = self.query_events(response_height)?; + let mut packet_events = events + .into_iter() + .filter(|e| { + let packet = match &e.event { + IbcEvent::SendPacket(send_event) => &send_event.packet, + IbcEvent::WriteAcknowledgement(write_ack_event) => { + &write_ack_event.packet + } + _ => return false, + }; + !block_events.contains(e) + && packet.source_port == request.source_port_id + && packet.source_channel == request.source_channel_id + && packet.destination_port == request.destination_port_id + && packet.destination_channel == request.destination_channel_id + && packet.sequence == *seq + }) + .collect(); + block_events.append(&mut packet_events); + } + } + Ok(block_events) + } + + /// Get the height at which the packet event has been emitted + fn query_packet_height( + &self, + request: &QueryPacketEventDataRequest, + sequence: Sequence, + ) -> Result, Error> { + match self + .rt + .block_on( + RPC.shell().ibc_packet( + self.ctx.client(), + &request + .event_id + .as_str() + .parse() + .expect("invalid event type"), + &request + .source_port_id + .as_str() + .parse() + .expect("PortId should be parsable"), + &request + .source_channel_id + .as_str() + .parse() + .expect("ChannelId should be parsable"), + &request + .destination_port_id + .as_str() + .parse() + .expect("PortId should be parsable"), + &request + .destination_channel_id + .as_str() + .parse() + .expect("ChannelId should be parsable"), + &u64::from(sequence).into(), + ), + ) + .map_err(NamadaError::query)? + { + Some(event) => { + let h = event + .read_attribute::() + .map_err(|_| Error::invalid_height_no_source())?; + let height = ICSHeight::new(self.config.id.version(), h.0) + .map_err(|_| Error::invalid_height_no_source())?; + Ok(Some(height)) + } + None => Ok(None), + } + } + + /// Get IBC events at the given height + fn query_events(&self, height: ICSHeight) -> Result, Error> { + crate::time!( + "query_blocks: query block packet events", + { + "src_chain": self.config.id.to_string(), + } + ); + crate::telemetry!(query, self.id(), "query_block"); + + let tm_height = TmHeight::try_from(height.revision_height()) + .map_err(|_| Error::invalid_height_no_source())?; + let response = self + .rt + .block_on(Client::block_results(self.ctx.client(), tm_height)) + .map_err(|e| NamadaError::rpc(self.config.rpc_addr.clone(), e))?; + + let events = response + .end_block_events + .ok_or_else(|| Error::query("No transaction result was found".to_string()))?; + let mut ibc_events = vec![]; + for event in events { + let pb_abci_event = TmEvent::from(event); + let abci_event = into_abci_event(pb_abci_event); + if let Ok(ibc_event) = ibc_event_try_from_abci_event(&abci_event) { + ibc_events.push(IbcEventWithHeight::new(ibc_event, height)) + } + } + Ok(ibc_events) + } + + /// Get IBC denom + pub fn query_denom(&self, raw_addr: String) -> Result { + let token = Address::decode(&raw_addr) + .map_err(|_| NamadaError::address_decode(raw_addr.to_string()))?; + let hash = match &token { + Address::Internal(InternalAddress::IbcToken(hash)) => hash.to_string(), + _ => return Err(NamadaError::denom_not_found(raw_addr).into()), + }; + + let prefix = ibc_trace_key_prefix(None); + let pairs = self.query_prefix(prefix)?; + let pair = pairs + .iter() + .find(|PrefixValue { key, value: _ }| { + if let Some((_, token_hash)) = is_ibc_trace_key(key) { + token_hash == *hash + } else { + false + } + }) + .ok_or(NamadaError::denom_not_found(raw_addr))?; + + String::try_from_slice(&pair.value).map_err(|e| Error::namada(NamadaError::borsh_decode(e))) + } +} + +fn into_tm_proof(proof_ops: ProofOps) -> tendermint::merkle::proof::ProofOps { + let ops = proof_ops + .ops + .into_iter() + .map(|op| tendermint::merkle::proof::ProofOp { + field_type: op.field_type, + key: op.key, + data: op.data, + }) + .collect(); + tendermint::merkle::proof::ProofOps { ops } +} + +fn into_abci_event(event: TmEvent) -> tendermint::abci::Event { + let attributes = event + .attributes + .into_iter() + .map(|attribute| (attribute.key, attribute.value).into()) + .collect(); + tendermint::abci::Event { + kind: event.r#type, + attributes, + } +} diff --git a/crates/relayer/src/chain/namada/tx.rs b/crates/relayer/src/chain/namada/tx.rs new file mode 100644 index 0000000000..4dc7f25e84 --- /dev/null +++ b/crates/relayer/src/chain/namada/tx.rs @@ -0,0 +1,384 @@ +use core::str::FromStr; +use core::time::Duration; +use std::path::PathBuf; +use std::thread; +use std::time::Instant; + +use ibc_proto::google::protobuf::Any; +use itertools::Itertools; +use namada_sdk::address::{Address, ImplicitAddress}; +use namada_sdk::args::TxBuilder; +use namada_sdk::args::{Tx as TxArgs, TxCustom}; +use namada_sdk::chain::ChainId; +use namada_sdk::io::NamadaIo; +use namada_sdk::tx::{prepare_tx, ProcessTxResponse}; +use namada_sdk::{rpc, signing, tx, Namada}; +use namada_tendermint_rpc::endpoint::broadcast::tx_sync::Response; +use tracing::{debug, debug_span, trace, warn}; + +use crate::chain::cosmos::gas::{adjust_estimated_gas, AdjustGas}; +use crate::chain::cosmos::types::gas::max_gas_from_config_opt; +use crate::chain::cosmos::types::tx::{TxStatus, TxSyncResult}; +use crate::chain::cosmos::wait::all_tx_results_found; +use crate::chain::endpoint::ChainEndpoint; +use crate::error::{Error, ErrorDetail}; + +use super::error::{Error as NamadaError, ErrorDetail as NamadaErrorDetail}; +use super::NamadaChain; + +const WAIT_BACKOFF: Duration = Duration::from_millis(300); + +impl NamadaChain { + pub fn batch_txs(&mut self, msgs: &[Any]) -> Result { + if msgs.is_empty() { + return Err(Error::send_tx("No message to be batched".to_string())); + } + + let tx_args = self.make_tx_args()?; + + let relayer_key = self.get_key()?; + let relayer_addr = relayer_key.address; + + let rt = self.rt.clone(); + rt.block_on(self.submit_reveal_aux(&tx_args, &relayer_addr))?; + + let args = TxCustom { + tx: tx_args.clone(), + code_path: Some(PathBuf::from(tx::TX_IBC_WASM)), + data_path: None, + serialized_tx: None, + owner: Some(relayer_addr.clone()), + }; + let mut txs = Vec::new(); + for msg in msgs { + let (mut tx, signing_data) = rt + .block_on(args.build(&self.ctx)) + .map_err(NamadaError::namada)?; + self.set_tx_data(&mut tx, msg)?; + txs.push((tx, signing_data.expect("signing_data should exist"))); + } + let (mut tx, signing_data) = tx::build_batch(txs).map_err(NamadaError::namada)?; + // This is fine, as only the relayers is signing the transactions + let signing_data = signing_data.first().expect("SigningData should exist"); + + // Estimate the fee with dry-run + match self.estimate_fee(tx.clone(), &tx_args, signing_data) { + // Set the estimated fee + Ok(Some((fee_token, gas_limit, fee_amount))) => { + self.prepare_tx_with_gas(&mut tx, &tx_args, &fee_token, gas_limit, fee_amount)? + } + Ok(None) => { + // the default gas limit will be used + } + Err(err) => match err.detail() { + ErrorDetail::Namada(namada_err) => { + match namada_err.source { + NamadaErrorDetail::DryRun(ref tx_results) => { + warn!("Simulation failed: {tx_results}"); + // Return the failure response to avoid the actual request. + // The response will be converted to `TxSyncResult`. + let response = Response { + codespace: Default::default(), + // the code value isn't used, but it should be non-zero to + // recognize the transaction failed + code: 1.into(), + data: Default::default(), + log: format!("Simulation failed: Results {tx_results}"), + hash: Default::default(), + }; + return Ok(response); + } + _ => return Err(err), + } + } + _ => return Err(err), + }, + } + + rt.block_on(self.ctx.sign( + &mut tx, + &tx_args, + signing_data.clone(), + signing::default_sign, + (), + )) + .map_err(NamadaError::namada)?; + + let tx_header_hash = tx.header_hash().to_string(); + let response = rt + .block_on(self.ctx.submit(tx, &tx_args)) + .map_err(NamadaError::namada)?; + + match response { + tx::ProcessTxResponse::Broadcast(mut response) => { + // overwrite the tx decrypted hash for the tx query + response.hash = tx_header_hash.parse().expect("invalid hash"); + Ok(response) + } + _ => unreachable!("The response type was unexpected"), + } + } + + fn make_tx_args(&mut self) -> Result { + let chain_id = ChainId::from_str(self.config.id.as_str()).expect("invalid chain ID"); + + let namada_key = self.get_key()?; + let relayer_public_key = namada_key.secret_key.to_public(); + + let tx_args = self.ctx.tx_builder(); + let tx_args = tx_args.chain_id(chain_id); + let tx_args = tx_args.signing_keys(vec![relayer_public_key]); + // Confirm the transaction later + let mut tx_args = tx_args.broadcast_only(true); + + let memo = self + .config + .memo_overwrite + .as_ref() + .unwrap_or(&self.config.memo_prefix); + let memo = if !memo.as_str().is_empty() { + Some(memo.as_str().to_string().as_bytes().to_vec()) + } else { + None + }; + tx_args.memo = memo; + + Ok(tx_args) + } + + fn set_tx_data(&self, tx: &mut tx::Tx, proto_msg: &Any) -> Result<(), Error> { + let mut tx_data = vec![]; + prost::Message::encode(proto_msg, &mut tx_data) + .map_err(|e| Error::protobuf_encode(String::from("Encoding the message failed"), e))?; + tx.add_serialized_data(tx_data); + Ok(()) + } + + fn estimate_fee( + &self, + mut tx: tx::Tx, + args: &TxArgs, + signing_data: &signing::SigningTxData, + ) -> Result, Error> { + let chain_id = self.config.id.clone(); + let fee_token_str = self.config.gas_price.denom.clone(); + let fee_token = Address::from_str(&fee_token_str) + .map_err(|_| NamadaError::address_decode(fee_token_str.clone()))?; + let gas_price = self.config.gas_price.price; + + let max_block_gas_key = namada_sdk::parameters::storage::get_max_block_gas_key(); + let max_block_gas: u64 = self + .rt + .block_on(rpc::query_storage_value( + self.ctx.client(), + &max_block_gas_key, + )) + .map_err(NamadaError::namada)?; + let max_gas = max_gas_from_config_opt(&self.config).unwrap_or(max_block_gas); + + let args = args.clone().dry_run_wrapper(true); + // Set the max gas to the gas limit for the simulation + self.prepare_tx_with_gas(&mut tx, &args, &fee_token, max_block_gas, gas_price)?; + + self.rt + .block_on(self.ctx.sign( + &mut tx, + &args, + signing_data.clone(), + signing::default_sign, + (), + )) + .map_err(NamadaError::namada)?; + + let response = match self.rt.block_on(self.ctx.submit(tx, &args)) { + Ok(resp) => resp, + Err(e) => { + warn!( + id = %chain_id, + "send_tx: gas estimation failed, using the default gas limit. Error: {}", + e + ); + return Ok(None); + } + }; + + let estimated_gas = match response { + ProcessTxResponse::DryRun(result) => { + if result + .0 + .iter() + .all(|(_, r)| matches!(&r, Ok(result) if result.is_accepted())) + { + result.1.into() + } else { + // All or some of requests will fail + return Err(NamadaError::dry_run(result.0).into()); + } + } + _ => unreachable!("Unexpected response"), + }; + if estimated_gas > max_gas { + debug!( + id = %chain_id, estimated = ?estimated_gas, max_gas, + "send_tx: estimated gas is higher than max gas" + ); + + return Err(Error::tx_simulate_gas_estimate_exceeded( + chain_id, + estimated_gas, + max_gas, + )); + } + + let gas_multiplier = self.config.gas_multiplier.unwrap_or_default().to_f64(); + + let adjusted_gas = adjust_estimated_gas(AdjustGas { + gas_multiplier, + max_gas, + gas_amount: estimated_gas, + }); + + debug!( + id = %chain_id, + "send_tx: using {} gas, gas_price {:?}", + estimated_gas, + gas_price, + ); + + Ok(Some((fee_token, adjusted_gas, gas_price))) + } + + fn prepare_tx_with_gas( + &self, + tx: &mut tx::Tx, + args: &TxArgs, + fee_token: &Address, + gas_limit: u64, + fee_amount: f64, + ) -> Result<(), Error> { + let relayer_key = self.get_key()?; + let relayer_public_key = relayer_key.secret_key.to_public(); + + let args = args + .clone() + .fee_token(fee_token.clone()) + .gas_limit(gas_limit.into()) + .fee_amount( + fee_amount + .to_string() + .parse() + .expect("Fee should be parsable"), + ); + let fee_amount = self + .rt + .block_on(signing::validate_fee(&self.ctx, &args)) + .map_err(NamadaError::namada)?; + self.rt + .block_on(prepare_tx(&args, tx, fee_amount, relayer_public_key)) + .map_err(NamadaError::namada)?; + + Ok(()) + } + + pub fn wait_for_block_commits( + &self, + tx_sync_results: &mut [TxSyncResult], + ) -> Result<(), Error> { + if all_tx_results_found(tx_sync_results) { + return Ok(()); + } + + let chain_id = &self.id(); + crate::time!( + "wait_for_block_commits", + { + "src_chain": chain_id, + } + ); + let _span = debug_span!("wait_for_block_commits", id = %chain_id).entered(); + + let start_time = Instant::now(); + + let hashes = tx_sync_results + .iter() + .map(|res| res.response.hash.to_string()) + .join(", "); + + debug!("waiting for commit of tx hashes(s) {}", hashes); + + loop { + let elapsed = start_time.elapsed(); + + if all_tx_results_found(tx_sync_results) { + trace!( + "retrieved {} tx results after {} ms", + tx_sync_results.len(), + elapsed.as_millis(), + ); + + return Ok(()); + } else if elapsed > self.config.rpc_timeout { + debug!("timed out after {} ms", elapsed.as_millis()); + return Err(Error::tx_no_confirmation()); + } else { + thread::sleep(WAIT_BACKOFF); + + for tx_sync_result in tx_sync_results.iter_mut() { + if let Err(e) = self.update_tx_sync_result(tx_sync_result) { + debug!("update_tx_sync_result failed. It will be retried: {e}"); + } + } + } + } + } + + fn update_tx_sync_result(&self, tx_sync_result: &mut TxSyncResult) -> Result<(), Error> { + if let TxStatus::Pending { .. } = tx_sync_result.status { + let tm_hash = namada_tendermint::Hash::from_bytes( + namada_tendermint::hash::Algorithm::Sha256, + tx_sync_result.response.hash.as_bytes(), + ) + .expect("tendermint hash should be converted"); + // If the transaction failed, query_txs returns the IbcEvent::ChainError, + // so that we don't attempt to resolve the transaction later on. + let events = self.query_tx_events(&tm_hash)?; + // If we get events back, progress was made, so we replace the events + // with the new ones. in both cases we will check in the next iteration + // whether or not the transaction was fully committed. + if !events.is_empty() { + tx_sync_result.events = events; + tx_sync_result.status = TxStatus::ReceivedResponse; + } + } + Ok(()) + } + + async fn submit_reveal_aux(&mut self, args: &TxArgs, address: &Address) -> Result<(), Error> { + if let Address::Implicit(ImplicitAddress(pkh)) = address { + let public_key = self + .ctx + .wallet() + .await + .find_public_key(pkh.to_string()) + .map_err(|e| NamadaError::namada(namada_sdk::error::Error::Other(e.to_string())))?; + + if tx::is_reveal_pk_needed(self.ctx.client(), address) + .await + .map_err(NamadaError::namada)? + { + let (mut tx, signing_data) = tx::build_reveal_pk(&self.ctx, args, &public_key) + .await + .map_err(NamadaError::namada)?; + self.ctx + .sign(&mut tx, args, signing_data, signing::default_sign, ()) + .await + .map_err(NamadaError::namada)?; + self.ctx + .submit(tx, args) + .await + .map_err(NamadaError::namada)?; + } + } + Ok(()) + } +} diff --git a/crates/relayer/src/chain/namada/version.rs b/crates/relayer/src/chain/namada/version.rs new file mode 100644 index 0000000000..295ae16393 --- /dev/null +++ b/crates/relayer/src/chain/namada/version.rs @@ -0,0 +1,27 @@ +use core::fmt::{Display, Error as FmtError, Formatter}; + +use crate::chain::version::ConsensusVersion; + +/// Captures the version(s) specification of different modules of a network. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Specs { + pub namada: Option, + pub consensus: Option, +} + +impl Display for Specs { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + let namada = self + .namada + .as_ref() + .map(|v| v.to_string()) + .unwrap_or_else(|| "UNKNOWN".to_string()); + + let consensus = match self.consensus { + Some(ref v) => v.to_string(), + None => "Tendermint: UNKNOWN, CometBFT: UNKNOWN".to_string(), + }; + + write!(f, "Namada {}, {}", namada, consensus) + } +} diff --git a/crates/relayer/src/chain/namada/wallet.rs b/crates/relayer/src/chain/namada/wallet.rs new file mode 100644 index 0000000000..c30742f489 --- /dev/null +++ b/crates/relayer/src/chain/namada/wallet.rs @@ -0,0 +1,65 @@ +use std::path::PathBuf; +use std::{env, fs}; + +use namada_sdk::wallet::fs::FsWalletStorage; +use namada_sdk::wallet::{LoadStoreError, Store, Wallet, WalletIo, WalletStorage}; +use namada_sdk::zeroize::Zeroizing; +use signature::rand_core::OsRng; + +/// Wallet utils for Namada context +#[derive(Clone)] +pub(super) struct NullWalletUtils; + +impl WalletIo for NullWalletUtils { + type Rng = OsRng; +} + +// Namada wallet never accesses the storage. It reads the keys added in the bootstrap from the store. +impl WalletStorage for NullWalletUtils { + fn save(&self, _wallet: &Wallet) -> Result<(), LoadStoreError> { + Ok(()) + } + + fn load(&self, _wallet: &mut Wallet) -> Result<(), LoadStoreError> { + Ok(()) + } +} + +/// For Namada wallet for adding a key with a password +#[derive(Clone)] +pub struct CliWalletUtils { + store_dir: PathBuf, +} + +impl CliWalletUtils { + pub fn new(store_dir: PathBuf) -> Wallet { + Wallet::new(Self { store_dir }, Store::default()) + } +} + +impl FsWalletStorage for CliWalletUtils { + fn store_dir(&self) -> &PathBuf { + &self.store_dir + } +} + +impl WalletIo for CliWalletUtils { + type Rng = OsRng; + + fn read_password(_confirm: bool, _target_key: Option<&str>) -> Zeroizing { + match env::var("NAMADA_WALLET_PASSWORD_FILE") { + Ok(path) => Zeroizing::new( + fs::read_to_string(path).expect("Something went wrong reading the file"), + ), + Err(_) => match env::var("NAMADA_WALLET_PASSWORD") { + Ok(password) => Zeroizing::new(password), + Err(_) => { + let prompt = "Enter your decryption password: "; + rpassword::read_password_from_tty(Some(prompt)) + .map(Zeroizing::new) + .expect("Failed reading password from tty.") + } + }, + } + } +} diff --git a/crates/relayer/src/chain/runtime.rs b/crates/relayer/src/chain/runtime.rs index 0aff1cb248..9c6a4a17fe 100644 --- a/crates/relayer/src/chain/runtime.rs +++ b/crates/relayer/src/chain/runtime.rs @@ -48,11 +48,11 @@ use crate::{ use super::{ client::ClientSettings, - cosmos::version::Specs, endpoint::{ChainEndpoint, ChainStatus, HealthCheck}, handle::{ChainHandle, ChainRequest, ReplyTo, Subscription}, requests::*, tracking::TrackedMsgs, + version::Specs, }; pub struct Threads { diff --git a/crates/relayer/src/chain/version.rs b/crates/relayer/src/chain/version.rs new file mode 100644 index 0000000000..0a43f51381 --- /dev/null +++ b/crates/relayer/src/chain/version.rs @@ -0,0 +1,27 @@ +use core::fmt::{Display, Error as FmtError, Formatter}; + +use crate::chain::cosmos::version::Specs as CosmosSpecs; +use crate::chain::namada::version::Specs as NamadaSpecs; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum ConsensusVersion { + Tendermint(semver::Version), + Comet(semver::Version), +} + +impl Display for ConsensusVersion { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + let consensus = match self { + ConsensusVersion::Tendermint(ref v) => format!("Tendermint {v}"), + ConsensusVersion::Comet(ref v) => format!("CometBFT {v}"), + }; + write!(f, "{consensus}") + } +} + +/// Captures the version(s) specification of different modules of a network. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Specs { + Cosmos(CosmosSpecs), + Namada(NamadaSpecs), +} diff --git a/crates/relayer/src/config.rs b/crates/relayer/src/config.rs index fa4725a6d2..584d0cf347 100644 --- a/crates/relayer/src/config.rs +++ b/crates/relayer/src/config.rs @@ -322,7 +322,7 @@ impl Config { } match chain_config { - ChainConfig::CosmosSdk(cosmos_config) => { + ChainConfig::CosmosSdk(cosmos_config) | ChainConfig::Namada(cosmos_config) => { cosmos_config .validate() .map_err(Into::>::into)?; @@ -655,36 +655,43 @@ pub enum EventSourceMode { #[serde(tag = "type")] pub enum ChainConfig { CosmosSdk(CosmosSdkConfig), + // Reuse CosmosSdkConfig for tendermint light clients + Namada(CosmosSdkConfig), } impl ChainConfig { pub fn id(&self) -> &ChainId { match self { Self::CosmosSdk(config) => &config.id, + Self::Namada(config) => &config.id, } } pub fn packet_filter(&self) -> &PacketFilter { match self { Self::CosmosSdk(config) => &config.packet_filter, + Self::Namada(config) => &config.packet_filter, } } pub fn max_block_time(&self) -> Duration { match self { Self::CosmosSdk(config) => config.max_block_time, + Self::Namada(config) => config.max_block_time, } } pub fn key_name(&self) -> &String { match self { Self::CosmosSdk(config) => &config.key_name, + Self::Namada(config) => &config.key_name, } } pub fn set_key_name(&mut self, key_name: String) { match self { Self::CosmosSdk(config) => config.key_name = key_name, + Self::Namada(config) => config.key_name = key_name, } } @@ -703,6 +710,15 @@ impl ChainConfig { .map(|(key_name, keys)| (key_name, keys.into())) .collect() } + ChainConfig::Namada(config) => { + let keyring = + KeyRing::new_namada(Store::Test, &config.id, &config.key_store_folder)?; + keyring + .keys()? + .into_iter() + .map(|(key_name, keys)| (key_name, keys.into())) + .collect() + } }; Ok(keys) @@ -710,25 +726,27 @@ impl ChainConfig { pub fn clear_interval(&self) -> Option { match self { - Self::CosmosSdk(config) => config.clear_interval, + Self::CosmosSdk(config) | Self::Namada(config) => config.clear_interval, } } pub fn query_packets_chunk_size(&self) -> usize { match self { - Self::CosmosSdk(config) => config.query_packets_chunk_size, + Self::CosmosSdk(config) | Self::Namada(config) => config.query_packets_chunk_size, } } pub fn set_query_packets_chunk_size(&mut self, query_packets_chunk_size: usize) { match self { - Self::CosmosSdk(config) => config.query_packets_chunk_size = query_packets_chunk_size, + Self::CosmosSdk(config) | Self::Namada(config) => { + config.query_packets_chunk_size = query_packets_chunk_size + } } } pub fn excluded_sequences(&self, channel_id: &ChannelId) -> Cow<'_, [Sequence]> { match self { - Self::CosmosSdk(config) => config + Self::CosmosSdk(config) | Self::Namada(config) => config .excluded_sequences .map .get(channel_id) @@ -739,7 +757,7 @@ impl ChainConfig { pub fn allow_ccq(&self) -> bool { match self { - Self::CosmosSdk(config) => config.allow_ccq, + Self::CosmosSdk(config) | Self::Namada(config) => config.allow_ccq, } } } @@ -768,7 +786,9 @@ impl<'de> Deserialize<'de> for ChainConfig { "CosmosSdk" => CosmosSdkConfig::deserialize(value) .map(Self::CosmosSdk) .map_err(|e| serde::de::Error::custom(format!("invalid CosmosSdk config: {e}"))), - + "Namada" => CosmosSdkConfig::deserialize(value) + .map(Self::Namada) + .map_err(|e| serde::de::Error::custom(format!("invalid Namada config: {e}"))), // // <-- Add new chain types here --> // @@ -927,6 +947,9 @@ mod tests { super::ChainConfig::CosmosSdk(_) => { // all good } + super::ChainConfig::Namada(_) => { + panic!("Default chain is expected to be CosmosSDK not Namada") + } } } @@ -953,11 +976,15 @@ mod tests { let config = load(path).expect("could not parse config"); let excluded_sequences1 = match config.chains.first().unwrap() { - ChainConfig::CosmosSdk(chain_config) => chain_config.excluded_sequences.clone(), + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { + chain_config.excluded_sequences.clone() + } }; let excluded_sequences2 = match config.chains.last().unwrap() { - ChainConfig::CosmosSdk(chain_config) => chain_config.excluded_sequences.clone(), + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { + chain_config.excluded_sequences.clone() + } }; assert_eq!(excluded_sequences1, excluded_sequences2); diff --git a/crates/relayer/src/error.rs b/crates/relayer/src/error.rs index c8ac6d656d..9059195537 100644 --- a/crates/relayer/src/error.rs +++ b/crates/relayer/src/error.rs @@ -36,6 +36,7 @@ use ibc_relayer_types::proofs::ProofError; use crate::chain::cosmos::version; use crate::chain::cosmos::BLOCK_MAX_BYTES_MAX_FRACTION; +use crate::chain::namada::error::Error as NamadaError; use crate::config::Error as ConfigError; use crate::event::source; use crate::keyring::{errors::Error as KeyringError, KeyType}; @@ -642,6 +643,10 @@ define_error! { Ics24HostValidationError [ ValidationError ] |_| { "ICS24 host validation error" }, + + Namada + [ NamadaError ] + |_| { "Namada error" }, } } diff --git a/crates/relayer/src/event.rs b/crates/relayer/src/event.rs index f5219f4750..0b59747dba 100644 --- a/crates/relayer/src/event.rs +++ b/crates/relayer/src/event.rs @@ -39,7 +39,7 @@ pub mod bus; pub mod error; pub mod source; -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Serialize, PartialEq)] pub struct IbcEventWithHeight { pub event: IbcEvent, pub height: Height, diff --git a/crates/relayer/src/event/source/websocket/extract.rs b/crates/relayer/src/event/source/websocket/extract.rs index ddc692054d..8e0539b144 100644 --- a/crates/relayer/src/event/source/websocket/extract.rs +++ b/crates/relayer/src/event/source/websocket/extract.rs @@ -6,11 +6,12 @@ use tendermint_rpc::{event::Event as RpcEvent, event::EventData as RpcEventData} use ibc_relayer_types::applications::ics31_icq::events::CrossChainQueryPacket; use ibc_relayer_types::core::ics02_client::{events as ClientEvents, height::Height}; +use ibc_relayer_types::core::ics03_connection::events as ConnectionEvents; use ibc_relayer_types::core::ics04_channel::events as ChannelEvents; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use ibc_relayer_types::events::IbcEvent; -use crate::chain::cosmos::types::events::channel::RawObject; +use crate::chain::cosmos::types::events::raw_object::RawObject; use crate::event::source::queries; use crate::telemetry; @@ -300,6 +301,36 @@ fn extract_block_events( } let mut events: Vec = vec![]; + append_events::( + &mut events, + extract_events( + height, + block_events, + "connection_open_init", + "connection_id", + ), + height, + ); + append_events::( + &mut events, + extract_events(height, block_events, "connection_open_try", "connection_id"), + height, + ); + append_events::( + &mut events, + extract_events(height, block_events, "connection_open_ack", "connection_id"), + height, + ); + append_events::( + &mut events, + extract_events( + height, + block_events, + "connection_open_confirm", + "connection_id", + ), + height, + ); append_events::( &mut events, extract_events(height, block_events, "channel_open_init", "channel_id"), @@ -330,6 +361,11 @@ fn extract_block_events( extract_events(height, block_events, "send_packet", "packet_data_hex"), height, ); + append_events::( + &mut events, + extract_events(height, block_events, "write_acknowledgement", "packet_ack"), + height, + ); append_events::( &mut events, extract_events(height, block_events, "channel_close_init", "channel_id"), diff --git a/crates/relayer/src/foreign_client.rs b/crates/relayer/src/foreign_client.rs index 1120ee2dda..fab20454db 100644 --- a/crates/relayer/src/foreign_client.rs +++ b/crates/relayer/src/foreign_client.rs @@ -906,7 +906,9 @@ impl ForeignClient config.client_refresh_rate, + ChainConfig::CosmosSdk(config) | ChainConfig::Namada(config) => { + config.client_refresh_rate + } }; let refresh_period = client_state @@ -1758,7 +1760,9 @@ impl ForeignClient config.ccv_consumer_chain, + ChainConfig::CosmosSdk(config) | ChainConfig::Namada(config) => { + config.ccv_consumer_chain + } }; let mut msgs = vec![]; diff --git a/crates/relayer/src/keyring.rs b/crates/relayer/src/keyring.rs index 1260de235e..446ba7b039 100644 --- a/crates/relayer/src/keyring.rs +++ b/crates/relayer/src/keyring.rs @@ -5,6 +5,8 @@ pub use key_type::KeyType; pub use secp256k1_key_pair::Secp256k1KeyPair; pub use signing_key_pair::{SigningKeyPair, SigningKeyPairSized}; +pub use crate::chain::namada::key::NamadaKeyPair; + mod any_signing_key_pair; mod ed25519_key_pair; mod key_type; @@ -286,7 +288,15 @@ impl KeyRing { } } -// Why is this not a method on `ChainConfig`? +impl KeyRing { + pub fn new_namada( + store: Store, + chain_id: &ChainId, + ks_folder: &Option, + ) -> Result { + Self::new(store, "", chain_id, ks_folder) + } +} fn disk_store_path(folder_name: &str, keystore_folder: &Option) -> Result { let ks_folder = match keystore_folder { diff --git a/crates/relayer/src/keyring/any_signing_key_pair.rs b/crates/relayer/src/keyring/any_signing_key_pair.rs index f6aa27bd0b..3bd57177a2 100644 --- a/crates/relayer/src/keyring/any_signing_key_pair.rs +++ b/crates/relayer/src/keyring/any_signing_key_pair.rs @@ -1,12 +1,13 @@ use serde::Serialize; -use super::{Ed25519KeyPair, KeyType, Secp256k1KeyPair, SigningKeyPair}; +use super::{Ed25519KeyPair, KeyType, NamadaKeyPair, Secp256k1KeyPair, SigningKeyPair}; #[derive(Clone, Debug, Serialize)] #[serde(untagged)] pub enum AnySigningKeyPair { Secp256k1(Secp256k1KeyPair), Ed25519(Ed25519KeyPair), + Namada(NamadaKeyPair), } impl AnySigningKeyPair { @@ -14,6 +15,7 @@ impl AnySigningKeyPair { match self { Self::Secp256k1(key_pair) => key_pair.account(), Self::Ed25519(key_pair) => key_pair.account(), + Self::Namada(key_pair) => key_pair.account(), } } @@ -21,6 +23,7 @@ impl AnySigningKeyPair { match self { Self::Secp256k1(_) => Secp256k1KeyPair::KEY_TYPE, Self::Ed25519(_) => Ed25519KeyPair::KEY_TYPE, + Self::Namada(_) => NamadaKeyPair::KEY_TYPE, } } @@ -28,6 +31,7 @@ impl AnySigningKeyPair { match self { Self::Secp256k1(key_pair) => key_pair.as_any(), Self::Ed25519(key_pair) => key_pair.as_any(), + Self::Namada(key_pair) => key_pair.as_any(), } .downcast_ref::() .cloned() @@ -45,3 +49,9 @@ impl From for AnySigningKeyPair { Self::Ed25519(key_pair) } } + +impl From for AnySigningKeyPair { + fn from(key_pair: NamadaKeyPair) -> Self { + Self::Namada(key_pair) + } +} diff --git a/crates/relayer/src/light_client/tendermint.rs b/crates/relayer/src/light_client/tendermint.rs index 808c616235..4628517b51 100644 --- a/crates/relayer/src/light_client/tendermint.rs +++ b/crates/relayer/src/light_client/tendermint.rs @@ -153,12 +153,12 @@ impl super::LightClient for LightClient { )) })?; - let update_header: &TmHeader = match any_header { - AnyHeader::Tendermint(header) => Ok(header), + let update_header = match any_header { + AnyHeader::Tendermint(header) => Ok::<_, Error>(header), }?; let client_state = match client_state { - AnyClientState::Tendermint(client_state) => Ok(client_state), + AnyClientState::Tendermint(client_state) => Ok::<_, Error>(client_state), }?; let next_validators = self @@ -322,7 +322,7 @@ impl LightClient { let scheduler = components::scheduler::basic_bisecting_schedule; let client_state = match client_state { - AnyClientState::Tendermint(client_state) => Ok(client_state), + AnyClientState::Tendermint(client_state) => Ok::<_, Error>(client_state), }?; Ok(TmLightClient::new( diff --git a/crates/relayer/src/spawn.rs b/crates/relayer/src/spawn.rs index 113ac1f6a7..f791fddabc 100644 --- a/crates/relayer/src/spawn.rs +++ b/crates/relayer/src/spawn.rs @@ -6,7 +6,9 @@ use tokio::runtime::Runtime as TokioRuntime; use ibc_relayer_types::core::ics24_host::identifier::ChainId; use crate::{ - chain::{cosmos::CosmosSdkChain, handle::ChainHandle, runtime::ChainRuntime}, + chain::{ + cosmos::CosmosSdkChain, handle::ChainHandle, namada::NamadaChain, runtime::ChainRuntime, + }, config::{ChainConfig, Config}, error::Error as RelayerError, }; @@ -82,6 +84,7 @@ pub fn spawn_chain_runtime_with_config( ) -> Result { let handle = match config { ChainConfig::CosmosSdk(_) => ChainRuntime::::spawn(config, rt), + ChainConfig::Namada(_) => ChainRuntime::::spawn(config, rt), } .map_err(SpawnError::relayer)?; diff --git a/crates/relayer/src/upgrade_chain.rs b/crates/relayer/src/upgrade_chain.rs index 318f35130b..f6a7277120 100644 --- a/crates/relayer/src/upgrade_chain.rs +++ b/crates/relayer/src/upgrade_chain.rs @@ -22,6 +22,7 @@ use tracing::warn; use crate::chain::handle::ChainHandle; use crate::chain::requests::{IncludeProof, QueryClientStateRequest, QueryHeight}; use crate::chain::tracking::TrackedMsgs; +use crate::chain::version::Specs; use crate::client_state::AnyClientState; use crate::error::Error; @@ -76,7 +77,7 @@ pub fn build_and_send_ibc_upgrade_proposal( src_chain: impl ChainHandle, // the source chain; supplies a client state for building the upgrade plan opts: &UpgradePlanOptions, ) -> Result { - let any_msg = if requires_legacy_upgrade_proposal(dst_chain.clone()) { + let any_msg = if requires_legacy_upgrade_proposal(dst_chain.clone())? { build_legacy_upgrade_proposal(dst_chain.clone(), src_chain, opts) } else { build_upgrade_proposal(dst_chain.clone(), src_chain, opts) @@ -98,10 +99,22 @@ pub fn build_and_send_ibc_upgrade_proposal( /// or if the newer `MsgIBCSoftwareUpdate` message should be used to upgrade the chain. /// If the ibc-go version returned isn't reliable, a deprecated version, then the version /// of Cosmos SDK is used, if any. If there is no SDK version, we assume that the legacy upgrade is required. -pub fn requires_legacy_upgrade_proposal(dst_chain: impl ChainHandle) -> bool { +pub fn requires_legacy_upgrade_proposal( + dst_chain: impl ChainHandle, +) -> Result { let Ok(version_specs) = dst_chain.version_specs() else { warn!("failed to get version specs, assuming legacy upgrade proposal is required"); - return true; + return Ok(true); + }; + + let version_specs = match version_specs { + Specs::Cosmos(v) => v, + Specs::Namada(_) => { + return Err(UpgradeChainError::submit( + dst_chain.id(), + crate::chain::namada::error::Error::upgrade().into(), + )) + } }; let sdk_before_50 = version_specs @@ -110,7 +123,7 @@ pub fn requires_legacy_upgrade_proposal(dst_chain: impl ChainHandle) -> bool { .map(|s| s.minor < 50) .unwrap_or(true); - match version_specs.ibc_go { + Ok(match version_specs.ibc_go { None => sdk_before_50, Some(ibc_version) => { // Some ibc-go simapps return unreliable ibc-go versions, such as simapp v8.0.0 @@ -123,7 +136,7 @@ pub fn requires_legacy_upgrade_proposal(dst_chain: impl ChainHandle) -> bool { ibc_version.major < 8 } } - } + }) } /// Ibc-go versions up to v7.x.x use the deprecated `UpgradeProposal` to upgrade a chain diff --git a/crates/relayer/src/util/compat_mode.rs b/crates/relayer/src/util/compat_mode.rs index c637d5a247..104026e70e 100644 --- a/crates/relayer/src/util/compat_mode.rs +++ b/crates/relayer/src/util/compat_mode.rs @@ -2,7 +2,7 @@ use tracing::warn; use tendermint::Version; -use crate::chain::cosmos::version::ConsensusVersion; +use crate::chain::version::ConsensusVersion; use crate::config::compat_mode::CompatMode; use crate::error::Error; diff --git a/crates/telemetry/Cargo.toml b/crates/telemetry/Cargo.toml index 37d7f2823c..30ce7f45c6 100644 --- a/crates/telemetry/Cargo.toml +++ b/crates/telemetry/Cargo.toml @@ -7,7 +7,7 @@ readme = "README.md" keywords = ["cosmos", "ibc", "relayer", "telemetry"] repository = "https://github.com/informalsystems/hermes" authors = ["Informal Systems "] -rust-version = "1.76.0" +rust-version = "1.79.0" description = """ Telemetry service for the Hermes IBC relayer """ diff --git a/tools/integration-test/Cargo.toml b/tools/integration-test/Cargo.toml index d5a7783d33..dc40cac620 100644 --- a/tools/integration-test/Cargo.toml +++ b/tools/integration-test/Cargo.toml @@ -2,7 +2,7 @@ name = "ibc-integration-test" version = "0.30.0" edition = "2021" -rust-version = "1.76.0" +rust-version = "1.79.0" license = "Apache-2.0" readme = "README.md" keywords = ["blockchain", "consensus", "cosmos", "ibc", "tendermint"] @@ -50,6 +50,7 @@ new-register-interchain-account = [] authz = [] benchmark = [] no-denom-trace = [] +namada = [] [[bin]] name = "test_setup_with_binary_channel" diff --git a/tools/integration-test/src/bin/test_setup_with_binary_channel.rs b/tools/integration-test/src/bin/test_setup_with_binary_channel.rs index 44d6cb40e4..85565698e2 100644 --- a/tools/integration-test/src/bin/test_setup_with_binary_channel.rs +++ b/tools/integration-test/src/bin/test_setup_with_binary_channel.rs @@ -43,7 +43,7 @@ impl TestOverrides for Test { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { // Modify the key store type to `Store::Test` so that the wallet // keys are stored to ~/.hermes/keys so that we can use them // with external relayer commands. diff --git a/tools/integration-test/src/bin/test_setup_with_fee_enabled_binary_channel.rs b/tools/integration-test/src/bin/test_setup_with_fee_enabled_binary_channel.rs index ac938158d2..39b749c3bf 100644 --- a/tools/integration-test/src/bin/test_setup_with_fee_enabled_binary_channel.rs +++ b/tools/integration-test/src/bin/test_setup_with_fee_enabled_binary_channel.rs @@ -44,7 +44,7 @@ impl TestOverrides for Test { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { // Modify the key store type to `Store::Test` so that the wallet // keys are stored to ~/.hermes/keys so that we can use them // with external relayer commands. diff --git a/tools/integration-test/src/bin/test_setup_with_ternary_channel.rs b/tools/integration-test/src/bin/test_setup_with_ternary_channel.rs index 1cfcd0f921..b11f77634d 100644 --- a/tools/integration-test/src/bin/test_setup_with_ternary_channel.rs +++ b/tools/integration-test/src/bin/test_setup_with_ternary_channel.rs @@ -43,7 +43,7 @@ impl TestOverrides for Test { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { // Modify the key store type to `Store::Test` so that the wallet // keys are stored to ~/.hermes/keys so that we can use them // with external relayer commands. diff --git a/tools/integration-test/src/tests/async_icq/simple_query.rs b/tools/integration-test/src/tests/async_icq/simple_query.rs index 493d034b1a..bce4a2c69b 100644 --- a/tools/integration-test/src/tests/async_icq/simple_query.rs +++ b/tools/integration-test/src/tests/async_icq/simple_query.rs @@ -2,7 +2,7 @@ use std::env; use ibc_relayer::channel::version::Version; use ibc_relayer::config::ChainConfig; -use ibc_test_framework::chain::config::{ +use ibc_test_framework::chain::config::cosmos::{ add_allow_message_interchainquery, set_floor_gas_price, set_max_deposit_period, set_min_deposit_amount, set_voting_period, }; @@ -70,7 +70,7 @@ impl BinaryConnectionTest for AsyncIcqTest { connection: ConnectedConnection, ) -> Result<(), Error> { let fee_denom_b: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(1))); + MonoTagged::new(Denom::base(config.native_token(1), config.native_token(1))); let port_a = DualTagged::new(PortId::oracle()); let port_b = DualTagged::new(PortId::icqhost()); let (channel_id_b, channel_id_a) = init_channel_version( @@ -217,7 +217,7 @@ impl BinaryConnectionTest for FailedAsyncIcqTest { connection: ConnectedConnection, ) -> Result<(), Error> { let fee_denom_b: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(1))); + MonoTagged::new(Denom::base(config.native_token(1), config.native_token(1))); let port_a = DualTagged::new(PortId::oracle()); let port_b = DualTagged::new(PortId::icqhost()); let (channel_id_b, channel_id_a) = init_channel_version( @@ -336,7 +336,7 @@ fn assert_eventual_async_icq_success( relayer: &RelayerDriver, ) -> Result<(), Error> { let rpc_addr = match relayer.config.chains.first().unwrap() { - ChainConfig::CosmosSdk(c) => c.rpc_addr.clone(), + ChainConfig::CosmosSdk(c) | ChainConfig::Namada(c) => c.rpc_addr.clone(), }; let mut rpc_client = HttpClient::new(rpc_addr).unwrap(); @@ -371,7 +371,7 @@ fn assert_eventual_async_icq_error( relayer: &RelayerDriver, ) -> Result<(), Error> { let rpc_addr = match relayer.config.chains.first().unwrap() { - ChainConfig::CosmosSdk(c) => c.rpc_addr.clone(), + ChainConfig::CosmosSdk(c) | ChainConfig::Namada(c) => c.rpc_addr.clone(), }; let mut rpc_client = HttpClient::new(rpc_addr).unwrap(); diff --git a/tools/integration-test/src/tests/authz.rs b/tools/integration-test/src/tests/authz.rs index 28f5c11a18..9a661a9a6a 100644 --- a/tools/integration-test/src/tests/authz.rs +++ b/tools/integration-test/src/tests/authz.rs @@ -35,7 +35,7 @@ impl BinaryChannelTest for AuthzTest { ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(0))); + MonoTagged::new(Denom::base(config.native_token(0), config.native_token(0))); let wallet_b = chains.node_b.wallets().user1().cloned(); let a_to_b_amount = 12345u64; @@ -75,6 +75,7 @@ impl BinaryChannelTest for AuthzTest { .query_balance(&chains.node_a.wallets().user2().address(), &denom_a)?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, @@ -120,7 +121,7 @@ impl BinaryChannelTest for NoAuthzTest { ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(0))); + MonoTagged::new(Denom::base(config.native_token(0), config.native_token(0))); let wallet_b = chains.node_b.wallets().user1().cloned(); let a_to_b_amount = 12345u64; @@ -140,6 +141,7 @@ impl BinaryChannelTest for NoAuthzTest { .to_string(); let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/channel_upgrade/flushing.rs b/tools/integration-test/src/tests/channel_upgrade/flushing.rs index 0e4bdf7143..3b2777f733 100644 --- a/tools/integration-test/src/tests/channel_upgrade/flushing.rs +++ b/tools/integration-test/src/tests/channel_upgrade/flushing.rs @@ -10,7 +10,7 @@ use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeigh use ibc_relayer_types::core::ics04_channel::channel::State as ChannelState; use ibc_relayer_types::core::ics04_channel::packet::Sequence; use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::chain::config::cosmos::{set_max_deposit_period, set_voting_period}; use ibc_test_framework::prelude::*; use ibc_test_framework::relayer::channel::{ assert_eventually_channel_established, assert_eventually_channel_upgrade_ack, @@ -166,6 +166,7 @@ impl BinaryChannelTest for ChannelUpgradeFlushing { relayer.with_supervisor(|| { let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, @@ -384,6 +385,7 @@ impl BinaryChannelTest for ChannelUpgradeHandshakeFlushPackets { // and move channel ends to `FLUSH_COMPLETE` relayer.with_supervisor(|| { let ibc_denom_a = derive_ibc_denom( + &chains.node_a.chain_driver().value().chain_type, &channels.port_a.as_ref(), &channels.channel_id_a.as_ref(), &denom_b, @@ -395,6 +397,7 @@ impl BinaryChannelTest for ChannelUpgradeHandshakeFlushPackets { )?; let ibc_denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/channel_upgrade/ica.rs b/tools/integration-test/src/tests/channel_upgrade/ica.rs index 8ddd4fb5c7..c2f1846f48 100644 --- a/tools/integration-test/src/tests/channel_upgrade/ica.rs +++ b/tools/integration-test/src/tests/channel_upgrade/ica.rs @@ -32,7 +32,7 @@ use ibc_relayer_types::signer::Signer; use ibc_relayer_types::timestamp::Timestamp; use ibc_relayer_types::tx_msg::Msg; -use ibc_test_framework::chain::config::{ +use ibc_test_framework::chain::config::cosmos::{ add_allow_message_interchainaccounts, set_max_deposit_period, set_voting_period, }; use ibc_test_framework::chain::ext::ica::register_ordered_interchain_account; @@ -91,8 +91,8 @@ impl BinaryConnectionTest for ChannelUpgradeICACloseChannel { connection: ConnectedConnection, ) -> Result<(), Error> { let fee_denom_host: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(1))); - let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); + MonoTagged::new(Denom::base(config.native_token(1), config.native_token(1))); + let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake", "stake")); // Run the block with supervisor in order to open and then upgrade the ICA channel let (wallet, ica_address, controller_channel_id, controller_port_id) = relayer @@ -315,7 +315,7 @@ impl TestOverrides for ChannelUpgradeICAUnordered { for chain in &mut config.chains { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.packet_filter = self.packet_filter.clone(); } } @@ -344,8 +344,8 @@ impl BinaryConnectionTest for ChannelUpgradeICAUnordered { connection: ConnectedConnection, ) -> Result<(), Error> { let fee_denom_host: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(1))); - let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); + MonoTagged::new(Denom::base(config.native_token(1), config.native_token(1))); + let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake", "stake")); info!("Will register interchain account..."); diff --git a/tools/integration-test/src/tests/channel_upgrade/ics29.rs b/tools/integration-test/src/tests/channel_upgrade/ics29.rs index 02f90b2745..95db144604 100644 --- a/tools/integration-test/src/tests/channel_upgrade/ics29.rs +++ b/tools/integration-test/src/tests/channel_upgrade/ics29.rs @@ -7,7 +7,7 @@ use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; use ibc_relayer_types::core::ics04_channel::packet::Sequence; use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::chain::config::cosmos::{set_max_deposit_period, set_voting_period}; use ibc_test_framework::prelude::*; use ibc_test_framework::relayer::channel::{ assert_eventually_channel_established, assert_eventually_channel_upgrade_open, @@ -202,6 +202,7 @@ impl BinaryChannelTest for ChannelUpgradeICS29 { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/channel_upgrade/timeout.rs b/tools/integration-test/src/tests/channel_upgrade/timeout.rs index 42bdd288ed..ed391391f1 100644 --- a/tools/integration-test/src/tests/channel_upgrade/timeout.rs +++ b/tools/integration-test/src/tests/channel_upgrade/timeout.rs @@ -27,7 +27,7 @@ use ibc_relayer_types::core::ics04_channel::channel::State as ChannelState; use ibc_relayer_types::core::ics04_channel::packet::Sequence; use ibc_relayer_types::core::ics04_channel::version::Version; use ibc_relayer_types::events::IbcEventType; -use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::chain::config::cosmos::{set_max_deposit_period, set_voting_period}; use ibc_test_framework::prelude::*; use ibc_test_framework::relayer::channel::{ assert_eventually_channel_established, assert_eventually_channel_upgrade_ack, @@ -992,6 +992,7 @@ impl BinaryChannelTest for ChannelUpgradeHandshakeTimeoutOnPacketAck { // and move channel ends to `FLUSH_COMPLETE` relayer.with_supervisor(|| { let ibc_denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake.rs b/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake.rs index 1a8dbe27ed..2929bf649a 100644 --- a/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake.rs +++ b/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake.rs @@ -11,7 +11,7 @@ use std::thread::sleep; use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeight}; use ibc_relayer_types::core::ics04_channel::packet::Sequence; use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::chain::config::cosmos::{set_max_deposit_period, set_voting_period}; use ibc_test_framework::prelude::*; use ibc_test_framework::relayer::channel::{ assert_eventually_channel_established, assert_eventually_channel_upgrade_open, diff --git a/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake_steps.rs b/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake_steps.rs index 31b665bc9a..c295ab55e4 100644 --- a/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake_steps.rs +++ b/tools/integration-test/src/tests/channel_upgrade/upgrade_handshake_steps.rs @@ -29,7 +29,7 @@ use ibc_relayer::chain::requests::{IncludeProof, QueryChannelRequest, QueryHeigh use ibc_relayer_types::core::ics04_channel::channel::{State as ChannelState, UpgradeState}; use ibc_relayer_types::core::ics04_channel::packet::Sequence; use ibc_relayer_types::core::ics04_channel::version::Version; -use ibc_test_framework::chain::config::{set_max_deposit_period, set_voting_period}; +use ibc_test_framework::chain::config::cosmos::{set_max_deposit_period, set_voting_period}; use ibc_test_framework::prelude::*; use ibc_test_framework::relayer::channel::{ assert_eventually_channel_established, assert_eventually_channel_upgrade_ack, diff --git a/tools/integration-test/src/tests/clear_packet.rs b/tools/integration-test/src/tests/clear_packet.rs index cf09b6dbad..d45fab572d 100644 --- a/tools/integration-test/src/tests/clear_packet.rs +++ b/tools/integration-test/src/tests/clear_packet.rs @@ -122,8 +122,11 @@ impl BinaryChannelTest for DisabledClearPacketTest { sleep(Duration::from_secs(1)); - let amount_b = - amount2.transfer(&channel.port_b.as_ref(), &channel.channel_id_b.as_ref())?; + let amount_b = amount2.transfer( + &chains.node_b.chain_driver().value().chain_type, + &channel.port_b.as_ref(), + &channel.channel_id_b.as_ref(), + )?; // Wallet on chain A should have both amount deducted. chains.node_a.chain_driver().assert_eventual_wallet_amount( @@ -162,7 +165,7 @@ impl BinaryChannelTest for ClearPacketRecoveryTest { channel: ConnectedChannel, ) -> Result<(), Error> { let fee_denom_b: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(1))); + MonoTagged::new(Denom::base(config.native_token(1), config.native_token(1))); let denom_a = chains.node_a.denom(); let denom_b1 = chains.node_b.denom(); @@ -190,6 +193,7 @@ impl BinaryChannelTest for ClearPacketRecoveryTest { )?; let denom_b2 = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -233,7 +237,10 @@ impl BinaryChannelTest for ClearPacketNoScanTest { channel: ConnectedChannel, ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); - let fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_a = MonoTagged::new(Denom::base( + &config.native_tokens[0], + &config.native_tokens[0], + )); let wallet_a = chains.node_a.wallets().user1().cloned(); let wallet_b = chains.node_b.wallets().user1().cloned(); @@ -254,6 +261,7 @@ impl BinaryChannelTest for ClearPacketNoScanTest { )?; let denom_b2 = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -334,7 +342,9 @@ impl TestOverrides for ClearPacketOverrideTest { for chain_config in config.chains.iter_mut() { match chain_config { // Use a small clear interval in the chain configurations to override the global high interval - ChainConfig::CosmosSdk(chain_config) => chain_config.clear_interval = Some(10), + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { + chain_config.clear_interval = Some(10) + } } } } @@ -353,7 +363,10 @@ impl BinaryChannelTest for ClearPacketOverrideTest { channel: ConnectedChannel, ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); - let fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_a = MonoTagged::new(Denom::base( + &config.native_tokens[0], + &config.native_tokens[0], + )); let wallet_a = chains.node_a.wallets().user1().cloned(); let wallet_b = chains.node_b.wallets().user1().cloned(); @@ -374,6 +387,7 @@ impl BinaryChannelTest for ClearPacketOverrideTest { )?; let denom_b2 = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -657,8 +671,11 @@ impl BinaryChannelTest for LimitedClearPacketTest { // Spawn the supervisor only after the first IBC transfer relayer.with_supervisor(|| { - let amount_b = cleared_amount - .transfer(&channel.port_b.as_ref(), &channel.channel_id_b.as_ref())?; + let amount_b = cleared_amount.transfer( + &chains.node_b.chain_driver().value().chain_type, + &channel.port_b.as_ref(), + &channel.channel_id_b.as_ref(), + )?; info!("Assert that {sent_amount} was escrowed from sending chain"); diff --git a/tools/integration-test/src/tests/client_expiration.rs b/tools/integration-test/src/tests/client_expiration.rs index 082cacf70a..234bea6b1c 100644 --- a/tools/integration-test/src/tests/client_expiration.rs +++ b/tools/integration-test/src/tests/client_expiration.rs @@ -7,6 +7,7 @@ use ibc_test_framework::bootstrap::binary::channel::{ bootstrap_channel_with_chains, bootstrap_channel_with_connection, }; use ibc_test_framework::bootstrap::binary::connection::bootstrap_connection; +use ibc_test_framework::chain::chain_type::ChainType; use ibc_test_framework::prelude::*; use ibc_test_framework::relayer::channel::{ assert_eventually_channel_established, init_channel, query_channel_end, @@ -113,7 +114,7 @@ impl TestOverrides for ExpirationTestOverrides { for chain_config in config.chains.iter_mut() { match chain_config { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.trusting_period = Some(CLIENT_EXPIRY); } } @@ -212,8 +213,16 @@ impl BinaryChainTest for ChannelExpirationTest { }, // From simapp version v7.1.0 if `ConnOpenInit` is sent while the client // is expired, an error will be returned. - // See https://github.com/cosmos/ibc-go/blob/v7.1.0/modules/core/03-connection/keeper/handshake.go#L40 - Err(e) => assert!(e.to_string().contains("status is Expired: client state is not active")), + Err(e) => match chains.node_b.chain_driver().value().chain_type { + ChainType::Namada => { + // See https://github.com/cosmos/ibc-rs/blob/v0.53.0/ibc-core/ics02-client/types/src/error.rs#L22 + assert!(e.to_string().contains("client is not active. Status=`Expired`")) + } + _ => { + // See https://github.com/cosmos/ibc-go/blob/v7.1.0/modules/core/03-connection/keeper/handshake.go#L40 + assert!(e.to_string().contains("status is Expired: client state is not active")) + } + } } } @@ -313,6 +322,7 @@ impl BinaryChainTest for PacketExpirationTest { let denom_a = chains.node_a.denom(); let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/client_refresh.rs b/tools/integration-test/src/tests/client_refresh.rs index e29adbb821..32d5ce067e 100644 --- a/tools/integration-test/src/tests/client_refresh.rs +++ b/tools/integration-test/src/tests/client_refresh.rs @@ -19,6 +19,7 @@ fn test_client_fail_refresh() -> Result<(), Error> { run_binary_chain_test(&ClientFailsTest) } +#[allow(dead_code)] struct ClientFailsTest; struct ClientDefaultsTest; @@ -126,12 +127,24 @@ impl BinaryChainTest for ClientFailsTest { chains, |config| { { - let ChainConfig::CosmosSdk(config_chain_a) = &mut config.chains[0]; - config_chain_a.gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); + match &mut config.chains[0] { + ChainConfig::CosmosSdk(config_chain_a) => { + config_chain_a.gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); + } + ChainConfig::Namada(config_chain_a) => { + config_chain_a.gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); + } + } } - let ChainConfig::CosmosSdk(config_chain_b) = &mut config.chains[1]; - config_chain_b.gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); + match &mut config.chains[1] { + ChainConfig::CosmosSdk(config_chain_b) => { + config_chain_b.gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); + } + ChainConfig::Namada(config_chain_b) => { + config_chain_b.gas_multiplier = Some(GasMultiplier::unsafe_new(0.8)); + } + } }, config, )?; @@ -160,6 +173,7 @@ impl BinaryChainTest for ClientFailsTest { } } +#[allow(dead_code)] fn override_connected_chains( chains: ConnectedChains, config_modifier: impl FnOnce(&mut Config), @@ -202,6 +216,7 @@ where Ok(chains) } +#[allow(dead_code)] fn restore_foreign_client_pair( chain_a: &ChainA, chain_b: &ChainB, diff --git a/tools/integration-test/src/tests/client_settings.rs b/tools/integration-test/src/tests/client_settings.rs index 0a3c7656a4..ccaee68b41 100644 --- a/tools/integration-test/src/tests/client_settings.rs +++ b/tools/integration-test/src/tests/client_settings.rs @@ -26,7 +26,7 @@ struct ClientOptionsTest; impl TestOverrides for ClientDefaultsTest { fn modify_relayer_config(&self, config: &mut Config) { match &mut config.chains[0] { - ChainConfig::CosmosSdk(chain_config_a) => { + ChainConfig::CosmosSdk(chain_config_a) | ChainConfig::Namada(chain_config_a) => { chain_config_a.clock_drift = Duration::from_secs(3); chain_config_a.max_block_time = Duration::from_secs(5); chain_config_a.trusting_period = Some(Duration::from_secs(120_000)); @@ -35,7 +35,7 @@ impl TestOverrides for ClientDefaultsTest { } match &mut config.chains[1] { - ChainConfig::CosmosSdk(chain_config_b) => { + ChainConfig::CosmosSdk(chain_config_b) | ChainConfig::Namada(chain_config_b) => { chain_config_b.clock_drift = Duration::from_secs(6); chain_config_b.max_block_time = Duration::from_secs(15); chain_config_b.trusting_period = Some(Duration::from_secs(340_000)); diff --git a/tools/integration-test/src/tests/client_upgrade.rs b/tools/integration-test/src/tests/client_upgrade.rs index 9480a4a105..b420c481a5 100644 --- a/tools/integration-test/src/tests/client_upgrade.rs +++ b/tools/integration-test/src/tests/client_upgrade.rs @@ -21,7 +21,7 @@ use ibc_relayer::chain::requests::QueryHeight; use ibc_relayer::client_state::AnyClientState; use ibc_relayer::upgrade_chain::{build_and_send_ibc_upgrade_proposal, UpgradePlanOptions}; use ibc_relayer_types::core::ics02_client::height::Height; -use ibc_test_framework::chain::config::{ +use ibc_test_framework::chain::config::cosmos::{ set_max_deposit_period, set_min_deposit_amount, set_voting_period, }; use ibc_test_framework::chain::ext::bootstrap::ChainBootstrapMethodsExt; @@ -82,8 +82,10 @@ impl BinaryChainTest for ClientUpgradeTest { chains: ibc_test_framework::prelude::ConnectedChains, ) -> Result<(), ibc_test_framework::prelude::Error> { let upgraded_chain_id = ChainId::new("upgradedibc".to_owned(), 1); - let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_a: MonoTagged = MonoTagged::new(Denom::base( + &config.native_tokens[0], + &config.native_tokens[0], + )); let foreign_clients = chains.clone().foreign_clients; // Create and send an chain upgrade proposal @@ -241,8 +243,10 @@ impl BinaryChainTest for HeightTooHighClientUpgradeTest { chains: ibc_test_framework::prelude::ConnectedChains, ) -> Result<(), ibc_test_framework::prelude::Error> { let upgraded_chain_id = ChainId::new("upgradedibc".to_owned(), 1); - let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_a: MonoTagged = MonoTagged::new(Denom::base( + &config.native_tokens[0], + &config.native_tokens[0], + )); let foreign_clients = chains.clone().foreign_clients; // Create and send an chain upgrade proposal @@ -339,8 +343,10 @@ impl BinaryChainTest for HeightTooLowClientUpgradeTest { chains: ibc_test_framework::prelude::ConnectedChains, ) -> Result<(), ibc_test_framework::prelude::Error> { let upgraded_chain_id = ChainId::new("upgradedibc".to_owned(), 1); - let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_a: MonoTagged = MonoTagged::new(Denom::base( + &config.native_tokens[0], + &config.native_tokens[0], + )); let foreign_clients = chains.clone().foreign_clients; let opts = create_upgrade_plan(config, &chains, &upgraded_chain_id)?; @@ -432,8 +438,10 @@ fn create_upgrade_plan( chains: &ibc_test_framework::prelude::ConnectedChains, upgraded_chain_id: &ChainId, ) -> Result { - let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_a: MonoTagged = MonoTagged::new(Denom::base( + &config.native_tokens[0], + &config.native_tokens[0], + )); let foreign_clients = chains.clone().foreign_clients; let src_client_id = foreign_clients.client_id_b().0.clone(); diff --git a/tools/integration-test/src/tests/connection_delay.rs b/tools/integration-test/src/tests/connection_delay.rs index 0c8ca19e57..43f034f45e 100644 --- a/tools/integration-test/src/tests/connection_delay.rs +++ b/tools/integration-test/src/tests/connection_delay.rs @@ -58,6 +58,7 @@ impl BinaryChannelTest for ConnectionDelayTest { let time1 = OffsetDateTime::now_utc(); let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/consensus_states.rs b/tools/integration-test/src/tests/consensus_states.rs index bfd0891679..b94045d666 100644 --- a/tools/integration-test/src/tests/consensus_states.rs +++ b/tools/integration-test/src/tests/consensus_states.rs @@ -1,9 +1,13 @@ -use ibc_relayer::chain::{ - cosmos::query::consensus_state::query_consensus_states, - requests::{PageRequest, QueryConsensusStateHeightsRequest, QueryConsensusStatesRequest}, +use ibc_relayer::{ + chain::{ + cosmos::query::consensus_state::query_consensus_states, + requests::{PageRequest, QueryConsensusStateHeightsRequest, QueryConsensusStatesRequest}, + }, + config::ChainConfig, }; use ibc_test_framework::prelude::*; +use ibc_test_framework::util::namada; #[test] fn test_consensus_state_heights() -> Result<(), Error> { @@ -48,29 +52,42 @@ impl BinaryChainTest for ConsensusStateHeights { &CONSENSUS_STATES_COUNT, )?; - let grpc_address = chains - .node_b - .value() - .chain_driver - .grpc_address() - .as_str() - .parse() - .unwrap(); + let states = match chains.handle_b().config().expect("Config should exist") { + ChainConfig::Namada(config) => chains.node_b.value().chain_driver.runtime.block_on( + namada::query_consensus_states( + config + .rpc_addr + .to_string() + .parse() + .expect("RPC address should be converted"), + chains.client_id_b().value(), + ), + )?, + _ => { + let grpc_address = chains + .node_b + .value() + .chain_driver + .grpc_address() + .as_str() + .parse() + .unwrap(); - let states = - chains - .node_b - .value() - .chain_driver - .runtime - .block_on(query_consensus_states( - chains.node_b.chain_id().value(), - &grpc_address, - QueryConsensusStatesRequest { - client_id: (*chains.client_id_b().value()).clone(), - pagination: Some(PageRequest::all()), - }, - ))?; + chains + .node_b + .value() + .chain_driver + .runtime + .block_on(query_consensus_states( + chains.node_b.chain_id().value(), + &grpc_address, + QueryConsensusStatesRequest { + client_id: (*chains.client_id_b().value()).clone(), + pagination: Some(PageRequest::all()), + }, + ))? + } + }; assert_eq( "did not find the expected number of consensus states", diff --git a/tools/integration-test/src/tests/denom_trace.rs b/tools/integration-test/src/tests/denom_trace.rs index 3c56efbdcb..50dbbd4aa8 100644 --- a/tools/integration-test/src/tests/denom_trace.rs +++ b/tools/integration-test/src/tests/denom_trace.rs @@ -40,6 +40,7 @@ impl BinaryChannelTest for IbcDenomTraceTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -83,7 +84,8 @@ impl BinaryChannelTest for IbcDenomTraceTest { assert_eq( "Denom returned by denom_trace query should be the same as denom_a", &denom_trace.base_denom, - &denom_a.value().as_str().to_string(), + // check the raw address + &denom_a.value().hash_only(), )?; Ok(()) diff --git a/tools/integration-test/src/tests/dynamic_gas_fee.rs b/tools/integration-test/src/tests/dynamic_gas_fee.rs index 3e30ec468d..950e8b9617 100644 --- a/tools/integration-test/src/tests/dynamic_gas_fee.rs +++ b/tools/integration-test/src/tests/dynamic_gas_fee.rs @@ -52,6 +52,7 @@ impl TestOverrides for DynamicGasTest { GasPrice::new(0.1, chain_config_a.gas_price.denom.clone()); chain_config_a.dynamic_gas_price = DynamicGasPrice::unsafe_new(false, 1.1, 0.6); } + ChainConfig::Namada(_) => {} } match &mut config.chains[1] { @@ -61,6 +62,7 @@ impl TestOverrides for DynamicGasTest { chain_config_b.dynamic_gas_price = DynamicGasPrice::unsafe_new(self.dynamic_gas_enabled, 1.1, 0.6); } + ChainConfig::Namada(_) => {} } } @@ -84,15 +86,38 @@ impl BinaryChannelTest for DynamicGasTest { let a_to_b_amount = 12345u64; let denom_a_to_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, )?; + let gas_denom_str_a = match relayer + .config + .chains + .first() + .ok_or_else(|| eyre!("chain configuration is empty"))? + { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { + chain_config.gas_price.denom.clone() + } + }; + + let gas_denom_str_b: String = match relayer + .config + .chains + .get(1) + .ok_or_else(|| eyre!("chain configuration is empty"))? + { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { + chain_config.gas_price.denom.clone() + } + }; + let gas_denom_a: MonoTagged = - MonoTagged::new(Denom::Base("stake".to_owned())); + MonoTagged::new(Denom::base(&gas_denom_str_a, &gas_denom_str_a)); let gas_denom_b: MonoTagged = - MonoTagged::new(Denom::Base("stake".to_owned())); + MonoTagged::new(Denom::base(&gas_denom_str_b, &gas_denom_str_b)); let balance_relayer_b_before = chains.node_b.chain_driver().query_balance( &chains.node_b.wallets().relayer().address(), @@ -148,6 +173,7 @@ impl BinaryChannelTest for DynamicGasTest { let denom_b = chains.node_b.denom(); let denom_b_to_a = derive_ibc_denom( + &chains.node_a.chain_driver().value().chain_type, &channel.port_a.as_ref(), &channel.channel_id_a.as_ref(), &denom_b, diff --git a/tools/integration-test/src/tests/error_events.rs b/tools/integration-test/src/tests/error_events.rs index 24602d0122..af054aac26 100644 --- a/tools/integration-test/src/tests/error_events.rs +++ b/tools/integration-test/src/tests/error_events.rs @@ -1,5 +1,6 @@ use ibc_relayer::chain::tracking::TrackedMsgs; use ibc_relayer_types::events::IbcEvent; +use ibc_test_framework::chain::chain_type::ChainType; use ibc_test_framework::prelude::*; use ibc_test_framework::relayer::transfer::build_transfer_message; @@ -36,24 +37,36 @@ impl BinaryChannelTest for ErrorEventsTest { let balance_a_amount: u128 = balance_a.value().amount.0.as_u128(); - let transfer_message = build_transfer_message( - &channel.port_a.as_ref(), - &channel.channel_id_a.as_ref(), - &wallet_a.as_ref(), - &wallet_b.address(), - &denom_a.with_amount((balance_a_amount / 3) + 1).as_ref(), - Duration::from_secs(30), - None, - )?; + let mut transfer_messages = Vec::new(); + for i in 0..4 { + let transfer_message = build_transfer_message( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount((balance_a_amount / 3) + 1).as_ref(), + Duration::from_secs(30), + // Namada batch transaction can't have the exact same message + Some(i.to_string()), + )?; + transfer_messages.push(transfer_message); + } - let messages = TrackedMsgs::new_static(vec![transfer_message; 4], "test_error_events"); + let messages = TrackedMsgs::new_static(transfer_messages, "test_error_events"); let events = chains.handle_a().send_messages_and_wait_commit(messages)?; - // We expect 4 error events to be returned, corresponding to the - // 4 messages sent. - - assert_eq!(events.len(), 4); + if matches!( + chains.node_a.chain_driver().value().chain_type, + ChainType::Namada + ) { + // Requested the messages with a batched transaction + assert_eq!(events.len(), 1); + } else { + // We expect 4 error events to be returned, corresponding to the + // 4 messages sent. + assert_eq!(events.len(), 4); + } for event_with_height in events { match event_with_height.event { diff --git a/tools/integration-test/src/tests/fee/auto_forward_relayer.rs b/tools/integration-test/src/tests/fee/auto_forward_relayer.rs index ca120394a5..e5aad208ce 100644 --- a/tools/integration-test/src/tests/fee/auto_forward_relayer.rs +++ b/tools/integration-test/src/tests/fee/auto_forward_relayer.rs @@ -76,6 +76,7 @@ impl BinaryChannelTest for AutoForwardRelayerTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/fee/filter_fees.rs b/tools/integration-test/src/tests/fee/filter_fees.rs index 963e93e2d8..b257f66bfd 100644 --- a/tools/integration-test/src/tests/fee/filter_fees.rs +++ b/tools/integration-test/src/tests/fee/filter_fees.rs @@ -22,6 +22,8 @@ struct FilterIncentivizedFeesRelayerTest; impl TestOverrides for FilterIncentivizedFeesRelayerTest { fn modify_relayer_config(&self, config: &mut Config) { + config.mode.packets.clear_on_start = false; + config.mode.packets.clear_interval = 0; config.mode.packets.auto_register_counterparty_payee = true; let recv_fee = MinFee::new(50, Some("samoleans".to_owned())); let fees_filters = FeePolicy::new(vec![recv_fee]); @@ -30,7 +32,7 @@ impl TestOverrides for FilterIncentivizedFeesRelayerTest { let packet_filter = PacketFilter::new(ChannelPolicy::default(), min_fees); for chain_config in config.chains.iter_mut() { match chain_config { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.packet_filter = packet_filter.clone(); } } @@ -92,6 +94,7 @@ impl BinaryChannelTest for FilterIncentivizedFeesRelayerTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -141,6 +144,7 @@ impl BinaryChannelTest for FilterIncentivizedFeesRelayerTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -180,7 +184,7 @@ impl TestOverrides for FilterByChannelIncentivizedFeesRelayerTest { let packet_filter = PacketFilter::new(ChannelPolicy::default(), min_fees); for chain_config in config.chains.iter_mut() { match chain_config { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.packet_filter = packet_filter.clone(); } } @@ -227,6 +231,7 @@ impl BinaryChannelTest for FilterByChannelIncentivizedFeesRelayerTest { let balance_a2 = balance_a1.clone() - send_amount; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/fee/forward_relayer.rs b/tools/integration-test/src/tests/fee/forward_relayer.rs index daa5bcf317..ca91aef498 100644 --- a/tools/integration-test/src/tests/fee/forward_relayer.rs +++ b/tools/integration-test/src/tests/fee/forward_relayer.rs @@ -115,6 +115,7 @@ impl BinaryChannelTest for ForwardRelayerTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/fee/no_forward_relayer.rs b/tools/integration-test/src/tests/fee/no_forward_relayer.rs index 8b840640e8..13683f9cfe 100644 --- a/tools/integration-test/src/tests/fee/no_forward_relayer.rs +++ b/tools/integration-test/src/tests/fee/no_forward_relayer.rs @@ -93,6 +93,7 @@ impl BinaryChannelTest for NoForwardRelayerTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -179,6 +180,7 @@ impl BinaryChannelTest for InvalidForwardRelayerTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/fee/non_fee_channel.rs b/tools/integration-test/src/tests/fee/non_fee_channel.rs index b7b026ae3a..e2c8c44c6a 100644 --- a/tools/integration-test/src/tests/fee/non_fee_channel.rs +++ b/tools/integration-test/src/tests/fee/non_fee_channel.rs @@ -93,6 +93,7 @@ impl BinaryChannelTest for NonFeeChannelTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/fee/pay_fee_async.rs b/tools/integration-test/src/tests/fee/pay_fee_async.rs index dc8f5a816d..73f5ae7e55 100644 --- a/tools/integration-test/src/tests/fee/pay_fee_async.rs +++ b/tools/integration-test/src/tests/fee/pay_fee_async.rs @@ -254,6 +254,7 @@ impl BinaryChannelTest for PayPacketFeeAsyncTest { } let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/fee/register_payee.rs b/tools/integration-test/src/tests/fee/register_payee.rs index 638800c846..9ddab19fe0 100644 --- a/tools/integration-test/src/tests/fee/register_payee.rs +++ b/tools/integration-test/src/tests/fee/register_payee.rs @@ -130,6 +130,7 @@ impl BinaryChannelTest for ForwardRelayerTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/fee_grant.rs b/tools/integration-test/src/tests/fee_grant.rs index a936c02e20..2a0a8aa272 100644 --- a/tools/integration-test/src/tests/fee_grant.rs +++ b/tools/integration-test/src/tests/fee_grant.rs @@ -42,7 +42,10 @@ impl BinaryChannelTest for FeeGrantTest { let denom_a = chains.node_a.denom(); let wallet_a = chains.node_a.wallets().user1().cloned(); let wallet_b = chains.node_b.wallets().user1().cloned(); - let fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_a = MonoTagged::new(Denom::base( + &config.native_tokens[0], + &config.native_tokens[0], + )); let a_to_b_amount = 12345u64; let granter = chains @@ -70,6 +73,7 @@ impl BinaryChannelTest for FeeGrantTest { thread::sleep(Duration::from_secs(5)); let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, @@ -81,10 +85,13 @@ impl BinaryChannelTest for FeeGrantTest { .first() .ok_or_else(|| eyre!("chain configuration is empty"))? { - ChainConfig::CosmosSdk(chain_config) => chain_config.gas_price.denom.clone(), + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { + chain_config.gas_price.denom.clone() + } }; - let gas_denom: MonoTagged = MonoTagged::new(Denom::Base(gas_denom_str)); + let gas_denom: MonoTagged = + MonoTagged::new(Denom::base(&gas_denom_str, &gas_denom_str)); let balance_user1_before = chains .node_a @@ -104,7 +111,7 @@ impl BinaryChannelTest for FeeGrantTest { .for_each(|chain_config| { if chain_config.id() == chains.node_a.chain_id().0 { match chain_config { - ChainConfig::CosmosSdk(c) => { + ChainConfig::CosmosSdk(c) | ChainConfig::Namada(c) => { c.fee_granter = Some("user2".to_owned()); } } @@ -185,7 +192,10 @@ impl BinaryChannelTest for NoFeeGrantTest { let wallet_a = chains.node_a.wallets().user1().cloned(); let wallet_a2 = chains.node_a.wallets().user2().cloned(); let wallet_b = chains.node_b.wallets().user1().cloned(); - let fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_a = MonoTagged::new(Denom::base( + &config.native_tokens[0], + &config.native_tokens[0], + )); let a_to_b_amount = 12345u64; let granter = chains @@ -213,6 +223,7 @@ impl BinaryChannelTest for NoFeeGrantTest { thread::sleep(Duration::from_secs(5)); let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, @@ -224,10 +235,13 @@ impl BinaryChannelTest for NoFeeGrantTest { .first() .ok_or_else(|| eyre!("chain configuration is empty"))? { - ChainConfig::CosmosSdk(chain_config) => chain_config.gas_price.denom.clone(), + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { + chain_config.gas_price.denom.clone() + } }; - let gas_denom: MonoTagged = MonoTagged::new(Denom::Base(gas_denom_str)); + let gas_denom: MonoTagged = + MonoTagged::new(Denom::base(&gas_denom_str, &gas_denom_str)); let balance_user1_before = chains .node_a diff --git a/tools/integration-test/src/tests/forward/forward_hop_transfer.rs b/tools/integration-test/src/tests/forward/forward_hop_transfer.rs index f42376c5b7..b86211233d 100644 --- a/tools/integration-test/src/tests/forward/forward_hop_transfer.rs +++ b/tools/integration-test/src/tests/forward/forward_hop_transfer.rs @@ -67,24 +67,28 @@ impl NaryChannelTest<4> for IbcForwardHopTransferTest { let denom_a = connected_chains.node_a.denom(); let denom_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_c = derive_ibc_denom( + &node_c.chain_driver().value().chain_type, &channel_b_to_c.port_b.as_ref(), &channel_b_to_c.channel_id_b.as_ref(), &denom_b.as_ref(), )?; let denom_a_to_d = derive_ibc_denom( + &node_d.chain_driver().value().chain_type, &channel_c_to_d.port_b.as_ref(), &channel_c_to_d.channel_id_b.as_ref(), &denom_a_to_c.as_ref(), @@ -188,24 +192,28 @@ impl NaryChannelTest<4> for AtomicIbcForwardHopTransferTest { let denom_a = connected_chains.node_a.denom(); let denom_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_c = derive_ibc_denom( + &node_c.chain_driver().value().chain_type, &channel_b_to_c.port_b.as_ref(), &channel_b_to_c.channel_id_b.as_ref(), &denom_b.as_ref(), )?; let denom_a_to_d = derive_ibc_denom( + &node_d.chain_driver().value().chain_type, &channel_c_to_d.port_b.as_ref(), &channel_c_to_d.channel_id_b.as_ref(), &denom_a_to_c.as_ref(), diff --git a/tools/integration-test/src/tests/forward/forward_transfer.rs b/tools/integration-test/src/tests/forward/forward_transfer.rs index a9569c8528..acef77d626 100644 --- a/tools/integration-test/src/tests/forward/forward_transfer.rs +++ b/tools/integration-test/src/tests/forward/forward_transfer.rs @@ -85,18 +85,21 @@ impl NaryChannelTest<3> for IbcForwardTransferTest { let denom_a = connected_chains.node_a.denom(); let denom_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_c = derive_ibc_denom( + &node_c.chain_driver().value().chain_type, &channel_b_to_c.port_b.as_ref(), &channel_b_to_c.channel_id_b.as_ref(), &denom_b.as_ref(), @@ -188,18 +191,21 @@ impl NaryChannelTest<3> for MisspelledMemoFieldsIbcForwardTransferTest { let denom_a = connected_chains.node_a.denom(); let denom_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_c = derive_ibc_denom( + &node_c.chain_driver().value().chain_type, &channel_b_to_c.port_b.as_ref(), &channel_b_to_c.channel_id_b.as_ref(), &denom_b.as_ref(), @@ -434,18 +440,21 @@ impl NaryChannelTest<3> for MisspelledMemoContentIbcForwardTransferTest { let denom_a = connected_chains.node_a.denom(); let denom_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, )?; let denom_a_to_c = derive_ibc_denom( + &node_c.chain_driver().value().chain_type, &channel_b_to_c.port_b.as_ref(), &channel_b_to_c.channel_id_b.as_ref(), &denom_b.as_ref(), diff --git a/tools/integration-test/src/tests/ica.rs b/tools/integration-test/src/tests/ica.rs index 0fe90d43ad..a6fb40408f 100644 --- a/tools/integration-test/src/tests/ica.rs +++ b/tools/integration-test/src/tests/ica.rs @@ -17,7 +17,7 @@ use ibc_relayer_types::timestamp::Timestamp; use ibc_relayer_types::tx_msg::Msg; use ibc_test_framework::chain::{ - config::add_allow_message_interchainaccounts, + config::cosmos::add_allow_message_interchainaccounts, ext::ica::{register_ordered_interchain_account, register_unordered_interchain_account}, }; use ibc_test_framework::prelude::*; @@ -71,7 +71,7 @@ impl TestOverrides for IcaFilterTestAllow { for chain in &mut config.chains { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.packet_filter = self.packet_filter.clone(); } } @@ -95,7 +95,7 @@ impl BinaryConnectionTest for IcaFilterTestAllow { connection: ConnectedConnection, ) -> Result<(), Error> { let fee_denom_host: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(1))); + MonoTagged::new(Denom::base(config.native_token(1), config.native_token(1))); // Register an interchain account on behalf of // controller wallet `user1` where the counterparty chain is the interchain accounts host. let (wallet, channel_id, port_id) = @@ -115,7 +115,7 @@ impl BinaryConnectionTest for IcaFilterTestAllow { .chain_driver() .query_interchain_account(&wallet.address(), &connection.connection_id_a.as_ref())?; - let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); + let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake", "stake")); chains.node_b.chain_driver().assert_eventual_wallet_amount( &ica_address.as_ref(), @@ -188,7 +188,7 @@ impl TestOverrides for IcaFilterTestDeny { for chain in &mut config.chains { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.packet_filter.channel_policy = ChannelPolicy::Deny(ChannelFilters::new(vec![( FilterPattern::Wildcard("ica*".parse().unwrap()), @@ -252,8 +252,8 @@ impl BinaryConnectionTest for ICACloseChannelTest { connection: ConnectedConnection, ) -> Result<(), Error> { let fee_denom_host: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(1))); - let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); + MonoTagged::new(Denom::base(config.native_token(1), config.native_token(1))); + let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake", "stake")); let (wallet, ica_address, controller_channel_id, controller_port_id) = relayer .with_supervisor(|| { // Register an interchain account on behalf of diff --git a/tools/integration-test/src/tests/ics20_filter/memo.rs b/tools/integration-test/src/tests/ics20_filter/memo.rs index 0ec207af37..ca696ec150 100644 --- a/tools/integration-test/src/tests/ics20_filter/memo.rs +++ b/tools/integration-test/src/tests/ics20_filter/memo.rs @@ -71,6 +71,7 @@ impl BinaryChannelTest for IbcMemoFilterTest { info!("Assert that the IBC transfer was filtered"); let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/ics31.rs b/tools/integration-test/src/tests/ics31.rs index 33065dc091..54e7408e78 100644 --- a/tools/integration-test/src/tests/ics31.rs +++ b/tools/integration-test/src/tests/ics31.rs @@ -13,7 +13,7 @@ use ibc_relayer::config::{self, ModeConfig}; use ibc_test_framework::chain::{ cli::host_zone::register_host_zone, - config::{ + config::cosmos::{ set_crisis_denom, set_mint_mint_denom, set_staking_bond_denom, set_staking_max_entries, set_voting_period, }, @@ -101,6 +101,7 @@ impl BinaryChannelTest for ICS31Test { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs b/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs index 3d2f217554..e45d3dfd78 100644 --- a/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs +++ b/tools/integration-test/src/tests/interchain_security/dynamic_gas_fee.rs @@ -80,7 +80,7 @@ impl TestOverrides for DynamicGasTest { update_relayer_config_for_consumer_chain(config); match &mut config.chains[0] { - ChainConfig::CosmosSdk(chain_config_a) => { + ChainConfig::CosmosSdk(chain_config_a) | ChainConfig::Namada(chain_config_a) => { chain_config_a.gas_price = GasPrice::new(0.3, chain_config_a.gas_price.denom.clone()); @@ -89,7 +89,7 @@ impl TestOverrides for DynamicGasTest { } match &mut config.chains[1] { - ChainConfig::CosmosSdk(chain_config_b) => { + ChainConfig::CosmosSdk(chain_config_b) | ChainConfig::Namada(chain_config_b) => { chain_config_b.gas_price = GasPrice::new(0.3, chain_config_b.gas_price.denom.clone()); @@ -121,15 +121,14 @@ impl BinaryChannelTest for DynamicGasTest { let a_to_b_amount = 12345u64; let denom_a_to_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, )?; - let gas_denom_a: MonoTagged = - MonoTagged::new(Denom::Base("stake".to_owned())); - let gas_denom_b: MonoTagged = - MonoTagged::new(Denom::Base("stake".to_owned())); + let gas_denom_a: MonoTagged = MonoTagged::new(Denom::base("stake", "stake")); + let gas_denom_b: MonoTagged = MonoTagged::new(Denom::base("stake", "stake")); let balance_relayer_b_before = chains.node_b.chain_driver().query_balance( &chains.node_b.wallets().relayer().address(), @@ -185,6 +184,7 @@ impl BinaryChannelTest for DynamicGasTest { let denom_b = chains.node_b.denom(); let denom_b_to_a = derive_ibc_denom( + &chains.node_a.chain_driver().value().chain_type, &channel.port_a.as_ref(), &channel.channel_id_a.as_ref(), &denom_b, diff --git a/tools/integration-test/src/tests/interchain_security/ica_ordered_channel.rs b/tools/integration-test/src/tests/interchain_security/ica_ordered_channel.rs index 7498d724f2..651a96f404 100644 --- a/tools/integration-test/src/tests/interchain_security/ica_ordered_channel.rs +++ b/tools/integration-test/src/tests/interchain_security/ica_ordered_channel.rs @@ -17,7 +17,7 @@ use ibc_relayer_types::bigint::U256; use ibc_relayer_types::signer::Signer; use ibc_relayer_types::timestamp::Timestamp; use ibc_relayer_types::tx_msg::Msg; -use ibc_test_framework::chain::config::add_allow_message_interchainaccounts; +use ibc_test_framework::chain::config::cosmos::add_allow_message_interchainaccounts; use ibc_test_framework::chain::ext::ica::register_ordered_interchain_account; use ibc_test_framework::framework::binary::channel::run_binary_interchain_security_channel_test; use ibc_test_framework::prelude::*; @@ -72,7 +72,7 @@ impl BinaryChannelTest for IcaOrderedChannelTest { channel: ConnectedChannel, ) -> Result<(), Error> { let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(0))); + MonoTagged::new(Denom::base(config.native_token(0), config.native_token(0))); let connection_b_to_a = channel.connection.clone().flip(); let (wallet, channel_id, port_id) = register_ordered_interchain_account( &chains.node_b, @@ -104,7 +104,7 @@ impl BinaryChannelTest for IcaOrderedChannelTest { &channel.connection.connection_id_b.as_ref(), )?; - let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); + let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake", "stake")); chains.node_a.chain_driver().assert_eventual_wallet_amount( &ica_address.as_ref(), diff --git a/tools/integration-test/src/tests/interchain_security/ica_transfer.rs b/tools/integration-test/src/tests/interchain_security/ica_transfer.rs index ec12f6b591..dfedfc9951 100644 --- a/tools/integration-test/src/tests/interchain_security/ica_transfer.rs +++ b/tools/integration-test/src/tests/interchain_security/ica_transfer.rs @@ -11,7 +11,7 @@ use ibc_relayer_types::bigint::U256; use ibc_relayer_types::signer::Signer; use ibc_relayer_types::timestamp::Timestamp; use ibc_relayer_types::tx_msg::Msg; -use ibc_test_framework::chain::config::add_allow_message_interchainaccounts; +use ibc_test_framework::chain::config::cosmos::add_allow_message_interchainaccounts; use ibc_test_framework::chain::ext::ica::register_unordered_interchain_account; use ibc_test_framework::framework::binary::channel::run_binary_interchain_security_channel_test; use ibc_test_framework::prelude::*; @@ -55,7 +55,7 @@ impl BinaryChannelTest for InterchainSecurityIcaTransferTest { channel: ConnectedChannel, ) -> Result<(), Error> { let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(0))); + MonoTagged::new(Denom::base(config.native_token(0), config.native_token(0))); let connection_b_to_a = channel.connection.clone().flip(); let (wallet, channel_id, port_id) = register_unordered_interchain_account( &chains.node_b, @@ -77,7 +77,7 @@ impl BinaryChannelTest for InterchainSecurityIcaTransferTest { &channel.connection.connection_id_b.as_ref(), )?; - let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake")); + let stake_denom: MonoTagged = MonoTagged::new(Denom::base("stake", "stake")); chains.node_a.chain_driver().assert_eventual_wallet_amount( &ica_address.as_ref(), diff --git a/tools/integration-test/src/tests/interchain_security/icq.rs b/tools/integration-test/src/tests/interchain_security/icq.rs index 19f2a84efb..5e940b7055 100644 --- a/tools/integration-test/src/tests/interchain_security/icq.rs +++ b/tools/integration-test/src/tests/interchain_security/icq.rs @@ -11,7 +11,7 @@ use ibc_relayer::config::ChainConfig; use ibc_test_framework::chain::cli::host_zone::register_host_zone; -use ibc_test_framework::chain::config::{ +use ibc_test_framework::chain::config::cosmos::{ set_crisis_denom, set_mint_mint_denom, set_staking_bond_denom, set_staking_max_entries, set_voting_period, }; @@ -92,7 +92,7 @@ impl TestOverrides for InterchainSecurityIcqTest { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.allow_ccq = self.allow_ccq; } } @@ -130,6 +130,7 @@ impl BinaryChannelTest for InterchainSecurityIcqTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/interchain_security/simple_transfer.rs b/tools/integration-test/src/tests/interchain_security/simple_transfer.rs index 05317917ed..1d6afed1e5 100644 --- a/tools/integration-test/src/tests/interchain_security/simple_transfer.rs +++ b/tools/integration-test/src/tests/interchain_security/simple_transfer.rs @@ -69,6 +69,7 @@ impl BinaryChannelTest for InterchainSecurityTransferTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/manual/simulation.rs b/tools/integration-test/src/tests/manual/simulation.rs index 30c801bfcf..827f4ba969 100644 --- a/tools/integration-test/src/tests/manual/simulation.rs +++ b/tools/integration-test/src/tests/manual/simulation.rs @@ -29,7 +29,7 @@ impl TestOverrides for SimulationTest { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.max_msg_num = MaxMsgNum::new(MAX_MSGS).unwrap(); } } diff --git a/tools/integration-test/src/tests/memo.rs b/tools/integration-test/src/tests/memo.rs index cf59bb712d..79483127ef 100644 --- a/tools/integration-test/src/tests/memo.rs +++ b/tools/integration-test/src/tests/memo.rs @@ -6,6 +6,7 @@ use ibc_relayer::config::types::Memo; use ibc_relayer::config::ChainConfig; +use ibc_test_framework::util::namada::query_receive_tx_memo; use serde_json as json; use ibc_test_framework::prelude::*; @@ -35,7 +36,7 @@ impl TestOverrides for MemoTest { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.memo_prefix = self.memo.clone(); } } @@ -69,6 +70,7 @@ impl BinaryChannelTest for MemoTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -79,12 +81,7 @@ impl BinaryChannelTest for MemoTest { &denom_b.with_amount(a_to_b_amount).as_ref(), )?; - let tx_info = chains - .node_b - .chain_driver() - .query_recipient_transactions(&chains.node_b.wallets().user1().address())?; - - assert_tx_memo_equals(&tx_info, self.memo.as_str())?; + assert_tx_memo_equals(&chains, &channel, self.memo.as_str())?; Ok(()) } @@ -98,7 +95,7 @@ impl TestOverrides for MemoOverwriteTest { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.memo_prefix = self.memo.clone(); chain_config.memo_overwrite = Some(Memo::new(OVERWRITE_MEMO).unwrap()) } @@ -133,6 +130,7 @@ impl BinaryChannelTest for MemoOverwriteTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -143,18 +141,13 @@ impl BinaryChannelTest for MemoOverwriteTest { &denom_b.with_amount(a_to_b_amount).as_ref(), )?; - let tx_info = chains - .node_b - .chain_driver() - .query_recipient_transactions(&chains.node_b.wallets().user1().address())?; - - assert_tx_memo_equals(&tx_info, OVERWRITE_MEMO)?; + assert_tx_memo_equals(&chains, &channel, OVERWRITE_MEMO)?; Ok(()) } } -fn assert_tx_memo_equals(tx_info: &json::Value, expected_memo: &str) -> Result<(), Error> { +fn get_tx_memo(tx_info: &json::Value) -> Result { debug!("comparing memo field from json value {}", tx_info); let memo_field = &tx_info["txs"][0]["tx"]["body"]["memo"]; @@ -165,7 +158,44 @@ fn assert_tx_memo_equals(tx_info: &json::Value, expected_memo: &str) -> Result<( .as_str() .ok_or_else(|| eyre!("expect memo string field to be present in JSON"))?; - assert_eq!(memo_str, expected_memo); + Ok(memo_str.to_string()) +} + +fn assert_tx_memo_equals( + chains: &ConnectedChains, + channel: &ConnectedChannel, + expected_memo: &str, +) -> Result<(), Error> { + let memo = match chains.handle_b().config().expect("Config should exist") { + ChainConfig::Namada(config) => { + chains + .node_b + .chain_driver() + .value() + .runtime + .block_on(query_receive_tx_memo( + config + .rpc_addr + .to_string() + .parse() + .expect("RPC address should be converted"), + channel.port_a.value(), + channel.channel_id_a.value(), + channel.port_b.value(), + channel.channel_id_b.value(), + 1.into(), + ))? + } + _ => { + let tx_info = chains + .node_b + .chain_driver() + .query_recipient_transactions(&chains.node_b.wallets().user1().address())?; + + get_tx_memo(&tx_info)? + } + }; + assert_eq!(memo, expected_memo); Ok(()) } diff --git a/tools/integration-test/src/tests/mod.rs b/tools/integration-test/src/tests/mod.rs index e8812377d6..d5e6411d8f 100644 --- a/tools/integration-test/src/tests/mod.rs +++ b/tools/integration-test/src/tests/mod.rs @@ -10,7 +10,7 @@ pub mod client_expiration; pub mod client_filter; pub mod client_refresh; pub mod client_settings; -#[cfg(not(feature = "celestia"))] +#[cfg(not(any(feature = "celestia", feature = "namada")))] pub mod client_upgrade; pub mod connection_delay; pub mod consensus_states; @@ -21,13 +21,12 @@ pub mod execute_schedule; pub mod handshake_on_start; pub mod ics20_filter; pub mod memo; +#[cfg(not(feature = "namada"))] pub mod python; pub mod query_packet; -#[cfg(not(feature = "celestia"))] -pub mod sequence_filter; pub mod supervisor; pub mod tendermint; -#[cfg(not(feature = "celestia"))] +#[cfg(not(any(feature = "celestia")))] pub mod ternary_transfer; pub mod transfer; diff --git a/tools/integration-test/src/tests/ordered_channel.rs b/tools/integration-test/src/tests/ordered_channel.rs index a72126d3f2..1d9b3b99da 100644 --- a/tools/integration-test/src/tests/ordered_channel.rs +++ b/tools/integration-test/src/tests/ordered_channel.rs @@ -94,6 +94,7 @@ impl BinaryChannelTest for OrderedChannelTest { sleep(Duration::from_secs(1)); let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/ordered_channel_clear.rs b/tools/integration-test/src/tests/ordered_channel_clear.rs index ed6e124e64..f687196419 100644 --- a/tools/integration-test/src/tests/ordered_channel_clear.rs +++ b/tools/integration-test/src/tests/ordered_channel_clear.rs @@ -51,7 +51,7 @@ impl TestOverrides for OrderedChannelClearTest { { let chain_a = &mut config.chains[0]; match chain_a { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.sequential_batch_tx = self.sequential_batch_tx; } } @@ -59,7 +59,7 @@ impl TestOverrides for OrderedChannelClearTest { let chain_b = &mut config.chains[1]; match chain_b { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.sequential_batch_tx = self.sequential_batch_tx; } } @@ -157,6 +157,7 @@ impl BinaryChannelTest for OrderedChannelClearTest { sleep(Duration::from_secs(10)); let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, @@ -196,7 +197,7 @@ impl TestOverrides for OrderedChannelClearEqualCLITest { { let chain_a = &mut config.chains[0]; match chain_a { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.sequential_batch_tx = true; chain_config.max_msg_num = MaxMsgNum::new(3).unwrap(); } @@ -205,7 +206,7 @@ impl TestOverrides for OrderedChannelClearEqualCLITest { let chain_b = &mut config.chains[1]; match chain_b { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.sequential_batch_tx = true; chain_config.max_msg_num = MaxMsgNum::new(3).unwrap(); } diff --git a/tools/integration-test/src/tests/python.rs b/tools/integration-test/src/tests/python.rs index 29d6457885..96c77e8ba1 100644 --- a/tools/integration-test/src/tests/python.rs +++ b/tools/integration-test/src/tests/python.rs @@ -10,7 +10,7 @@ impl TestOverrides for PythonTest { fn modify_relayer_config(&self, config: &mut Config) { for chain in config.chains.iter_mut() { match chain { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { // Modify the key store type to `Store::Test` so that the wallet // keys are stored to ~/.hermes/keys so that we can use them // with external relayer commands. diff --git a/tools/integration-test/src/tests/sequence_filter.rs b/tools/integration-test/src/tests/sequence_filter.rs index a880f7720e..52e80d8f5a 100644 --- a/tools/integration-test/src/tests/sequence_filter.rs +++ b/tools/integration-test/src/tests/sequence_filter.rs @@ -52,7 +52,7 @@ impl TestOverrides for FilterClearOnStartTest { excluded_sequences.insert(ChannelId::new(2), vec![2.into()]); let chain_a = &mut config.chains[0]; match chain_a { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.excluded_sequences = ExcludedSequences::new(excluded_sequences); } } @@ -89,7 +89,7 @@ impl TestOverrides for FilterClearIntervalTest { excluded_sequences.insert(ChannelId::new(2), vec![2.into()]); let chain_a = &mut config.chains[0]; match chain_a { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.excluded_sequences = ExcludedSequences::new(excluded_sequences); } } @@ -248,7 +248,7 @@ impl TestOverrides for StandardRelayingNoFilterTest { excluded_sequences.insert(ChannelId::new(2), vec![2.into()]); let chain_a = &mut config.chains[0]; match chain_a { - ChainConfig::CosmosSdk(chain_config) => { + ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { chain_config.excluded_sequences = ExcludedSequences::new(excluded_sequences); } } diff --git a/tools/integration-test/src/tests/supervisor.rs b/tools/integration-test/src/tests/supervisor.rs index 17ee1b5af7..5ff051962c 100644 --- a/tools/integration-test/src/tests/supervisor.rs +++ b/tools/integration-test/src/tests/supervisor.rs @@ -56,9 +56,9 @@ impl BinaryChainTest for SupervisorTest { chains: ConnectedChains, ) -> Result<(), Error> { let fee_denom_a: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(0))); + MonoTagged::new(Denom::base(config.native_token(0), config.native_token(0))); let fee_denom_b: MonoTagged = - MonoTagged::new(Denom::base(config.native_token(1))); + MonoTagged::new(Denom::base(config.native_token(1), config.native_token(1))); let (connection_id_b, _) = init_connection( &chains.handle_a, &chains.handle_b, @@ -95,7 +95,12 @@ impl BinaryChainTest for SupervisorTest { let denom_a = chains.node_a.denom(); - let denom_b = derive_ibc_denom(&port_b.as_ref(), &channel_id_b.as_ref(), &denom_a)?; + let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, + &port_b.as_ref(), + &channel_id_b.as_ref(), + &denom_a, + )?; // Use the same wallet as the relayer to perform token transfer. // This will cause an account sequence mismatch error. @@ -199,9 +204,13 @@ impl BinaryChannelTest for SupervisorScanTest { channels: ConnectedChannel, ) -> Result<(), Error> { let denom_a = chains.node_a.denom(); - let fee_denom_a = MonoTagged::new(Denom::base(config.native_token(0))); + let fee_denom_a = MonoTagged::new(Denom::base( + &config.native_tokens[0], + &config.native_tokens[0], + )); let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channels.port_b.as_ref(), &channels.channel_id_b.as_ref(), &denom_a, diff --git a/tools/integration-test/src/tests/tendermint/sequential.rs b/tools/integration-test/src/tests/tendermint/sequential.rs index be9d254873..6bd106dc53 100644 --- a/tools/integration-test/src/tests/tendermint/sequential.rs +++ b/tools/integration-test/src/tests/tendermint/sequential.rs @@ -3,6 +3,7 @@ use std::time::Instant; use ibc_relayer::chain::tracking::TrackedMsgs; use ibc_relayer::config::types::max_msg_num::MaxMsgNum; use ibc_relayer::config::ChainConfig; +use ibc_test_framework::chain::chain_type::ChainType; use ibc_test_framework::chain::config; use ibc_test_framework::prelude::*; use ibc_test_framework::relayer::transfer::build_transfer_message; @@ -22,11 +23,20 @@ pub struct SequentialCommitTest; impl TestOverrides for SequentialCommitTest { fn modify_node_config(&self, config: &mut toml::Value) -> Result<(), Error> { - config::set_timeout_commit(config, BLOCK_TIME)?; - config::set_timeout_propose(config, BLOCK_TIME)?; + let config = if let Some(config) = config.get_mut("ledger") { + // Namada + config + .get_mut("cometbft") + .ok_or_else(|| eyre!("expect cometbft section"))? + } else { + config + }; + + config::cosmos::set_timeout_commit(config, BLOCK_TIME)?; + config::cosmos::set_timeout_propose(config, BLOCK_TIME)?; // Enable priority mempool - config::set_mempool_version(config, "v1")?; + config::cosmos::set_mempool_version(config, "v1")?; Ok(()) } @@ -34,14 +44,14 @@ impl TestOverrides for SequentialCommitTest { fn modify_relayer_config(&self, config: &mut Config) { // Use sequential batching for chain A, and default parallel batching for chain B match &mut config.chains[0] { - ChainConfig::CosmosSdk(chain_config_a) => { + ChainConfig::CosmosSdk(chain_config_a) | ChainConfig::Namada(chain_config_a) => { chain_config_a.max_msg_num = MaxMsgNum::new(MESSAGES_PER_BATCH).unwrap(); chain_config_a.sequential_batch_tx = true; } }; match &mut config.chains[1] { - ChainConfig::CosmosSdk(chain_config_b) => { + ChainConfig::CosmosSdk(chain_config_b) | ChainConfig::Namada(chain_config_b) => { chain_config_b.max_msg_num = MaxMsgNum::new(MESSAGES_PER_BATCH).unwrap(); chain_config_b.sequential_batch_tx = false; } @@ -67,20 +77,22 @@ impl BinaryChannelTest for SequentialCommitTest { { let denom_a = chains.node_a.denom(); - let transfer_message = build_transfer_message( - &channel.port_a.as_ref(), - &channel.channel_id_a.as_ref(), - &wallet_a.as_ref(), - &wallet_b.address(), - &denom_a.with_amount(100u64).as_ref(), - Duration::from_secs(30), - None, - )?; - - let messages = TrackedMsgs::new_static( - vec![transfer_message; TOTAL_MESSAGES], - "test_error_events", - ); + let mut transfer_messages = Vec::new(); + for i in 0..TOTAL_MESSAGES { + let transfer_message = build_transfer_message( + &channel.port_a.as_ref(), + &channel.channel_id_a.as_ref(), + &wallet_a.as_ref(), + &wallet_b.address(), + &denom_a.with_amount(100u64).as_ref(), + Duration::from_secs(30), + // Namada batch transaction can't have the exact same message + Some(i.to_string()), + )?; + transfer_messages.push(transfer_message); + } + + let messages = TrackedMsgs::new_static(transfer_messages, "test_sequential_commit"); let start = Instant::now(); @@ -95,35 +107,49 @@ impl BinaryChannelTest for SequentialCommitTest { TOTAL_MESSAGES, duration ); - // Time taken for submitting sequential batches should be around number of transactions * block time - - assert!( - duration - > Duration::from_millis((BLOCK_TIME_MILLIS * TOTAL_TRANSACTIONS as u64) - 1000) - ); - assert!( - duration - < Duration::from_millis((BLOCK_TIME_MILLIS * TOTAL_TRANSACTIONS as u64) + 1000) - ); + let (min_duration, max_duration) = match chains.node_a.chain_driver().value().chain_type + { + ChainType::Namada => ( + Duration::from_millis((BLOCK_TIME_MILLIS * TOTAL_TRANSACTIONS as u64) - 1000), + Duration::from_millis( + (BLOCK_TIME_MILLIS * TOTAL_TRANSACTIONS as u64 * 2) + 1000, + ), + ), + _ => { + // Time taken for submitting sequential batches should be around number of transactions * block time + ( + Duration::from_millis( + (BLOCK_TIME_MILLIS * TOTAL_TRANSACTIONS as u64) - 1000, + ), + Duration::from_millis( + (BLOCK_TIME_MILLIS * TOTAL_TRANSACTIONS as u64) + 1000, + ), + ) + } + }; + assert!(duration > min_duration); + assert!(duration < max_duration); } { let denom_b = chains.node_b.denom(); - let transfer_message = build_transfer_message( - &channel.port_b.as_ref(), - &channel.channel_id_b.as_ref(), - &wallet_b.as_ref(), - &wallet_a.address(), - &denom_b.with_amount(100u64).as_ref(), - Duration::from_secs(30), - None, - )?; - - let messages = TrackedMsgs::new_static( - vec![transfer_message; TOTAL_MESSAGES], - "test_error_events", - ); + let mut transfer_messages = Vec::new(); + for i in 0..TOTAL_MESSAGES { + let transfer_message = build_transfer_message( + &channel.port_b.as_ref(), + &channel.channel_id_b.as_ref(), + &wallet_b.as_ref(), + &wallet_a.address(), + &denom_b.with_amount(100u64).as_ref(), + Duration::from_secs(30), + // Namada batch transaction can't have the exact same message + Some(i.to_string()), + )?; + transfer_messages.push(transfer_message); + } + + let messages = TrackedMsgs::new_static(transfer_messages, "test_sequential_commit"); let start = Instant::now(); @@ -141,7 +167,14 @@ impl BinaryChannelTest for SequentialCommitTest { TOTAL_MESSAGES, duration ); - assert!(duration < Duration::from_millis(BLOCK_TIME_MILLIS * 2)); + let max_duration = match chains.node_b.chain_driver().value().chain_type { + ChainType::Namada => { + // Shorter than the sequential batches + Duration::from_millis(BLOCK_TIME_MILLIS * TOTAL_TRANSACTIONS as u64 * 2) + } + _ => Duration::from_millis(BLOCK_TIME_MILLIS * 2), + }; + assert!(duration < max_duration); } Ok(()) diff --git a/tools/integration-test/src/tests/ternary_transfer.rs b/tools/integration-test/src/tests/ternary_transfer.rs index 527c085629..945c1e8417 100644 --- a/tools/integration-test/src/tests/ternary_transfer.rs +++ b/tools/integration-test/src/tests/ternary_transfer.rs @@ -66,6 +66,7 @@ impl NaryChannelTest<3> for TernaryIbcTransferTest { )?; let denom_a_to_b = derive_ibc_denom( + &node_b.chain_driver().value().chain_type, &channel_a_to_b.port_b.as_ref(), &channel_a_to_b.channel_id_b.as_ref(), &denom_a, @@ -97,6 +98,7 @@ impl NaryChannelTest<3> for TernaryIbcTransferTest { let channel_b_to_c = channels.channel_at::<1, 2>()?; let denom_a_to_c = derive_ibc_denom( + &node_c.chain_driver().value().chain_type, &channel_b_to_c.port_b.as_ref(), &channel_b_to_c.channel_id_b.as_ref(), &denom_a_to_b.as_ref(), @@ -134,6 +136,7 @@ impl NaryChannelTest<3> for TernaryIbcTransferTest { let channel_c_to_a = channels.channel_at::<2, 0>()?; let denom_a_to_c_to_a = derive_ibc_denom( + &node_a.chain_driver().value().chain_type, &channel_c_to_a.port_b.as_ref(), &channel_c_to_a.channel_id_b.as_ref(), &denom_a_to_c.as_ref(), diff --git a/tools/integration-test/src/tests/transfer.rs b/tools/integration-test/src/tests/transfer.rs index f117dc742f..3e2a4cf014 100644 --- a/tools/integration-test/src/tests/transfer.rs +++ b/tools/integration-test/src/tests/transfer.rs @@ -69,7 +69,7 @@ impl BinaryChannelTest for IbcTransferTest { chains.chain_id_a(), chains.chain_id_b(), a_to_b_amount, - denom_a + denom_a, ); chains.node_a.chain_driver().ibc_transfer_token( @@ -81,14 +81,15 @@ impl BinaryChannelTest for IbcTransferTest { )?; let denom_b = derive_ibc_denom( + &chains.node_b.chain_driver().value().chain_type, &channel.port_b.as_ref(), &channel.channel_id_b.as_ref(), &denom_a, )?; info!( - "Waiting for user on chain B to receive IBC transferred amount of {}", - a_to_b_amount + "Waiting for user on chain B to receive IBC transferred amount of {} {}", + a_to_b_amount, denom_b, ); chains.node_a.chain_driver().assert_eventual_wallet_amount( @@ -115,10 +116,11 @@ impl BinaryChannelTest for IbcTransferTest { let b_to_a_amount = random_u128_range(500, a_to_b_amount); info!( - "Sending IBC transfer from chain {} to chain {} with amount of {}", + "Sending IBC transfer from chain {} to chain {} with amount of {} {}", chains.chain_id_b(), chains.chain_id_a(), b_to_a_amount, + denom_b, ); chains.node_b.chain_driver().ibc_transfer_token( @@ -129,6 +131,12 @@ impl BinaryChannelTest for IbcTransferTest { &denom_b.with_amount(b_to_a_amount).as_ref(), )?; + info!( + "Waiting for user on chain A to receive IBC transferred amount of {} {}", + b_to_a_amount, + balance_c.denom(), + ); + chains.node_b.chain_driver().assert_eventual_wallet_amount( &wallet_b.address(), &denom_b.with_amount(a_to_b_amount - b_to_a_amount).as_ref(), diff --git a/tools/test-framework/Cargo.toml b/tools/test-framework/Cargo.toml index 997b5ddf40..e8b0f2e894 100644 --- a/tools/test-framework/Cargo.toml +++ b/tools/test-framework/Cargo.toml @@ -18,8 +18,14 @@ ibc-relayer-types = { workspace = true } ibc-relayer = { workspace = true } ibc-relayer-cli = { workspace = true } ibc-proto = { workspace = true, features = ["serde"] } +namada_sdk = { workspace = true } +tendermint = { workspace = true } tendermint-rpc = { workspace = true, features = ["http-client", "websocket-client"] } +# for Namada +namada-tendermint = { workspace = true } +namada-tendermint-rpc = { workspace = true, features = ["http-client", "websocket-client"] } + color-eyre = { workspace = true } crossbeam-channel = { workspace = true } eyre = { workspace = true } diff --git a/tools/test-framework/src/bootstrap/binary/chain.rs b/tools/test-framework/src/bootstrap/binary/chain.rs index 365c079e8c..750c56d794 100644 --- a/tools/test-framework/src/bootstrap/binary/chain.rs +++ b/tools/test-framework/src/bootstrap/binary/chain.rs @@ -67,6 +67,9 @@ pub fn bootstrap_chains_with_full_nodes( let registry = new_registry(config.clone()); + // Wait before spawning the chain handle + std::thread::sleep(Duration::from_secs(10)); + // Pass in unique closure expressions `||{}` as the first argument so that // the returned chains are considered different types by Rust. // See [`spawn_chain_handle`] for more details. @@ -211,7 +214,7 @@ pub fn add_key_to_chain_handle( chain: &Chain, wallet: &Wallet, ) -> Result<(), Error> { - let res = chain.add_key(wallet.id.0.clone(), wallet.key.clone().into()); + let res = chain.add_key(wallet.id.0.clone(), wallet.key.clone()); // Ignore error if chain handle already have the given key match res { diff --git a/tools/test-framework/src/bootstrap/consumer.rs b/tools/test-framework/src/bootstrap/consumer.rs index c473ab6c28..e5acabc87a 100644 --- a/tools/test-framework/src/bootstrap/consumer.rs +++ b/tools/test-framework/src/bootstrap/consumer.rs @@ -5,6 +5,7 @@ use eyre::eyre; use std::sync::{Arc, RwLock}; use std::thread; use std::time::Duration; +use toml; use tracing::info; use crate::chain::builder::ChainBuilder; @@ -25,9 +26,9 @@ pub fn bootstrap_consumer_node( provider_chain_driver: &ChainDriver, provider_fee: &String, ) -> Result { - let stake_denom = Denom::base("stake"); + let stake_denom = Denom::base("stake", "stake"); - let denom = Denom::base("samoleans"); + let denom = Denom::base("samoleans", "samoleans"); let initial_amount = random_u128_range(1_000_000_000_000_000_000, 2_000_000_000_000_000_000); @@ -85,34 +86,34 @@ pub fn bootstrap_consumer_node( } ]); chain_driver.update_genesis_file("genesis.json", |genesis| { - config::set_soft_opt_out_threshold(genesis, "0.05")?; - config::consensus_params_max_gas(genesis, "3000000")?; - config::globalfee_minimum_gas_prices(genesis, globalfee_minimum_gas)?; - config::set_retry_delay_period(genesis, "100s")?; + config::cosmos::set_soft_opt_out_threshold(genesis, "0.05")?; + config::cosmos::consensus_params_max_gas(genesis, "3000000")?; + config::cosmos::globalfee_minimum_gas_prices(genesis, globalfee_minimum_gas)?; + config::cosmos::set_retry_delay_period(genesis, "100s")?; Ok(()) })?; let log_level = std::env::var("CHAIN_LOG_LEVEL").unwrap_or_else(|_| "info".to_string()); - chain_driver.update_chain_config("config.toml", |config| { - config::set_log_level(config, &log_level)?; - config::set_rpc_port(config, chain_driver.rpc_port)?; - config::set_p2p_port(config, chain_driver.p2p_port)?; - config::set_pprof_port(config, chain_driver.pprof_port)?; - config::set_timeout_commit(config, Duration::from_secs(1))?; - config::set_timeout_propose(config, Duration::from_secs(1))?; - config::set_mode(config, "validator")?; + chain_driver.update_chain_config("config/config.toml", |config| { + config::cosmos::set_log_level(config, &log_level)?; + config::cosmos::set_rpc_port(config, chain_driver.rpc_port)?; + config::cosmos::set_p2p_port(config, chain_driver.p2p_port)?; + config::cosmos::set_pprof_port(config, chain_driver.pprof_port)?; + config::cosmos::set_timeout_commit(config, Duration::from_secs(1))?; + config::cosmos::set_timeout_propose(config, Duration::from_secs(1))?; + config::cosmos::set_mode(config, "validator")?; config_modifier(config)?; Ok(()) })?; - chain_driver.update_chain_config("app.toml", |config| { - config::set_grpc_port(config, chain_driver.grpc_port)?; - config::disable_grpc_web(config)?; - config::disable_api(config)?; - config::set_minimum_gas_price(config, "0stake")?; + chain_driver.update_chain_config("config/app.toml", |config| { + config::cosmos::set_grpc_port(config, chain_driver.grpc_port)?; + config::cosmos::disable_grpc_web(config)?; + config::cosmos::disable_api(config)?; + config::cosmos::set_minimum_gas_price(config, "0stake")?; Ok(()) })?; diff --git a/tools/test-framework/src/bootstrap/mod.rs b/tools/test-framework/src/bootstrap/mod.rs index 17216d9455..b31132f5b6 100644 --- a/tools/test-framework/src/bootstrap/mod.rs +++ b/tools/test-framework/src/bootstrap/mod.rs @@ -14,5 +14,6 @@ pub mod binary; pub mod consumer; pub mod init; +pub mod namada; pub mod nary; pub mod single; diff --git a/tools/test-framework/src/bootstrap/namada.rs b/tools/test-framework/src/bootstrap/namada.rs new file mode 100644 index 0000000000..608a35f6ce --- /dev/null +++ b/tools/test-framework/src/bootstrap/namada.rs @@ -0,0 +1,328 @@ +/*! + Helper functions for bootstrapping a single full node. +*/ +use core::time::Duration; +use eyre::eyre; +use std::env; +use std::path::PathBuf; +use std::sync::{Arc, RwLock}; +use toml; + +use ibc_relayer::chain::namada::wallet::CliWalletUtils; +use ibc_relayer::keyring::{KeyRing, NamadaKeyPair, Store}; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; + +use crate::chain::builder::ChainBuilder; +use crate::chain::config; +use crate::chain::exec::{simple_exec, simple_exec_with_envs}; +use crate::chain::ext::bootstrap::ChainBootstrapMethodsExt; +use crate::error::Error; +use crate::ibc::denom::Denom; +use crate::prelude::{TestWallets, Wallet}; +use crate::types::single::node::FullNode; +use crate::util::namada::get_namada_denom_address; + +use std::fs; +use std::process::{Command, Stdio}; +use std::str; +use std::thread::sleep; + +use crate::types::process::ChildProcess; +use crate::util::file::pipe_to_file; + +/** + Bootstrap a single Namada full node with the provided [`ChainBuilder`] and + a prefix for the chain ID. + + The bootstrap function follows the commands and configurations done in the + the setup-namada-single-node script found in the scripts/ directory. +*/ +pub fn bootstrap_namada_node( + builder: &ChainBuilder, + prefix: &str, + use_random_id: bool, + config_modifier: impl FnOnce(&mut toml::Value) -> Result<(), Error>, + _genesis_modifier: impl FnOnce(&mut serde_json::Value) -> Result<(), Error>, + parameters_modifier: impl FnOnce(&mut toml::Value) -> Result<(), Error>, + chain_number: usize, +) -> Result { + let namada_repo_path = env::var("NAMADA_REPO_PATH") + .map_err(|_| Error::generic(eyre!("missing environment variable `NAMADA_REPO_PATH")))?; + let chain_driver = builder.new_chain(prefix, use_random_id, chain_number)?; + let home_path = &chain_driver.home_path; + let templates_path = &format!("{home_path}/templates"); + fs::create_dir_all(templates_path)?; + + // Copy templates + let copy_loop = format!("for file in {namada_repo_path}/genesis/localnet/*.toml; do cp \"$file\" {templates_path}; done"); + simple_exec("namada", "sh", &["-c", ©_loop])?; + + chain_driver.update_chain_config("templates/parameters.toml", |parameters| { + config::namada::set_default_mint_limit(parameters, i64::MAX)?; + config::namada::set_epochs_per_year(parameters, 31536)?; + config::namada::set_default_per_epoch_throughput_limit(parameters, i64::MAX)?; + config::namada::set_pipeline_len(parameters, 2000)?; + + parameters_modifier(parameters)?; + + Ok(()) + })?; + + let pre_genesis_path = &format!("{home_path}/pre-genesis"); + fs::create_dir_all(pre_genesis_path)?; + + // Copy pre-genesis + let copy_loop = format!("for file in {namada_repo_path}/genesis/localnet/src/pre-genesis/*; do cp \"$file\" {pre_genesis_path}; done"); + simple_exec("namada", "sh", &["-c", ©_loop])?; + simple_exec( + "namada", + "cp", + &[ + "-r", + &format!("{namada_repo_path}/genesis/localnet/src/pre-genesis/validator-0"), + pre_genesis_path, + ], + )?; + + let genesis_path = &format!("{home_path}/genesis"); + fs::create_dir_all(genesis_path)?; + + let wasm_dir = &format!("{namada_repo_path}/wasm"); + let wasm_checksum = &format!("{wasm_dir}/checksums.json"); + + // Init network + let output = simple_exec_with_envs( + "namada", + "namadac", + &[ + "utils", + "init-network", + "--chain-prefix", + &chain_driver.chain_id.to_string(), + "--genesis-time", + "2023-01-01T00:00:00.000000000+00:00", + "--templates-path", + templates_path, + "--wasm-checksums-path", + wasm_checksum, + "--archive-dir", + genesis_path, + "--wasm-dir", + wasm_dir, + ], + &[("NAMADA_BASE_DIR", home_path)], + )?; + + let chain_id = extract_chain_id(output.stdout)?; + + let validator_base_dir = &format!("{home_path}/setup/validator-0"); + let pre_genesis_path = &format!("{home_path}/pre-genesis/validator-0"); + + // TODO: workaround a bug of specifying the wasm directory in Namada v0.43.0 + let cur_dir = std::env::current_dir()?; + std::env::set_current_dir(&namada_repo_path)?; + simple_exec_with_envs( + &chain_id, + "namadac", + &[ + "--base-dir", + validator_base_dir, + "utils", + "join-network", + "--chain-id", + &chain_id, + "--genesis-validator", + "validator-0", + "--pre-genesis-path", + pre_genesis_path, + ], + &[("NAMADA_NETWORK_CONFIGS_DIR", genesis_path)], + )?; + + let chain_dir = &format!("{home_path}/{chain_id}"); + simple_exec("namada", "rm", &["-rf", chain_dir])?; + + simple_exec_with_envs( + &chain_id, + "namadac", + &[ + "--base-dir", + home_path, + "utils", + "join-network", + "--chain-id", + &chain_id, + ], + &[("NAMADA_NETWORK_CONFIGS_DIR", genesis_path)], + )?; + std::env::set_current_dir(cur_dir)?; + + let config_path = format!("{home_path}/setup/validator-0/{chain_id}/config.toml"); + + chain_driver.update_chain_config(&config_path, |config| { + config::namada::set_rpc_port(config, chain_driver.rpc_port)?; + config::namada::set_p2p_port(config, chain_driver.p2p_port)?; + config::namada::set_proxy_app_port(config, chain_driver.pprof_port)?; + config::namada::set_block_cache_bytes(config, 268435456)?; + + config_modifier(config)?; + + Ok(()) + })?; + + let base_args = ["--base-dir", validator_base_dir, "ledger", "run"]; + + let args: Vec<&str> = base_args.to_vec(); + + let mut child = Command::new("namadan") + .args(&args) + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?; + + let stdout = child + .stdout + .take() + .ok_or_else(|| eyre!("expected stdout to be present in child process"))?; + + let stderr = child + .stderr + .take() + .ok_or_else(|| eyre!("expected stderr to be present in child process"))?; + + let stderr_path = format!("{home_path}/stdout.log"); + let stdout_path = format!("{home_path}/stderr.log"); + + pipe_to_file(stdout, &stdout_path)?; + pipe_to_file(stderr, &stderr_path)?; + + // Wait for a while and check if the child process exited immediately. + // If so, return error since we expect the full node to be running in the background. + + sleep(Duration::from_millis(2000)); + + let status = child + .try_wait() + .map_err(|e| eyre!("error try waiting for child status: {}", e))?; + + let process = match status { + None => ChildProcess::new(child), + Some(status) => { + let stdout_output = fs::read_to_string(stdout_path)?; + let stderr_output = fs::read_to_string(stderr_path)?; + + return Err(eyre!( + "expected full node process to be running, but it exited immediately with exit status {} and output: {}\n{}", + status, + stdout_output, + stderr_output, + ).into()); + } + }; + + let ks_folder = Some(format!("{}/hermes_keyring", builder.base_store_dir).into()); + + let albert_key = add_namada_key(home_path, &chain_id, "albert-key", "albert", &ks_folder)?; + let bertha_key = add_namada_key(home_path, &chain_id, "bertha-key", "bertha", &ks_folder)?; + let christel_key = + add_namada_key(home_path, &chain_id, "christel-key", "christel", &ks_folder)?; + let daewon_key = add_namada_key(home_path, &chain_id, "daewon", "daewon", &ks_folder)?; + + let albert = Wallet::new_namada( + "albert".to_string(), + albert_key.address.to_string(), + albert_key, + ); + let bertha = Wallet::new_namada( + "bertha".to_string(), + bertha_key.address.to_string(), + bertha_key, + ); + let christel = Wallet::new_namada( + "christel".to_string(), + christel_key.address.to_string(), + christel_key, + ); + let daewon = Wallet::new_namada( + "daewon".to_string(), + daewon_key.address.to_string(), + daewon_key, + ); + + let wallets = TestWallets { + validator: albert, + relayer: bertha, + user1: christel, + user2: daewon, + }; + + sleep(Duration::from_secs(10)); + + let mut updated_chain_driver = chain_driver.clone(); + updated_chain_driver.chain_id = ChainId::from_string(&chain_id); + + let denom_str = get_namada_denom_address(&chain_id, home_path, "nam")?; + let denom = Denom::base("nam", &denom_str); + + let node = FullNode { + chain_driver: updated_chain_driver, + denom, + wallets, + process: Arc::new(RwLock::new(process)), + }; + + Ok(node) +} + +fn extract_chain_id(output: String) -> Result { + let words: Vec<&str> = output.split_whitespace().collect(); + + if let Some(derived_index) = words.iter().position(|&w| w == "Derived") { + if let Some(&chain_id) = words.get(derived_index + 3) { + return Ok(chain_id.to_owned()); + } + return Err(Error::generic(eyre!( + "chain id is not 3 words after `Derived`: {output}" + ))); + } + Err(Error::generic(eyre!( + "could not find `Derived` in output: {output}" + ))) +} + +fn add_namada_key( + home_path: &str, + chain_id: &str, + key_name: &str, + address_name: &str, + ks_folder: &Option, +) -> Result { + let chain_id = ChainId::from_string(chain_id); + let mut keyring = KeyRing::new_namada(Store::Test, &chain_id, ks_folder) + .map_err(|e| Error::generic(eyre!("error creating keyring: {e}")))?; + + let key_file: PathBuf = format!("{home_path}/{chain_id}").into(); + + let mut wallet = CliWalletUtils::new(key_file.to_path_buf()); + wallet + .load() + .map_err(|e| eyre!("error loading Namada wallet: {e}"))?; + + let secret_key = wallet + .find_secret_key(key_name, None) + .map_err(|e| eyre!("error loading the key from Namada wallet: {e}"))?; + let address = wallet + .find_address(address_name) + .ok_or_else(|| eyre!("error loading the address from Namada wallet"))?; + let namada_key = NamadaKeyPair { + alias: address_name.to_string(), + address: address.into_owned(), + secret_key: secret_key.clone(), + }; + keyring + .add_key(address_name, namada_key.clone()) + .map_err(|e| Error::generic(eyre!("error adding Namada key: {e}")))?; + + Ok(namada_key) +} diff --git a/tools/test-framework/src/bootstrap/single.rs b/tools/test-framework/src/bootstrap/single.rs index df87589b35..62764be9be 100644 --- a/tools/test-framework/src/bootstrap/single.rs +++ b/tools/test-framework/src/bootstrap/single.rs @@ -46,12 +46,13 @@ pub fn bootstrap_single_node( ) -> Result { let native_token_number = chain_number % builder.native_tokens.len(); let native_token = &builder.native_tokens[native_token_number]; - let native_denom = Denom::base(native_token); + let native_denom = Denom::base(native_token, native_token); let denom = if use_random_id { - Denom::base(&format!("coin{:x}", random_u32())) + let random_coin = format!("coin{:x}", random_u32()); + Denom::base(&random_coin, &random_coin) } else { - Denom::base("samoleans") + Denom::base("samoleans", "samoleans") }; // Evmos requires of at least 1_000_000_000_000_000_000 or else there will be the @@ -95,16 +96,16 @@ pub fn bootstrap_single_node( let log_level = std::env::var("CHAIN_LOG_LEVEL").unwrap_or_else(|_| "info".to_string()); - chain_driver.update_chain_config("config.toml", |config| { - config::set_log_level(config, &log_level)?; - config::set_rpc_port(config, chain_driver.rpc_port)?; - config::set_p2p_port(config, chain_driver.p2p_port)?; - config::set_pprof_port(config, chain_driver.pprof_port)?; - config::set_block_sync(config, true)?; - config::set_timeout_commit(config, Duration::from_secs(1))?; - config::set_timeout_propose(config, Duration::from_secs(1))?; - config::set_mode(config, "validator")?; - config::set_indexer(config, "kv")?; + chain_driver.update_chain_config("config/config.toml", |config| { + config::cosmos::set_log_level(config, &log_level)?; + config::cosmos::set_rpc_port(config, chain_driver.rpc_port)?; + config::cosmos::set_p2p_port(config, chain_driver.p2p_port)?; + config::cosmos::set_pprof_port(config, chain_driver.pprof_port)?; + config::cosmos::set_block_sync(config, true)?; + config::cosmos::set_timeout_commit(config, Duration::from_secs(1))?; + config::cosmos::set_timeout_propose(config, Duration::from_secs(1))?; + config::cosmos::set_mode(config, "validator")?; + config::cosmos::set_indexer(config, "kv")?; config_modifier(config)?; @@ -112,16 +113,16 @@ pub fn bootstrap_single_node( })?; let minimum_gas = format!("0{}", native_token); - chain_driver.update_chain_config("app.toml", |config| { + chain_driver.update_chain_config("config/app.toml", |config| { if builder.ipv6_grpc { - config::set_grpc_port_ipv6(config, chain_driver.grpc_port)?; + config::cosmos::set_grpc_port_ipv6(config, chain_driver.grpc_port)?; } else { - config::set_grpc_port(config, chain_driver.grpc_port)?; + config::cosmos::set_grpc_port(config, chain_driver.grpc_port)?; } - config::enable_grpc(config)?; - config::disable_grpc_web(config)?; - config::disable_api(config)?; - config::set_minimum_gas_price(config, &minimum_gas)?; + config::cosmos::enable_grpc(config)?; + config::cosmos::disable_grpc_web(config)?; + config::cosmos::disable_api(config)?; + config::cosmos::set_minimum_gas_price(config, &minimum_gas)?; Ok(()) })?; diff --git a/tools/test-framework/src/chain/chain_type.rs b/tools/test-framework/src/chain/chain_type.rs index 309a91b00e..84dfd7d2a1 100644 --- a/tools/test-framework/src/chain/chain_type.rs +++ b/tools/test-framework/src/chain/chain_type.rs @@ -8,6 +8,7 @@ use crate::util::random::{random_u32, random_unused_tcp_port}; const COSMOS_HD_PATH: &str = "m/44'/118'/0'/0/0"; const EVMOS_HD_PATH: &str = "m/44'/60'/0'/0/0"; const PROVENANCE_HD_PATH: &str = "m/44'/505'/0'/0/0"; +const NAMADA_HD_PATH: &str = "m/44'/877'/0'/0'/0'"; #[derive(Clone, Debug)] pub enum ChainType { @@ -16,6 +17,7 @@ pub enum ChainType { Evmos, Provenance, Injective, + Namada, } impl ChainType { @@ -24,6 +26,7 @@ impl ChainType { Self::Cosmos { dynamic_fee: _ } | Self::Osmosis => COSMOS_HD_PATH, Self::Evmos | Self::Injective => EVMOS_HD_PATH, Self::Provenance => PROVENANCE_HD_PATH, + Self::Namada => NAMADA_HD_PATH, } } @@ -46,6 +49,7 @@ impl ChainType { Self::Injective => ChainId::from_string(&format!("injective-{prefix}")), Self::Evmos => ChainId::from_string(&format!("evmos_9000-{prefix}")), Self::Provenance => ChainId::from_string(&format!("pio-mainnet-{prefix}")), + Self::Namada => ChainId::from_string(&format!("namada-{prefix}")), } } @@ -54,7 +58,8 @@ impl ChainType { let mut res = vec![]; let json_rpc_port = random_unused_tcp_port(); match self { - Self::Cosmos { dynamic_fee: _ } | Self::Injective | Self::Provenance => {} + Self::Cosmos { dynamic_fee: _ } | Self::Injective | Self::Provenance | Self::Namada => { + } Self::Osmosis => { res.push("--reject-config-defaults".to_owned()); } @@ -70,7 +75,11 @@ impl ChainType { pub fn extra_add_genesis_account_args(&self, chain_id: &ChainId) -> Vec { let mut res = vec![]; match self { - Self::Cosmos { dynamic_fee: _ } | Self::Osmosis | Self::Evmos | Self::Provenance => {} + Self::Cosmos { dynamic_fee: _ } + | Self::Osmosis + | Self::Evmos + | Self::Provenance + | Self::Namada => {} Self::Injective => { res.push("--chain-id".to_owned()); res.push(format!("{chain_id}")); @@ -81,7 +90,7 @@ impl ChainType { pub fn address_type(&self) -> AddressType { match self { - Self::Cosmos { dynamic_fee: _ } | Self::Osmosis | Self::Provenance => { + Self::Cosmos { dynamic_fee: _ } | Self::Osmosis | Self::Provenance | Self::Namada => { AddressType::default() } Self::Evmos => AddressType::Ethermint { @@ -110,6 +119,7 @@ impl FromStr for ChainType { name if name.contains("injectived") => Ok(ChainType::Injective), name if name.contains("provenanced") => Ok(ChainType::Provenance), name if name.contains("osmosisd") => Ok(ChainType::Osmosis), + name if name.contains("namada") => Ok(ChainType::Namada), _ => Ok(ChainType::Cosmos { dynamic_fee: false }), } } diff --git a/tools/test-framework/src/chain/cli/query.rs b/tools/test-framework/src/chain/cli/query.rs index 9c662a7161..d4cd140a24 100644 --- a/tools/test-framework/src/chain/cli/query.rs +++ b/tools/test-framework/src/chain/cli/query.rs @@ -8,6 +8,7 @@ use tracing::debug; use crate::chain::exec::simple_exec; use crate::error::{handle_generic_error, Error}; +use crate::prelude::*; pub fn query_balance( chain_id: &str, @@ -102,6 +103,58 @@ pub fn query_balance( } } +pub fn query_namada_balance( + chain_id: &str, + _command_path: &str, + home_path: &str, + denom: &Denom, + wallet_id: &str, + rpc_listen_address: &str, +) -> Result { + let output = simple_exec( + chain_id, + "namadac", + &[ + "--base-dir", + home_path, + "balance", + "--owner", + wallet_id, + "--token", + &denom.hash_only(), + "--node", + rpc_listen_address, + ], + )?; + + let words: Vec<&str> = output.stdout.split_whitespace().collect(); + let raw_addr = &format!("{}:", denom.hash_only()); + + if let Some(derived_index) = words.iter().position(|&w| w.contains(raw_addr)) { + if let Some(&amount_str) = words.get(derived_index + 1) { + return Amount::from_str(amount_str).map_err(handle_generic_error); + } + Err(Error::generic(eyre!( + "chain id is not 1 words after `{raw_addr}`: raw output `{}` split output `{words:#?}`", + output.stdout + ))) + } else { + let denom_display_name = &format!("{}:", denom.namada_display_name()); + if let Some(derived_index) = words.iter().position(|&w| w.contains(denom_display_name)) { + if let Some(&amount_str) = words.get(derived_index + 1) { + return Amount::from_str(amount_str).map_err(handle_generic_error); + } + Err(Error::generic(eyre!( + "chain id is not 1 words after `{denom_display_name}`: raw output `{}` split output `{words:#?}`", + output.stdout + ))) + } else { + debug!("Denom `{denom_display_name}` not found when querying for balance, will return 0{denom}"); + Ok(Amount::from_str("0").map_err(handle_generic_error)?) + } + } +} + /** Query for the transactions related to a wallet on `Chain` receiving token transfer from others. diff --git a/tools/test-framework/src/chain/config.rs b/tools/test-framework/src/chain/config/cosmos.rs similarity index 100% rename from tools/test-framework/src/chain/config.rs rename to tools/test-framework/src/chain/config/cosmos.rs diff --git a/tools/test-framework/src/chain/config/mod.rs b/tools/test-framework/src/chain/config/mod.rs new file mode 100644 index 0000000000..5cffe3a80f --- /dev/null +++ b/tools/test-framework/src/chain/config/mod.rs @@ -0,0 +1,2 @@ +pub mod cosmos; +pub mod namada; diff --git a/tools/test-framework/src/chain/config/namada.rs b/tools/test-framework/src/chain/config/namada.rs new file mode 100644 index 0000000000..27f3bef64e --- /dev/null +++ b/tools/test-framework/src/chain/config/namada.rs @@ -0,0 +1,144 @@ +use eyre::{eyre, Report as Error}; +use toml::Value; + +/// Set the `rpc` field in the full node config. +pub fn set_rpc_port(config: &mut Value, port: u16) -> Result<(), Error> { + config + .get_mut("ledger") + .ok_or_else(|| eyre!("expect ledger section"))? + .get_mut("cometbft") + .ok_or_else(|| eyre!("expect cometbft section"))? + .get_mut("rpc") + .ok_or_else(|| eyre!("expect cometbft rpc"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert( + "laddr".to_string(), + format!("tcp://0.0.0.0:{}", port).into(), + ); + + Ok(()) +} + +/// Set the `p2p` field in the full node config. +pub fn set_p2p_port(config: &mut Value, port: u16) -> Result<(), Error> { + config + .get_mut("ledger") + .ok_or_else(|| eyre!("expect ledger section"))? + .get_mut("cometbft") + .ok_or_else(|| eyre!("expect cometbft section"))? + .get_mut("p2p") + .ok_or_else(|| eyre!("expect cometbft p2p"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert( + "laddr".to_string(), + format!("tcp://0.0.0.0:{}", port).into(), + ); + + Ok(()) +} + +/// Set the `proxy_app` field in the full node config. +pub fn set_proxy_app_port(config: &mut Value, port: u16) -> Result<(), Error> { + config + .get_mut("ledger") + .ok_or_else(|| eyre!("expect ledger section"))? + .get_mut("cometbft") + .ok_or_else(|| eyre!("expect cometbft section"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert( + "proxy_app".to_string(), + format!("tcp://0.0.0.0:{}", port).into(), + ); + + Ok(()) +} + +/// Set the `block_cache_bytes` field in the full node config. +pub fn set_block_cache_bytes(config: &mut Value, block_cache_bytes: i64) -> Result<(), Error> { + config + .get_mut("ledger") + .ok_or_else(|| eyre!("expect ledger section"))? + .get_mut("shell") + .ok_or_else(|| eyre!("expect shell section"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert( + "block_cache_bytes".to_string(), + Value::Integer(block_cache_bytes), + ); + + Ok(()) +} + +pub fn set_unbonding_len(parameters: &mut Value, unbonding_len: i64) -> Result<(), Error> { + parameters + .get_mut("pos_params") + .ok_or_else(|| eyre!("expect pos_params section"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert("unbonding_len".to_string(), Value::Integer(unbonding_len)); + + Ok(()) +} + +pub fn set_pipeline_len(parameters: &mut Value, pipeline_len: i64) -> Result<(), Error> { + parameters + .get_mut("pos_params") + .ok_or_else(|| eyre!("expect pos_params section"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert("pipeline_len".to_string(), Value::Integer(pipeline_len)); + + Ok(()) +} + +pub fn set_default_mint_limit( + parameters: &mut Value, + default_mint_limit: i64, +) -> Result<(), Error> { + parameters + .get_mut("ibc_params") + .ok_or_else(|| eyre!("expect ibc_params section"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert( + "default_mint_limit".to_string(), + Value::String(default_mint_limit.to_string()), + ); + + Ok(()) +} + +pub fn set_default_per_epoch_throughput_limit( + parameters: &mut Value, + default_per_epoch_throughput_limit: i64, +) -> Result<(), Error> { + parameters + .get_mut("ibc_params") + .ok_or_else(|| eyre!("expect ibc_params section"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert( + "default_per_epoch_throughput_limit".to_string(), + Value::String(default_per_epoch_throughput_limit.to_string()), + ); + + Ok(()) +} + +pub fn set_epochs_per_year(parameters: &mut Value, epochs_per_year: i64) -> Result<(), Error> { + parameters + .get_mut("parameters") + .ok_or_else(|| eyre!("expect parameters section"))? + .as_table_mut() + .ok_or_else(|| eyre!("expect object"))? + .insert( + "epochs_per_year".to_string(), + Value::Integer(epochs_per_year), + ); + + Ok(()) +} diff --git a/tools/test-framework/src/chain/driver.rs b/tools/test-framework/src/chain/driver.rs index bd4aba6543..a1348f5855 100644 --- a/tools/test-framework/src/chain/driver.rs +++ b/tools/test-framework/src/chain/driver.rs @@ -23,6 +23,8 @@ use crate::types::env::{EnvWriter, ExportEnv}; use crate::types::wallet::WalletAddress; use crate::util::retry::assert_eventually_succeed; +use super::cli::query::query_namada_balance; + /** Number of times (seconds) to try and query a wallet to reach the target amount, as used by [`assert_eventual_wallet_amount`]. @@ -188,7 +190,11 @@ impl ChainDriver { as it requires the `"tcp://"` scheme. */ pub fn rpc_listen_address(&self) -> String { - format!("tcp://localhost:{}", self.rpc_port) + if self.command_path == "namada" { + format!("http://localhost:{}", self.rpc_port) + } else { + format!("tcp://localhost:{}", self.rpc_port) + } } /** @@ -210,13 +216,23 @@ impl ChainDriver { Query for the balances for a given wallet address and denomination */ pub fn query_balance(&self, wallet_id: &WalletAddress, denom: &Denom) -> Result { - query_balance( - self.chain_id.as_str(), - &self.command_path, - &self.rpc_listen_address(), - &wallet_id.0, - &denom.to_string(), - ) + match self.chain_type { + ChainType::Namada => query_namada_balance( + self.chain_id.as_str(), + &self.command_path, + &self.home_path, + denom, + &wallet_id.0, + &self.rpc_listen_address(), + ), + _ => query_balance( + self.chain_id.as_str(), + &self.command_path, + &self.rpc_listen_address(), + &wallet_id.0, + &denom.to_string(), + ), + } } /** diff --git a/tools/test-framework/src/chain/exec.rs b/tools/test-framework/src/chain/exec.rs index c9b958de3f..1ca6134d8b 100644 --- a/tools/test-framework/src/chain/exec.rs +++ b/tools/test-framework/src/chain/exec.rs @@ -49,3 +49,54 @@ pub fn simple_exec(desc: &str, command_path: &str, args: &[&str]) -> Result Result { + debug!( + "Executing command for {}: {} {}", + desc, + command_path, + itertools::join(args, " ") + ); + + let mut cmd = Command::new(command_path); + + for (key, value) in envs { + cmd.env(key, value); + } + + let output = cmd + .args(args) + .output() + .map_err(handle_exec_error(command_path))?; + + if output.status.success() { + let stdout = str::from_utf8(&output.stdout) + .map_err(handle_generic_error)? + .to_string(); + + let stderr = str::from_utf8(&output.stderr) + .map_err(handle_generic_error)? + .to_string(); + + trace!( + "command executed successfully with stdout: {}, stderr: {}", + stdout, + stderr + ); + + Ok(ExecOutput { stdout, stderr }) + } else { + let message = str::from_utf8(&output.stderr).map_err(handle_generic_error)?; + + Err(Error::generic(eyre!( + "command exited with error status {:?} and message: {}", + output.status.code(), + message + ))) + } +} diff --git a/tools/test-framework/src/chain/ext/bootstrap.rs b/tools/test-framework/src/chain/ext/bootstrap.rs index 07103fcd05..60033b6752 100644 --- a/tools/test-framework/src/chain/ext/bootstrap.rs +++ b/tools/test-framework/src/chain/ext/bootstrap.rs @@ -182,9 +182,7 @@ impl ChainBootstrapMethodsExt for ChainDriver { file: &str, cont: impl FnOnce(&mut toml::Value) -> Result<(), Error>, ) -> Result<(), Error> { - let config_path = format!("config/{file}"); - - let config1 = self.read_file(&config_path)?; + let config1 = self.read_file(file)?; let mut config2 = toml::from_str(&config1).map_err(handle_generic_error)?; @@ -192,7 +190,7 @@ impl ChainBootstrapMethodsExt for ChainDriver { let config3 = toml::to_string_pretty(&config2).map_err(handle_generic_error)?; - self.write_file(&config_path, &config3)?; + self.write_file(file, &config3)?; Ok(()) } @@ -245,7 +243,11 @@ impl ChainBootstrapMethodsExt for ChainDriver { let key = Secp256k1KeyPair::from_seed_file(&seed_content, &hd_path) .map_err(handle_generic_error)?; - Ok(Wallet::new(wallet_id.to_string(), wallet_address, key)) + Ok(Wallet::new_secp256( + wallet_id.to_string(), + wallet_address, + key, + )) } fn add_genesis_account(&self, wallet: &WalletAddress, amounts: &[&Token]) -> Result<(), Error> { diff --git a/tools/test-framework/src/chain/ext/ica.rs b/tools/test-framework/src/chain/ext/ica.rs index 427acd8003..f335774d31 100644 --- a/tools/test-framework/src/chain/ext/ica.rs +++ b/tools/test-framework/src/chain/ext/ica.rs @@ -88,24 +88,25 @@ pub fn register_unordered_interchain_account { sender: &MonoTagged, recipient: &MonoTagged, token: &TaggedTokenRef, - ) -> Result; + ) -> Result<(), Error>; fn ibc_transfer_token_with_memo_and_timeout( &self, @@ -53,7 +56,7 @@ pub trait ChainTransferMethodsExt { token: &TaggedTokenRef, memo: Option, timeout: Option, - ) -> Result; + ) -> Result<(), Error>; fn ibc_transfer_token_multiple( &self, @@ -94,19 +97,34 @@ impl ChainTransferMethodsExt for MonoTagged, recipient: &MonoTagged, token: &TaggedTokenRef, - ) -> Result { - let rpc_client = self.rpc_client()?; - self.value().runtime.block_on(ibc_token_transfer( - rpc_client.as_ref(), - &self.tx_config(), - port_id, - channel_id, - sender, - recipient, - token, - None, - None, - )) + ) -> Result<(), Error> { + match self.value().chain_type { + crate::chain::chain_type::ChainType::Namada => ibc_namada_token_transfer( + &self.value().home_path, + &sender.value().id.to_string(), + recipient.value().as_str(), + token.value().denom.as_str(), + &token.value().amount.to_string(), + &channel_id.to_string(), + &self.value().rpc_port.to_string(), + None, + None, + ), + _ => { + let rpc_client = self.rpc_client()?; + self.value().runtime.block_on(ibc_token_transfer( + rpc_client.as_ref(), + &self.tx_config(), + port_id, + channel_id, + sender, + recipient, + token, + None, + None, + )) + } + } } fn ibc_transfer_token_with_memo_and_timeout( @@ -118,19 +136,39 @@ impl ChainTransferMethodsExt for MonoTagged, memo: Option, timeout: Option, - ) -> Result { - let rpc_client = self.rpc_client()?; - self.value().runtime.block_on(ibc_token_transfer( - rpc_client.as_ref(), - &self.tx_config(), - port_id, - channel_id, - sender, - recipient, - token, - memo, - timeout, - )) + ) -> Result<(), Error> { + match self.value().chain_type { + ChainType::Namada => { + let denom = token.value().denom.to_string(); + let amount = token.value().amount.to_string(); + let rpc_port = self.value().rpc_port.to_string(); + ibc_namada_token_transfer( + &self.value().home_path, + &sender.value().id.to_string(), + recipient.value().as_str(), + &denom, + &amount, + channel_id.value().as_ref(), + &rpc_port, + memo, + timeout, + ) + } + _ => { + let rpc_client = self.rpc_client()?; + self.value().runtime.block_on(ibc_token_transfer( + rpc_client.as_ref(), + &self.tx_config(), + port_id, + channel_id, + sender, + recipient, + token, + memo, + timeout, + )) + } + } } fn ibc_transfer_token_multiple( @@ -143,18 +181,42 @@ impl ChainTransferMethodsExt for MonoTagged, ) -> Result<(), Error> { - let rpc_client = self.rpc_client()?; - self.value().runtime.block_on(batched_ibc_token_transfer( - rpc_client.as_ref(), - &self.tx_config(), - port_id, - channel_id, - sender, - recipient, - token, - num_msgs, - memo, - )) + match self.value().chain_type { + ChainType::Namada => { + let denom = token.value().denom.to_string(); + let amount = token.value().amount.to_string(); + let rpc_port = self.value().rpc_port.to_string(); + // Namada CLI doesn't support batching transactions + for _ in 0..num_msgs { + ibc_namada_token_transfer( + &self.value().home_path, + &sender.value().id.to_string(), + recipient.value().as_str(), + &denom, + &amount, + &channel_id.to_string(), + &rpc_port, + memo.clone(), + None, + )?; + } + Ok(()) + } + _ => { + let rpc_client = self.rpc_client()?; + self.value().runtime.block_on(batched_ibc_token_transfer( + rpc_client.as_ref(), + &self.tx_config(), + port_id, + channel_id, + sender, + recipient, + token, + num_msgs, + memo, + )) + } + } } fn local_transfer_token( @@ -165,16 +227,31 @@ impl ChainTransferMethodsExt for MonoTagged, ) -> Result<(), Error> { let driver = *self.value(); - local_transfer_token( - driver.chain_id.as_str(), - &driver.command_path, - &driver.home_path, - &driver.rpc_listen_address(), - sender.value().address.as_str(), - recipient.value().as_str(), - &token.value().to_string(), - &fees.value().to_string(), - ) + match driver.chain_type { + ChainType::Namada => { + let denom = token.value().denom.to_string(); + let amount = token.value().amount.to_string(); + let rpc_port = self.value().rpc_port.to_string(); + local_namada_token_transfer( + &driver.home_path, + &sender.value().id.to_string(), + recipient.value().as_str(), + &denom, + &amount, + &rpc_port, + ) + } + _ => local_transfer_token( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + sender.value().address.as_str(), + recipient.value().as_str(), + &token.value().to_string(), + &fees.value().to_string(), + ), + } } fn transfer_from_chain( @@ -188,19 +265,39 @@ impl ChainTransferMethodsExt for MonoTagged Result<(), Error> { let driver = *self.value(); - let timeout_height_str = timeout_height.revision_height() + 100; - transfer_from_chain( - driver.chain_id.as_str(), - &driver.command_path, - &driver.home_path, - &driver.rpc_listen_address(), - sender.value().address.as_str(), - port.as_ref(), - channel.as_ref(), - recipient.value().as_str(), - &token.value().to_string(), - &fees.value().to_string(), - &timeout_height_str.to_string(), - ) + match driver.chain_type { + ChainType::Namada => { + let denom = token.value().denom.to_string(); + let amount = token.value().amount.to_string(); + let rpc_port = self.value().rpc_port.to_string(); + ibc_namada_token_transfer( + &driver.home_path, + &sender.value().id.to_string(), + recipient.value().as_str(), + &denom, + &amount, + channel.as_ref(), + &rpc_port, + None, + None, + ) + } + _ => { + let timeout_height_str = timeout_height.revision_height() + 100; + transfer_from_chain( + driver.chain_id.as_str(), + &driver.command_path, + &driver.home_path, + &driver.rpc_listen_address(), + sender.value().address.as_str(), + port.as_ref(), + channel.as_ref(), + recipient.value().as_str(), + &token.value().to_string(), + &fees.value().to_string(), + &timeout_height_str.to_string(), + ) + } + } } } diff --git a/tools/test-framework/src/chain/tagged.rs b/tools/test-framework/src/chain/tagged.rs index d6f2f510ad..8f324bf922 100644 --- a/tools/test-framework/src/chain/tagged.rs +++ b/tools/test-framework/src/chain/tagged.rs @@ -1,6 +1,8 @@ /*! Methods for tagged version of the chain driver. */ +use eyre::eyre; +use serde_json as json; use ibc_proto::google::protobuf::Any; use ibc_relayer::chain::cosmos::tx::simple_send_tx; @@ -8,7 +10,6 @@ use ibc_relayer::chain::cosmos::types::config::TxConfig; use ibc_relayer::config::compat_mode::CompatMode; use ibc_relayer::event::IbcEventWithHeight; use ibc_relayer_types::core::ics24_host::identifier::ChainId; -use serde_json as json; use tendermint_rpc::client::{Client, HttpClient}; use tendermint_rpc::Url; use tracing::warn; @@ -144,12 +145,18 @@ impl TaggedChainDriverExt for MonoTagged Result, Error> { let rpc_client = self.rpc_client()?; + let key = &wallet + .value() + .key + .downcast() + .ok_or_else(|| eyre!("unable to downcast key")) + .map_err(Error::generic)?; self.value() .runtime .block_on(simple_send_tx( rpc_client.as_ref().into_value(), &self.value().tx_config, - &wallet.value().key, + key, messages, )) .map_err(Error::relayer) diff --git a/tools/test-framework/src/docs/walkthroughs/memo.rs b/tools/test-framework/src/docs/walkthroughs/memo.rs index 7c0887a76c..336bc5d874 100644 --- a/tools/test-framework/src/docs/walkthroughs/memo.rs +++ b/tools/test-framework/src/docs/walkthroughs/memo.rs @@ -10,8 +10,7 @@ //! //! ```no_run //! # use serde_json as json; -//! # use ibc_relayer::config::{types::Memo, Config}; -//! # use ibc_relayer::config::ChainConfig; +//! # use ibc_relayer::config::{types::Memo, Config, ChainConfig}; //! # use ibc_test_framework::ibc::denom::derive_ibc_denom; //! # use ibc_test_framework::prelude::*; //! # use ibc_test_framework::util::random::{random_string, random_u128_range}; @@ -32,9 +31,9 @@ //! fn modify_relayer_config(&self, config: &mut Config) { //! for mut chain in config.chains.iter_mut() { //! match chain { -//! ChainConfig::CosmosSdk(chain_config) => { +//! ChainConfig::CosmosSdk(chain_config) | ChainConfig::Namada(chain_config) => { //! chain_config.memo_prefix = self.memo.clone(); -//! }, +//! } //! } //! } //! } @@ -61,6 +60,7 @@ //! )?; //! //! let denom_b = derive_ibc_denom( +//! &chains.node_b.chain_driver().value().chain_type, //! &channel.port_b.as_ref(), //! &channel.channel_id_b.as_ref(), //! &denom_a, diff --git a/tools/test-framework/src/docs/walkthroughs/ordered_channel.rs b/tools/test-framework/src/docs/walkthroughs/ordered_channel.rs index 36c04807a6..6f717d436e 100644 --- a/tools/test-framework/src/docs/walkthroughs/ordered_channel.rs +++ b/tools/test-framework/src/docs/walkthroughs/ordered_channel.rs @@ -95,6 +95,7 @@ //! sleep(Duration::from_secs(1)); //! //! let denom_b = derive_ibc_denom( +//! &chains.node_b.chain_driver().value().chain_type, //! &channel.port_b.as_ref(), //! &channel.channel_id_b.as_ref(), //! &denom_a, diff --git a/tools/test-framework/src/framework/binary/chain.rs b/tools/test-framework/src/framework/binary/chain.rs index 5e58a2ef58..2c753f2c5a 100644 --- a/tools/test-framework/src/framework/binary/chain.rs +++ b/tools/test-framework/src/framework/binary/chain.rs @@ -13,8 +13,8 @@ use crate::error::Error; use crate::framework::base::{HasOverrides, TestConfigOverride}; use crate::framework::binary::ics::InterchainSecurityChainTest; use crate::framework::binary::node::{ - run_binary_node_test, run_single_node_test, BinaryNodeTest, NodeConfigOverride, - NodeGenesisOverride, + run_binary_node_test, run_single_node_test, BinaryNodeTest, NamadaParametersOverride, + NodeConfigOverride, NodeGenesisOverride, }; use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; use crate::relayer::driver::RelayerDriver; @@ -39,7 +39,8 @@ where + RelayerConfigOverride + ClientOptionsOverride + SupervisorOverride - + TestConfigOverride, + + TestConfigOverride + + NamadaParametersOverride, { run_binary_chain_test(&RunTwoWayBinaryChainTest::new(test)) } @@ -56,7 +57,8 @@ where + RelayerConfigOverride + ClientOptionsOverride + SupervisorOverride - + TestConfigOverride, + + TestConfigOverride + + NamadaParametersOverride, { run_binary_node_test(&RunBinaryChainTest::new(&RunWithSupervisor::new(test))) } @@ -74,7 +76,8 @@ where + NodeGenesisOverride + RelayerConfigOverride + ClientOptionsOverride - + TestConfigOverride, + + TestConfigOverride + + NamadaParametersOverride, { run_single_node_test(&RunBinaryChainTest::new(test)) } diff --git a/tools/test-framework/src/framework/binary/channel.rs b/tools/test-framework/src/framework/binary/channel.rs index 6aef65d90c..3f3d964da2 100644 --- a/tools/test-framework/src/framework/binary/channel.rs +++ b/tools/test-framework/src/framework/binary/channel.rs @@ -24,7 +24,7 @@ use crate::framework::binary::connection::{ }; use crate::framework::binary::ics::run_binary_interchain_security_node_test; use crate::framework::binary::node::{ - run_binary_node_test, NodeConfigOverride, NodeGenesisOverride, + run_binary_node_test, NamadaParametersOverride, NodeConfigOverride, NodeGenesisOverride, }; use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; use crate::relayer::driver::RelayerDriver; @@ -54,7 +54,8 @@ where + ConnectionDelayOverride + PortsOverride + ChannelOrderOverride - + ChannelVersionOverride, + + ChannelVersionOverride + + NamadaParametersOverride, { run_binary_channel_test(&RunTwoWayBinaryChannelTest::new(test)) } @@ -75,7 +76,8 @@ where + ConnectionDelayOverride + PortsOverride + ChannelOrderOverride - + ChannelVersionOverride, + + ChannelVersionOverride + + NamadaParametersOverride, { run_binary_node_test(&RunBinaryChainTest::new(&RunBinaryConnectionTest::new( &RunBinaryChannelTest::new(&RunWithSupervisor::new(test)), diff --git a/tools/test-framework/src/framework/binary/connection.rs b/tools/test-framework/src/framework/binary/connection.rs index d1fb5e7887..0f01082f98 100644 --- a/tools/test-framework/src/framework/binary/connection.rs +++ b/tools/test-framework/src/framework/binary/connection.rs @@ -16,7 +16,7 @@ use crate::framework::binary::chain::{ BinaryChainTest, ClientOptionsOverride, RelayerConfigOverride, RunBinaryChainTest, }; use crate::framework::binary::node::{ - run_binary_node_test, NodeConfigOverride, NodeGenesisOverride, + run_binary_node_test, NamadaParametersOverride, NodeConfigOverride, NodeGenesisOverride, }; use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; use crate::relayer::driver::RelayerDriver; @@ -41,7 +41,8 @@ where + RelayerConfigOverride + ClientOptionsOverride + SupervisorOverride - + ConnectionDelayOverride, + + ConnectionDelayOverride + + NamadaParametersOverride, { run_binary_connection_test(&RunTwoWayBinaryConnectionTest::new(test)) } @@ -59,7 +60,8 @@ where + RelayerConfigOverride + ClientOptionsOverride + SupervisorOverride - + ConnectionDelayOverride, + + ConnectionDelayOverride + + NamadaParametersOverride, { run_binary_node_test(&RunBinaryChainTest::new(&RunBinaryConnectionTest::new( &RunWithSupervisor::new(test), @@ -172,9 +174,7 @@ where } } -impl BinaryConnectionTest - for RunTwoWayBinaryConnectionTest<'_, Test> -{ +impl BinaryConnectionTest for RunTwoWayBinaryConnectionTest<'_, Test> { fn run( &self, config: &TestConfig, diff --git a/tools/test-framework/src/framework/binary/node.rs b/tools/test-framework/src/framework/binary/node.rs index cea2cb1832..528a4dd021 100644 --- a/tools/test-framework/src/framework/binary/node.rs +++ b/tools/test-framework/src/framework/binary/node.rs @@ -3,8 +3,14 @@ running without setting up the relayer. */ +use std::str::FromStr; + +use toml; + +use crate::bootstrap::namada::bootstrap_namada_node; use crate::bootstrap::single::bootstrap_single_node; use crate::chain::builder::ChainBuilder; +use crate::chain::chain_type::ChainType; use crate::error::Error; use crate::framework::base::HasOverrides; use crate::framework::base::{run_basic_test, BasicTest, TestConfigOverride}; @@ -18,7 +24,8 @@ pub fn run_binary_node_test(test: &Test) -> Result<(), Error> where Test: BinaryNodeTest, Test: HasOverrides, - Overrides: NodeConfigOverride + NodeGenesisOverride + TestConfigOverride, + Overrides: + NodeConfigOverride + NodeGenesisOverride + TestConfigOverride + NamadaParametersOverride, { run_basic_test(&RunBinaryNodeTest { test }) } @@ -27,7 +34,8 @@ pub fn run_single_node_test(test: &Test) -> Result<(), Error> where Test: BinaryNodeTest, Test: HasOverrides, - Overrides: NodeConfigOverride + NodeGenesisOverride + TestConfigOverride, + Overrides: + NodeConfigOverride + NodeGenesisOverride + TestConfigOverride + NamadaParametersOverride, { run_basic_test(&RunSingleNodeTest { test }) } @@ -87,6 +95,10 @@ pub trait NodeGenesisOverride { fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error>; } +pub trait NamadaParametersOverride { + fn namada_modify_parameter_file(&self, parameter: &mut toml::Value) -> Result<(), Error>; +} + /** A wrapper type that lifts a test case that implements [`BinaryNodeTest`] into a test case that implements [`BasicTest`]. @@ -105,26 +117,59 @@ impl BasicTest for RunBinaryNodeTest<'_, Test> where Test: BinaryNodeTest, Test: HasOverrides, - Overrides: NodeConfigOverride + NodeGenesisOverride, + Overrides: NodeConfigOverride + NodeGenesisOverride + NamadaParametersOverride, { fn run(&self, config: &TestConfig, builder: &ChainBuilder) -> Result<(), Error> { - let node_a = bootstrap_single_node( - builder, - "1", - config.bootstrap_with_random_ids, - |config| self.test.get_overrides().modify_node_config(config), - |genesis| self.test.get_overrides().modify_genesis_file(genesis), - 0, - )?; - - let node_b = bootstrap_single_node( - builder, - "2", - config.bootstrap_with_random_ids, - |config| self.test.get_overrides().modify_node_config(config), - |genesis| self.test.get_overrides().modify_genesis_file(genesis), - 1, - )?; + let command_paths_len = builder.command_paths.len(); + let node_a_type = ChainType::from_str(&builder.command_paths[0 % command_paths_len])?; + let node_a = match node_a_type { + ChainType::Namada => bootstrap_namada_node( + builder, + "a", + false, + |config| self.test.get_overrides().modify_node_config(config), + |genesis| self.test.get_overrides().modify_genesis_file(genesis), + |parameters| { + self.test + .get_overrides() + .namada_modify_parameter_file(parameters) + }, + 0, + ), + _ => bootstrap_single_node( + builder, + "1", + config.bootstrap_with_random_ids, + |config| self.test.get_overrides().modify_node_config(config), + |genesis| self.test.get_overrides().modify_genesis_file(genesis), + 0, + ), + }?; + let node_b_type = ChainType::from_str(&builder.command_paths[1 % command_paths_len])?; + + let node_b = match node_b_type { + ChainType::Namada => bootstrap_namada_node( + builder, + "b", + false, + |config| self.test.get_overrides().modify_node_config(config), + |genesis| self.test.get_overrides().modify_genesis_file(genesis), + |parameters| { + self.test + .get_overrides() + .namada_modify_parameter_file(parameters) + }, + 1, + ), + _ => bootstrap_single_node( + builder, + "2", + config.bootstrap_with_random_ids, + |config| self.test.get_overrides().modify_node_config(config), + |genesis| self.test.get_overrides().modify_genesis_file(genesis), + 1, + ), + }?; let _node_process_a = node_a.process.clone(); let _node_process_b = node_b.process.clone(); @@ -139,17 +184,34 @@ impl BasicTest for RunSingleNodeTest<'_, Test> where Test: BinaryNodeTest, Test: HasOverrides, - Overrides: NodeConfigOverride + NodeGenesisOverride, + Overrides: NodeConfigOverride + NodeGenesisOverride + NamadaParametersOverride, { fn run(&self, config: &TestConfig, builder: &ChainBuilder) -> Result<(), Error> { - let node = bootstrap_single_node( - builder, - "1", - config.bootstrap_with_random_ids, - |config| self.test.get_overrides().modify_node_config(config), - |genesis| self.test.get_overrides().modify_genesis_file(genesis), - 0, - )?; + let command_paths_len = builder.command_paths.len(); + let node_type = ChainType::from_str(&builder.command_paths[0 % command_paths_len])?; + let node = match node_type { + ChainType::Namada => bootstrap_namada_node( + builder, + "a", + false, + |config| self.test.get_overrides().modify_node_config(config), + |genesis| self.test.get_overrides().modify_genesis_file(genesis), + |parameters| { + self.test + .get_overrides() + .namada_modify_parameter_file(parameters) + }, + 0, + ), + _ => bootstrap_single_node( + builder, + "1", + config.bootstrap_with_random_ids, + |config| self.test.get_overrides().modify_node_config(config), + |genesis| self.test.get_overrides().modify_genesis_file(genesis), + 0, + ), + }?; let _node_process = node.process.clone(); diff --git a/tools/test-framework/src/framework/nary/chain.rs b/tools/test-framework/src/framework/nary/chain.rs index 7667ac42e4..19fff4dc00 100644 --- a/tools/test-framework/src/framework/nary/chain.rs +++ b/tools/test-framework/src/framework/nary/chain.rs @@ -12,7 +12,9 @@ use crate::bootstrap::nary::chain::{ use crate::error::Error; use crate::framework::base::{HasOverrides, TestConfigOverride}; use crate::framework::binary::chain::{RelayerConfigOverride, TopologyOverride}; -use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::framework::binary::node::{ + NamadaParametersOverride, NodeConfigOverride, NodeGenesisOverride, +}; use crate::framework::nary::node::{run_nary_node_test, NaryNodeTest}; use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; use crate::relayer::driver::RelayerDriver; @@ -49,6 +51,7 @@ where + NodeGenesisOverride + RelayerConfigOverride + SupervisorOverride + + NamadaParametersOverride + TopologyOverride, { run_nary_node_test(&RunNaryChainTest::new(&RunWithSupervisor::new(test))) @@ -79,6 +82,7 @@ where + NodeGenesisOverride + RelayerConfigOverride + SupervisorOverride + + NamadaParametersOverride + TopologyOverride, { run_nary_node_test(&RunSelfConnectedNaryChainTest::new( diff --git a/tools/test-framework/src/framework/nary/channel.rs b/tools/test-framework/src/framework/nary/channel.rs index 0f4fe189dd..c48f728fd7 100644 --- a/tools/test-framework/src/framework/nary/channel.rs +++ b/tools/test-framework/src/framework/nary/channel.rs @@ -14,7 +14,9 @@ use crate::framework::base::{HasOverrides, TestConfigOverride}; use crate::framework::binary::chain::{RelayerConfigOverride, TopologyOverride}; use crate::framework::binary::channel::{BinaryChannelTest, ChannelOrderOverride}; use crate::framework::binary::connection::ConnectionDelayOverride; -use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::framework::binary::node::{ + NamadaParametersOverride, NodeConfigOverride, NodeGenesisOverride, +}; use crate::framework::nary::chain::RunNaryChainTest; use crate::framework::nary::connection::{NaryConnectionTest, RunNaryConnectionTest}; use crate::framework::nary::node::run_nary_node_test; @@ -39,6 +41,7 @@ where + ConnectionDelayOverride + PortsOverride + ChannelOrderOverride + + NamadaParametersOverride + TopologyOverride, { run_nary_node_test(&RunNaryChainTest::new(&RunNaryConnectionTest::new( @@ -58,6 +61,7 @@ where + ConnectionDelayOverride + PortsOverride<2> + ChannelOrderOverride + + NamadaParametersOverride + TopologyOverride, { run_nary_channel_test(&RunBinaryAsNaryChannelTest::new(test)) diff --git a/tools/test-framework/src/framework/nary/connection.rs b/tools/test-framework/src/framework/nary/connection.rs index 6d54b1e11d..646ffdbd2e 100644 --- a/tools/test-framework/src/framework/nary/connection.rs +++ b/tools/test-framework/src/framework/nary/connection.rs @@ -12,7 +12,9 @@ use crate::error::Error; use crate::framework::base::{HasOverrides, TestConfigOverride}; use crate::framework::binary::chain::{RelayerConfigOverride, TopologyOverride}; use crate::framework::binary::connection::{BinaryConnectionTest, ConnectionDelayOverride}; -use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::framework::binary::node::{ + NamadaParametersOverride, NodeConfigOverride, NodeGenesisOverride, +}; use crate::framework::nary::chain::{NaryChainTest, RunNaryChainTest}; use crate::framework::nary::node::run_nary_node_test; use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride}; @@ -35,6 +37,7 @@ where + RelayerConfigOverride + SupervisorOverride + ConnectionDelayOverride + + NamadaParametersOverride + TopologyOverride, { run_nary_node_test(&RunNaryChainTest::new(&RunNaryConnectionTest::new( @@ -141,8 +144,7 @@ where } } -impl NaryConnectionTest - for RunWithSupervisor<'_, Test> +impl NaryConnectionTest for RunWithSupervisor<'_, Test> where Test: NaryConnectionTest, Test: HasOverrides, diff --git a/tools/test-framework/src/framework/nary/node.rs b/tools/test-framework/src/framework/nary/node.rs index 2ea2379e25..e5c0d7a5fe 100644 --- a/tools/test-framework/src/framework/nary/node.rs +++ b/tools/test-framework/src/framework/nary/node.rs @@ -3,12 +3,15 @@ running without setting up the relayer. */ +use crate::bootstrap::namada::bootstrap_namada_node; use crate::bootstrap::single::bootstrap_single_node; use crate::chain::builder::ChainBuilder; use crate::error::Error; use crate::framework::base::HasOverrides; use crate::framework::base::{run_basic_test, BasicTest, TestConfigOverride}; -use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::framework::binary::node::{ + NamadaParametersOverride, NodeConfigOverride, NodeGenesisOverride, +}; use crate::types::config::TestConfig; use crate::types::single::node::FullNode; use crate::util::array::try_into_array; @@ -17,7 +20,8 @@ pub fn run_nary_node_test(test: &Test) -> Re where Test: NaryNodeTest, Test: HasOverrides, - Overrides: NodeConfigOverride + NodeGenesisOverride + TestConfigOverride, + Overrides: + NodeConfigOverride + NodeGenesisOverride + TestConfigOverride + NamadaParametersOverride, { run_basic_test(&RunNaryNodeTest { test }) } @@ -49,21 +53,39 @@ impl BasicTest for RunNaryNodeTest<'_, Test, where Test: NaryNodeTest, Test: HasOverrides, - Overrides: NodeConfigOverride + NodeGenesisOverride, + Overrides: NodeConfigOverride + NodeGenesisOverride + NamadaParametersOverride, { fn run(&self, config: &TestConfig, builder: &ChainBuilder) -> Result<(), Error> { let mut nodes = Vec::new(); let mut node_processes = Vec::new(); for i in 0..SIZE { - let node = bootstrap_single_node( - builder, - &format!("{}", i + 1), - config.bootstrap_with_random_ids, - |config| self.test.get_overrides().modify_node_config(config), - |genesis| self.test.get_overrides().modify_genesis_file(genesis), - i, - )?; + let is_namada = builder.command_paths == vec!["namada".to_string()] + || builder.command_paths.get(i) == Some(&"namada".to_string()); + let node = if is_namada { + bootstrap_namada_node( + builder, + &format!("{}", i + 1), + config.bootstrap_with_random_ids, + |config| self.test.get_overrides().modify_node_config(config), + |genesis| self.test.get_overrides().modify_genesis_file(genesis), + |parameters| { + self.test + .get_overrides() + .namada_modify_parameter_file(parameters) + }, + i, + )? + } else { + bootstrap_single_node( + builder, + &format!("{}", i + 1), + config.bootstrap_with_random_ids, + |config| self.test.get_overrides().modify_node_config(config), + |genesis| self.test.get_overrides().modify_genesis_file(genesis), + i, + )? + }; node_processes.push(node.process.clone()); nodes.push(node); diff --git a/tools/test-framework/src/framework/overrides.rs b/tools/test-framework/src/framework/overrides.rs index 70398de376..bf08d8c06d 100644 --- a/tools/test-framework/src/framework/overrides.rs +++ b/tools/test-framework/src/framework/overrides.rs @@ -18,7 +18,9 @@ use crate::framework::binary::channel::{ ChannelOrderOverride, ChannelVersionOverride, PortsOverride, }; use crate::framework::binary::connection::ConnectionDelayOverride; -use crate::framework::binary::node::{NodeConfigOverride, NodeGenesisOverride}; +use crate::framework::binary::node::{ + NamadaParametersOverride, NodeConfigOverride, NodeGenesisOverride, +}; use crate::framework::nary::channel::PortsOverride as NaryPortsOverride; use crate::framework::supervisor::SupervisorOverride; use crate::types::config::TestConfig; @@ -81,6 +83,10 @@ pub trait TestOverrides { // No modification by default } + fn namada_modify_parameter_file(&self, _parameter: &mut toml::Value) -> Result<(), Error> { + Ok(()) + } + /// Returns the settings for the foreign client on the first chain for the /// second chain. The defaults are for a client connecting two Cosmos chains /// with no custom settings. @@ -180,6 +186,12 @@ impl NodeGenesisOverride for Test { } } +impl NamadaParametersOverride for Test { + fn namada_modify_parameter_file(&self, parameter: &mut toml::Value) -> Result<(), Error> { + TestOverrides::namada_modify_parameter_file(self, parameter) + } +} + impl RelayerConfigOverride for Test { fn modify_relayer_config(&self, config: &mut Config) { TestOverrides::modify_relayer_config(self, config) diff --git a/tools/test-framework/src/ibc/denom.rs b/tools/test-framework/src/ibc/denom.rs index 965a56b1b7..d0301b9e15 100644 --- a/tools/test-framework/src/ibc/denom.rs +++ b/tools/test-framework/src/ibc/denom.rs @@ -8,6 +8,7 @@ use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, PortId}; use sha2::{Digest, Sha256}; use subtle_encoding::hex; +use crate::chain::chain_type::ChainType; use crate::types::id::{TaggedChannelIdRef, TaggedPortIdRef}; use crate::types::tagged::*; @@ -16,11 +17,16 @@ use crate::types::tagged::*; */ #[derive(Debug, Clone)] pub enum Denom { - Base(String), + Base { + display_name: String, + raw_address: String, + token_denom: u8, + }, Ibc { path: String, - denom: String, + denom: Box, hashed: String, + token_denom: u8, }, } @@ -51,6 +57,18 @@ pub type TaggedDenomRef<'a, Chain> = MonoTagged; Returns the derived denomination on `ChainB`. */ pub fn derive_ibc_denom( + chain_type: &ChainType, + port_id: &TaggedPortIdRef, + channel_id: &TaggedChannelIdRef, + denom: &TaggedDenomRef, +) -> Result, Error> { + match chain_type { + ChainType::Namada => derive_namada_ibc_denom(port_id, channel_id, denom), + _ => derive_cosmos_ibc_denom(port_id, channel_id, denom), + } +} + +fn derive_cosmos_ibc_denom( port_id: &TaggedPortIdRef, channel_id: &TaggedChannelIdRef, denom: &TaggedDenomRef, @@ -77,16 +95,26 @@ pub fn derive_ibc_denom( } match denom.value() { - Denom::Base(denom) => { - let hashed = derive_denom(port_id.value(), channel_id.value(), denom)?; + Denom::Base { + raw_address, + token_denom, + .. + } => { + let hashed = derive_denom(port_id.value(), channel_id.value(), raw_address)?; Ok(MonoTagged::new(Denom::Ibc { path: format!("{port_id}/{channel_id}"), - denom: denom.clone(), + denom: Box::new((*denom.value()).clone()), hashed, + token_denom: *token_denom, })) } - Denom::Ibc { path, denom, .. } => { + Denom::Ibc { + path, + denom, + token_denom, + .. + } => { let new_path = format!("{port_id}/{channel_id}/{path}"); let hashed = derive_denom_with_path(&format!("{new_path}/{denom}"))?; @@ -94,19 +122,65 @@ pub fn derive_ibc_denom( path: new_path, denom: denom.clone(), hashed, + token_denom: *token_denom, + })) + } + } +} + +fn derive_namada_ibc_denom( + port_id: &TaggedPortIdRef, + channel_id: &TaggedChannelIdRef, + denom: &TaggedDenomRef, +) -> Result, Error> { + match denom.value() { + Denom::Base { + raw_address, + token_denom, + .. + } => { + let path = format!("{port_id}/{channel_id}"); + let ibc_token_addr = namada_sdk::ibc::trace::ibc_token(format!("{path}/{raw_address}")); + + Ok(MonoTagged::new(Denom::Ibc { + path, + denom: Box::new((*denom.value()).clone()), + hashed: ibc_token_addr.to_string(), + token_denom: *token_denom, + })) + } + Denom::Ibc { + path, + denom, + token_denom, + .. + } => { + let new_path = format!("{port_id}/{channel_id}/{path}"); + let ibc_token_addr = + namada_sdk::ibc::trace::ibc_token(format!("{new_path}/{}", denom.hash_only())); + + Ok(MonoTagged::new(Denom::Ibc { + path: new_path, + denom: denom.clone(), + hashed: ibc_token_addr.to_string(), + token_denom: *token_denom, })) } } } impl Denom { - pub fn base(denom: &str) -> Self { - Denom::Base(denom.to_string()) + pub fn base(display_name: &str, raw_address: &str) -> Self { + Denom::Base { + display_name: display_name.to_owned(), + raw_address: raw_address.to_owned(), + token_denom: if display_name == "nam" { 6 } else { 0 }, + } } pub fn hash_only(&self) -> String { match self { - Denom::Base(denom) => denom.to_string(), + Denom::Base { raw_address, .. } => raw_address.to_string(), Denom::Ibc { hashed, .. } => match hashed.find('/') { Some(index) => hashed[index + 1..].to_string(), None => hashed.to_string(), @@ -114,9 +188,23 @@ impl Denom { } } + pub fn display_name(&self) -> String { + match self { + Denom::Base { display_name, .. } => display_name.to_string(), + Denom::Ibc { hashed, .. } => hashed.to_string(), + } + } + + pub fn namada_display_name(&self) -> String { + match self { + Denom::Base { display_name, .. } => display_name.to_string(), + Denom::Ibc { path, denom, .. } => format!("{path}/{}", denom.namada_display_name()), + } + } + pub fn as_str(&self) -> &str { match self { - Denom::Base(denom) => denom, + Denom::Base { display_name, .. } => display_name, Denom::Ibc { hashed, .. } => hashed, } } @@ -125,8 +213,8 @@ impl Denom { impl Display for Denom { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { - Denom::Base(denom) => { - write!(f, "{denom}") + Denom::Base { raw_address, .. } => { + write!(f, "{raw_address}") } Denom::Ibc { hashed, .. } => { write!(f, "{hashed}") @@ -138,19 +226,32 @@ impl Display for Denom { impl PartialEq for Denom { fn eq(&self, other: &Self) -> bool { match (self, other) { - (Self::Base(d1), Self::Base(d2)) => d1 == d2, + ( + Self::Base { + display_name: d1, + raw_address: a1, + token_denom: td1, + }, + Self::Base { + display_name: d2, + raw_address: a2, + token_denom: td2, + }, + ) => (d1 == d2) && (a1 == a2) && (td1 == td2), ( Self::Ibc { path: p1, denom: d1, hashed: h1, + token_denom: td1, }, Self::Ibc { path: p2, denom: d2, hashed: h2, + token_denom: td2, }, - ) => p1 == p2 && d1 == d2 && h1 == h2, + ) => p1 == p2 && d1 == d2 && h1 == h2 && (td1 == td2), _ => self.as_str() == other.as_str(), } } diff --git a/tools/test-framework/src/ibc/token.rs b/tools/test-framework/src/ibc/token.rs index 7300304d18..e7ece52fc0 100644 --- a/tools/test-framework/src/ibc/token.rs +++ b/tools/test-framework/src/ibc/token.rs @@ -1,7 +1,9 @@ use core::ops::{Add, Sub}; use ibc_relayer_types::applications::transfer::amount::Amount; use ibc_relayer_types::applications::transfer::coin::{Coin, RawCoin}; +use ibc_relayer_types::bigint::U256; +use crate::chain::chain_type::ChainType; use crate::error::Error; use crate::ibc::denom::{derive_ibc_denom, Denom, TaggedDenom, TaggedDenomRef}; use crate::types::id::{TaggedChannelIdRef, TaggedPortIdRef}; @@ -21,6 +23,7 @@ pub trait TaggedTokenExt { fn transfer( &self, + chain_type: &ChainType, port_id: &TaggedPortIdRef, channel_id: &TaggedChannelIdRef, ) -> Result, Error>; @@ -45,10 +48,11 @@ impl TaggedTokenExt for TaggedToken { fn transfer( &self, + chain_type: &ChainType, port_id: &TaggedPortIdRef, channel_id: &TaggedChannelIdRef, ) -> Result, Error> { - let denom = derive_ibc_denom(port_id, channel_id, &self.denom())?; + let denom = derive_ibc_denom(chain_type, port_id, channel_id, &self.denom())?; Ok(denom.with_amount(self.value().amount)) } @@ -69,10 +73,11 @@ impl TaggedTokenExt for TaggedTokenRef<'_, Chain> { fn transfer( &self, + chain_type: &ChainType, port_id: &TaggedPortIdRef, channel_id: &TaggedChannelIdRef, ) -> Result, Error> { - let denom = derive_ibc_denom(port_id, channel_id, &self.denom())?; + let denom = derive_ibc_denom(chain_type, port_id, channel_id, &self.denom())?; Ok(denom.with_amount(self.value().amount)) } @@ -80,18 +85,32 @@ impl TaggedTokenExt for TaggedTokenRef<'_, Chain> { impl TaggedDenomExt for TaggedDenom { fn with_amount(&self, amount: impl Into) -> TaggedToken { + let amount: Amount = match self.value() { + Denom::Base { .. } => amount.into(), + Denom::Ibc { token_denom, .. } => { + let amount: Amount = amount.into(); + (amount.0 * U256::from(10).pow(U256::from(*token_denom))).into() + } + }; self.map(|denom| Token { denom: denom.clone(), - amount: amount.into(), + amount, }) } } impl TaggedDenomExt for TaggedDenomRef<'_, Chain> { fn with_amount(&self, amount: impl Into) -> TaggedToken { + let amount: Amount = match self.value() { + Denom::Base { .. } => amount.into(), + Denom::Ibc { token_denom, .. } => { + let amount: Amount = amount.into(); + (amount.0 * U256::from(10).pow(U256::from(*token_denom))).into() + } + }; self.map(|denom| Token { denom: (*denom).clone(), - amount: amount.into(), + amount, }) } } diff --git a/tools/test-framework/src/relayer/chain.rs b/tools/test-framework/src/relayer/chain.rs index 4d98354aea..1308d49d5a 100644 --- a/tools/test-framework/src/relayer/chain.rs +++ b/tools/test-framework/src/relayer/chain.rs @@ -22,7 +22,7 @@ use crossbeam_channel as channel; use ibc_proto::ibc::core::channel::v1::{QueryUpgradeErrorRequest, QueryUpgradeRequest}; -use ibc_relayer::chain::cosmos::version::Specs; +use ibc_relayer::chain::version::Specs; use ibc_relayer_types::applications::ics28_ccv::msgs::{ConsumerChain, ConsumerId}; use ibc_relayer_types::core::ics04_channel::upgrade::{ErrorReceipt, Upgrade}; use tracing::Span; diff --git a/tools/test-framework/src/relayer/fee.rs b/tools/test-framework/src/relayer/fee.rs index 51b1ff6814..e4a2a92bd4 100644 --- a/tools/test-framework/src/relayer/fee.rs +++ b/tools/test-framework/src/relayer/fee.rs @@ -1,3 +1,5 @@ +use eyre::eyre; + use core::time::Duration; use http::uri::Uri; use ibc_relayer::chain::cosmos::query::fee::{ @@ -63,13 +65,13 @@ pub async fn ibc_token_transfer_with_fee( let messages = vec![pay_message, transfer_message]; - let events = simple_send_tx( - rpc_client.value(), - tx_config.value(), - &sender.value().key, - messages, - ) - .await?; + let key = &sender + .value() + .key + .downcast() + .ok_or_else(|| eyre!("unable to downcast key")) + .map_err(Error::generic)?; + let events = simple_send_tx(rpc_client.value(), tx_config.value(), key, messages).await?; Ok(events) } @@ -101,14 +103,15 @@ pub async fn pay_packet_fee( ) .map_err(handle_generic_error)?; - let events = simple_send_tx( - rpc_client.value(), - tx_config.value(), - &payer.value().key, - vec![message], - ) - .await - .map_err(Error::relayer)?; + let key = &payer + .value() + .key + .downcast() + .ok_or_else(|| eyre!("unable to downcast key")) + .map_err(Error::generic)?; + let events = simple_send_tx(rpc_client.value(), tx_config.value(), key, vec![message]) + .await + .map_err(Error::relayer)?; Ok(events) } @@ -140,13 +143,13 @@ pub async fn register_counterparty_payee( let messages = vec![message]; - simple_send_tx( - rpc_client.value(), - tx_config.value(), - &wallet.value().key, - messages, - ) - .await?; + let key = &wallet + .value() + .key + .downcast() + .ok_or_else(|| eyre!("unable to downcast key")) + .map_err(Error::generic)?; + simple_send_tx(rpc_client.value(), tx_config.value(), key, messages).await?; Ok(()) } @@ -174,13 +177,13 @@ pub async fn register_payee( let messages = vec![message]; - simple_send_tx( - rpc_client.value(), - tx_config.value(), - &wallet.value().key, - messages, - ) - .await?; + let key = &wallet + .value() + .key + .downcast() + .ok_or_else(|| eyre!("unable to downcast key")) + .map_err(Error::generic)?; + simple_send_tx(rpc_client.value(), tx_config.value(), key, messages).await?; Ok(()) } diff --git a/tools/test-framework/src/relayer/transfer.rs b/tools/test-framework/src/relayer/transfer.rs index 26595051a5..43a379ee29 100644 --- a/tools/test-framework/src/relayer/transfer.rs +++ b/tools/test-framework/src/relayer/transfer.rs @@ -6,7 +6,6 @@ use core::ops::Add; use core::time::Duration; use eyre::eyre; -use ibc_relayer_types::core::ics04_channel::packet::Packet; use ibc_relayer_types::events::IbcEvent; use ibc_proto::google::protobuf::Any; @@ -20,6 +19,7 @@ use ibc_relayer_types::core::ics04_channel::timeout::TimeoutHeight; use ibc_relayer_types::timestamp::Timestamp; use tendermint_rpc::HttpClient; +use crate::chain::exec::simple_exec; use crate::error::{handle_generic_error, Error}; use crate::ibc::token::TaggedTokenRef; use crate::types::id::{TaggedChannelIdRef, TaggedPortIdRef}; @@ -92,7 +92,7 @@ pub async fn ibc_token_transfer( token: &TaggedTokenRef<'_, SrcChain>, memo: Option, timeout: Option, -) -> Result { +) -> Result<(), Error> { let message = build_transfer_message( port_id, channel_id, @@ -103,15 +103,21 @@ pub async fn ibc_token_transfer( memo.clone(), )?; + let key = &sender + .value() + .key + .downcast() + .ok_or_else(|| eyre!("unable to downcast key")) + .map_err(Error::generic)?; let events = simple_send_tx( rpc_client.into_value(), tx_config.value(), - &sender.value().key, + key, vec![message], ) .await?; - let packet = events + let _packet = events .into_iter() .find_map(|event| match event.event { IbcEvent::SendPacket(ev) => Some(ev.packet), @@ -119,7 +125,95 @@ pub async fn ibc_token_transfer( }) .ok_or_else(|| eyre!("failed to find send packet event"))?; - Ok(packet) + Ok(()) +} + +pub fn local_namada_token_transfer( + home_path: &str, + sender: &str, + recipient: &str, + denom: &str, + amount: &str, + rpc_port: &str, +) -> Result<(), Error> { + simple_exec( + "namada local transfer", + "namadac", + &[ + "--base-dir", + home_path, + "transparent-transfer", + "--source", + sender, + "--target", + recipient, + "--token", + denom, + "--amount", + amount, + "--signing-keys", + &format!("{sender}-key"), + "--gas-limit", + "150000", + "--node", + &format!("http://127.0.0.1:{rpc_port}"), + ], + )?; + + Ok(()) +} + +pub fn ibc_namada_token_transfer( + home_path: &str, + sender: &str, + receiver: &str, + denom: &str, + amount: &str, + channel_id: &str, + rpc_port: &str, + memo: Option, + timeout: Option, +) -> Result<(), Error> { + let signing_key = format!("{sender}-key"); + let node = format!("http://127.0.0.1:{rpc_port}"); + let mut args = vec![ + "--base-dir", + home_path, + "ibc-transfer", + "--source", + sender, + "--receiver", + receiver, + "--token", + denom, + "--amount", + amount, + "--signing-keys", + &signing_key, + "--channel-id", + channel_id, + "--gas-limit", + "150000", + "--node", + &node, + ]; + + let memo_str = memo.clone().unwrap_or_default(); + if memo.is_some() { + args.push("--ibc-memo"); + args.push(&memo_str); + } + + let timeout_str; + if let Some(timeout) = timeout { + args.push("--timeout-sec-offset"); + timeout_str = timeout.as_secs().to_string(); + args.push(&timeout_str); + } + + simple_exec("namada transfer", "namadac", &args)?; + + Ok(()) } pub async fn batched_ibc_token_transfer( @@ -147,13 +241,13 @@ pub async fn batched_ibc_token_transfer( .take(num_msgs) .collect::, _>>()?; - batched_send_tx( - rpc_client.value(), - tx_config.value(), - &sender.value().key, - messages, - ) - .await?; + let key = &sender + .value() + .key + .downcast() + .ok_or_else(|| eyre!("unable to downcast key")) + .map_err(Error::generic)?; + batched_send_tx(rpc_client.value(), tx_config.value(), key, messages).await?; Ok(()) } diff --git a/tools/test-framework/src/types/single/node.rs b/tools/test-framework/src/types/single/node.rs index 4abdea72b8..51ab9499d3 100644 --- a/tools/test-framework/src/types/single/node.rs +++ b/tools/test-framework/src/types/single/node.rs @@ -21,6 +21,7 @@ use tendermint_rpc::WebSocketClientUrl; use crate::chain::chain_type::ChainType as TestedChainType; use crate::chain::driver::ChainDriver; +use crate::chain::exec::simple_exec; use crate::ibc::denom::Denom; use crate::prelude::TestConfig; use crate::types::env::{prefix_writer, EnvWriter, ExportEnv}; @@ -149,6 +150,10 @@ impl FullNode { TestedChainType::Provenance => { config::GasPrice::new(5000.0, test_config.native_token(chain_number).clone()) } + TestedChainType::Namada => { + let denom = get_denom(&self.chain_driver.home_path)?; + config::GasPrice::new(0.000003, denom) + } _ => config::GasPrice::new(0.003, test_config.native_token(chain_number).clone()), }; @@ -158,51 +163,104 @@ impl FullNode { DynamicGasPrice::disabled() }; - Ok(config::ChainConfig::CosmosSdk(CosmosSdkConfig { - id: self.chain_driver.chain_id.clone(), - rpc_addr: Url::from_str(&self.chain_driver.rpc_address())?, - grpc_addr: Url::from_str(&self.chain_driver.grpc_address())?, - event_source: config::EventSourceMode::Push { - url: WebSocketClientUrl::from_str(&self.chain_driver.websocket_address())?, - batch_delay: config::default::batch_delay(), - }, - rpc_timeout: config::default::rpc_timeout(), - trusted_node: false, - genesis_restart: None, - account_prefix: self.chain_driver.account_prefix.clone(), - key_name: self.wallets.relayer.id.0.clone(), - key_store_type: Store::Test, - key_store_folder: Some(hermes_keystore_dir.into()), - store_prefix: "ibc".to_string(), - default_gas: None, - max_gas: Some(3000000), - gas_adjustment: None, - gas_multiplier: Some(GasMultiplier::unsafe_new(1.5)), - dynamic_gas_price, - fee_granter: None, - max_msg_num: Default::default(), - max_tx_size: Default::default(), - max_grpc_decoding_size: config::default::max_grpc_decoding_size(), - query_packets_chunk_size: config::default::query_packets_chunk_size(), - max_block_time: Duration::from_secs(30), - clock_drift: Duration::from_secs(5), - trusting_period: Some(Duration::from_secs(14 * 24 * 3600)), - client_refresh_rate: config::default::client_refresh_rate(), - ccv_consumer_chain: false, - trust_threshold: Default::default(), - gas_price, - packet_filter: Default::default(), - address_type: chain_type.address_type(), - memo_prefix: Default::default(), - memo_overwrite: None, - proof_specs: Default::default(), - extension_options: Default::default(), - sequential_batch_tx: false, - compat_mode, - clear_interval: None, - excluded_sequences: ExcludedSequences::new(BTreeMap::new()), - allow_ccq: true, - })) + let chain_config = match chain_type { + TestedChainType::Cosmos { dynamic_fee: _ } + | TestedChainType::Provenance + | TestedChainType::Evmos + | TestedChainType::Osmosis + | TestedChainType::Injective => config::ChainConfig::CosmosSdk(CosmosSdkConfig { + id: self.chain_driver.chain_id.clone(), + rpc_addr: Url::from_str(&self.chain_driver.rpc_address())?, + grpc_addr: Url::from_str(&self.chain_driver.grpc_address())?, + event_source: config::EventSourceMode::Push { + url: WebSocketClientUrl::from_str(&self.chain_driver.websocket_address())?, + batch_delay: config::default::batch_delay(), + }, + rpc_timeout: config::default::rpc_timeout(), + trusted_node: false, + genesis_restart: None, + account_prefix: self.chain_driver.account_prefix.clone(), + key_name: self.wallets.relayer.id.0.clone(), + key_store_type: Store::Test, + key_store_folder: Some(hermes_keystore_dir.into()), + store_prefix: "ibc".to_string(), + default_gas: None, + max_gas: Some(3000000), + gas_adjustment: None, + gas_multiplier: Some(GasMultiplier::unsafe_new(1.5)), + dynamic_gas_price, + fee_granter: None, + max_msg_num: Default::default(), + max_tx_size: Default::default(), + max_grpc_decoding_size: config::default::max_grpc_decoding_size(), + query_packets_chunk_size: config::default::query_packets_chunk_size(), + max_block_time: Duration::from_secs(30), + clock_drift: Duration::from_secs(5), + trusting_period: Some(Duration::from_secs(14 * 24 * 3600)), + client_refresh_rate: config::default::client_refresh_rate(), + ccv_consumer_chain: false, + trust_threshold: Default::default(), + gas_price, + packet_filter: Default::default(), + address_type: chain_type.address_type(), + memo_prefix: Default::default(), + memo_overwrite: None, + proof_specs: Default::default(), + extension_options: Default::default(), + sequential_batch_tx: false, + compat_mode, + clear_interval: None, + excluded_sequences: ExcludedSequences::new(BTreeMap::new()), + allow_ccq: true, + }), + TestedChainType::Namada => config::ChainConfig::Namada(CosmosSdkConfig { + id: self.chain_driver.chain_id.clone(), + rpc_addr: Url::from_str(&self.chain_driver.rpc_address())?, + grpc_addr: Url::from_str(&self.chain_driver.grpc_address())?, + event_source: config::EventSourceMode::Push { + url: WebSocketClientUrl::from_str(&self.chain_driver.websocket_address())?, + batch_delay: config::default::batch_delay(), + }, + rpc_timeout: config::default::rpc_timeout(), + trusted_node: false, + genesis_restart: None, + account_prefix: "".to_owned(), + key_name: self.wallets.relayer.id.0.clone(), + key_store_type: Store::Test, + key_store_folder: Some(hermes_keystore_dir.into()), + store_prefix: "ibc".to_string(), + default_gas: None, + max_gas: Some(4000000), + gas_adjustment: None, + gas_multiplier: Some(GasMultiplier::unsafe_new(1.2)), + dynamic_gas_price: DynamicGasPrice::default(), + fee_granter: None, + max_msg_num: Default::default(), + max_tx_size: Default::default(), + max_grpc_decoding_size: config::default::max_grpc_decoding_size(), + query_packets_chunk_size: config::default::query_packets_chunk_size(), + max_block_time: Duration::from_secs(30), + clock_drift: Duration::from_secs(5), + trusting_period: Some(Duration::from_secs(1999)), + client_refresh_rate: config::default::client_refresh_rate(), + ccv_consumer_chain: false, + trust_threshold: Default::default(), + gas_price, + packet_filter: Default::default(), + address_type: chain_type.address_type(), + memo_prefix: Default::default(), + memo_overwrite: None, + proof_specs: Default::default(), + extension_options: Default::default(), + sequential_batch_tx: false, + compat_mode, + clear_interval: None, + excluded_sequences: ExcludedSequences::new(BTreeMap::new()), + allow_ccq: false, + }), + }; + + Ok(chain_config) } /** @@ -220,6 +278,27 @@ impl FullNode { } } +fn get_denom(home_path: &str) -> Result { + let output = simple_exec( + "namada", + "namadaw", + &["--base-dir", home_path, "find", "--alias", "nam"], + )? + .stdout; + + let words: Vec<&str> = output.split_whitespace().collect(); + + if let Some(derived_index) = words.iter().position(|&w| w == "Established:") { + if let Some(&denom) = words.get(derived_index + 1) { + return Ok(denom.to_owned()); + } + return Err(eyre!( + "chain id is not 3 words after `Established:`: {output}" + )); + } + Err(eyre!("could not find `Derived` in output: {output}")) +} + impl ExportEnv for FullNode { fn export_env(&self, writer: &mut impl EnvWriter) { self.chain_driver.export_env(writer); diff --git a/tools/test-framework/src/types/wallet.rs b/tools/test-framework/src/types/wallet.rs index 89b75f5b82..943ebb9aa3 100644 --- a/tools/test-framework/src/types/wallet.rs +++ b/tools/test-framework/src/types/wallet.rs @@ -3,7 +3,7 @@ */ use core::fmt::{self, Display}; -use ibc_relayer::keyring::Secp256k1KeyPair; +use ibc_relayer::keyring::{AnySigningKeyPair, NamadaKeyPair, Secp256k1KeyPair}; use crate::types::env::{prefix_writer, EnvWriter, ExportEnv}; use crate::types::tagged::*; @@ -36,7 +36,7 @@ pub struct Wallet { // TODO: Parameterize this type on `SigningKeyPair` /// The wallet key information in the form of `SigningKeyPair` /// that is used by the relayer. - pub key: Secp256k1KeyPair, + pub key: AnySigningKeyPair, } /** @@ -82,7 +82,7 @@ pub trait TaggedWallet { fn address(&self) -> MonoTagged; /// Get the `SigningKeyPair` tagged with the given `Chain`. - fn key(&self) -> MonoTagged; + fn key(&self) -> MonoTagged; } /** @@ -107,11 +107,19 @@ pub trait TaggedTestWalletsExt { impl Wallet { /// Create a new [`Wallet`] - pub fn new(id: String, address: String, key: Secp256k1KeyPair) -> Self { + pub fn new_secp256(id: String, address: String, secp256_key: Secp256k1KeyPair) -> Self { Self { id: WalletId(id), address: WalletAddress(address), - key, + key: secp256_key.into(), + } + } + + pub fn new_namada(id: String, address: String, namada_key: NamadaKeyPair) -> Self { + Self { + id: WalletId(id), + address: WalletAddress(address), + key: namada_key.into(), } } } @@ -131,7 +139,7 @@ impl TaggedWallet for MonoTagged { self.map_ref(|w| &w.address) } - fn key(&self) -> MonoTagged { + fn key(&self) -> MonoTagged { self.map_ref(|w| &w.key) } } @@ -145,7 +153,7 @@ impl TaggedWallet for MonoTagged { self.map_ref(|w| &w.address) } - fn key(&self) -> MonoTagged { + fn key(&self) -> MonoTagged { self.map_ref(|w| &w.key) } } diff --git a/tools/test-framework/src/util/interchain_security.rs b/tools/test-framework/src/util/interchain_security.rs index ea66e12f4f..70a0e5da39 100644 --- a/tools/test-framework/src/util/interchain_security.rs +++ b/tools/test-framework/src/util/interchain_security.rs @@ -1,4 +1,4 @@ -use crate::chain::config::set_voting_period; +use crate::chain::config::cosmos::set_voting_period; use crate::prelude::*; use ibc_relayer::chain::tracking::TrackedMsgs; @@ -35,7 +35,7 @@ pub fn update_relayer_config_for_consumer_chain(config: &mut Config) { chain_config.ccv_consumer_chain = true; chain_config.trusting_period = Some(Duration::from_secs(99)); } - ChainConfig::CosmosSdk(_) => {} + ChainConfig::CosmosSdk(_) | ChainConfig::Namada(_) => {} } } } diff --git a/tools/test-framework/src/util/mod.rs b/tools/test-framework/src/util/mod.rs index 7db62f867e..0e677c7d6f 100644 --- a/tools/test-framework/src/util/mod.rs +++ b/tools/test-framework/src/util/mod.rs @@ -6,6 +6,7 @@ pub mod array; pub mod assert; pub mod file; pub mod interchain_security; +pub mod namada; pub mod proposal_status; pub mod random; pub mod retry; diff --git a/tools/test-framework/src/util/namada.rs b/tools/test-framework/src/util/namada.rs new file mode 100644 index 0000000000..03d967b17e --- /dev/null +++ b/tools/test-framework/src/util/namada.rs @@ -0,0 +1,176 @@ +use ibc_proto::Protobuf; +use ibc_relayer::consensus_state::{AnyConsensusState, AnyConsensusStateWithHeight}; +use ibc_relayer_types::core::ics04_channel::packet::Sequence; +use ibc_relayer_types::core::ics24_host::identifier::{ChannelId, ClientId, PortId}; +use ibc_relayer_types::events::IbcEventType; +use ibc_relayer_types::Height; +use itertools::Itertools; +use namada_sdk::events::extend::Height as HeightAttr; +use namada_sdk::ibc::storage::{consensus_height, consensus_state_prefix}; +use namada_sdk::queries::RPC; +use namada_sdk::storage::{Key, PrefixValue}; +use namada_sdk::tx::Tx; +use namada_tendermint_rpc::{Client, HttpClient, Url}; +use std::fs::File; +use std::io::Read; +use toml::Value; + +use crate::prelude::*; + +pub fn get_namada_denom_address( + chain_id: &str, + home_path: &str, + denom: &str, +) -> Result { + let file_path = format!("{}/{}/wallet.toml", home_path, chain_id); + tracing::warn!("file path: {file_path}"); + let mut toml_content = String::new(); + let mut file = File::open(file_path).expect("Failed to open file"); + file.read_to_string(&mut toml_content) + .expect("Failed to read file"); + + // Parse the TOML content into a `toml::Value` object + let toml_value: Value = toml::from_str(&toml_content).expect("Failed to parse TOML"); + + // Extract a field from the TOML file + let denom_address = toml_value + .get("addresses") + .ok_or_else(|| eyre!("missing `addresses` field"))? + .get(denom) + .ok_or_else(|| eyre!("missing `{denom}` field"))? + .as_str() + .unwrap_or(denom) + .to_owned(); + + Ok(denom_address) +} + +pub async fn query_consensus_states( + rpc_address: Url, + client_id: &ClientId, +) -> Result, Error> { + // convert to that of ibc-rs + let client_id = client_id + .to_string() + .parse() + .expect("Client ID conversion shouldn't fail"); + let prefix = consensus_state_prefix(&client_id); + let mut states = vec![]; + for PrefixValue { key, value } in query_prefix(rpc_address, &prefix).await? { + let height = consensus_height(&key).expect("Key should have the height"); + let state = AnyConsensusStateWithHeight { + height: Height::new(height.revision_number(), height.revision_height()).unwrap(), + consensus_state: AnyConsensusState::decode_vec(&value) + .map_err(|_| Error::query_client())?, + }; + states.push(state); + } + Ok(states) +} + +async fn query_prefix(rpc_address: Url, prefix: &Key) -> Result, Error> { + let client = HttpClient::new(rpc_address).expect("Failed to make a RPC client"); + let response = RPC + .shell() + .storage_prefix(&client, None, None, false, prefix) + .await + .map_err(|e| eyre!("Namada query with prefix failed: {e}"))?; + Ok(response.data) +} + +pub async fn query_receive_tx_memo( + rpc_address: Url, + src_port_id: &PortId, + src_channel_id: &ChannelId, + dst_port_id: &PortId, + dst_channel_id: &ChannelId, + sequence: Sequence, +) -> Result { + let client = HttpClient::new(rpc_address).expect("Failed to make a RPC client"); + let height = query_write_ack_packet_height( + &client, + src_port_id, + src_channel_id, + dst_port_id, + dst_channel_id, + sequence, + ) + .await?; + + let height = namada_tendermint::block::Height::try_from(height.revision_height()) + .expect("Height should be converted"); + let response = client + .block(height) + .await + .map_err(|e| eyre!("Query a block failed: {e}"))?; + let memo: Vec = response + .block + .data + .iter() + .flat_map(|tx_bytes| { + let tx = Tx::try_from(&tx_bytes[..]) + .map_err(|e| e.to_string()) + .expect("Decoding tx failed"); + let memo: Vec = tx + .header() + .batch + .iter() + .filter_map(|cmt| { + tx.memo(cmt) + .map(|memo_bytes| String::from_utf8_lossy(&memo_bytes).to_string()) + }) + .collect(); + memo + }) + .collect(); + + // All memo should be the same for now + assert!(memo.iter().all_equal()); + + let memo = memo.first().ok_or_else(|| eyre!("No memo field"))?; + Ok(memo.to_string()) +} + +async fn query_write_ack_packet_height( + client: &HttpClient, + src_port_id: &PortId, + src_channel_id: &ChannelId, + dst_port_id: &PortId, + dst_channel_id: &ChannelId, + sequence: Sequence, +) -> Result { + let event = RPC + .shell() + .ibc_packet( + client, + &IbcEventType::WriteAck + .as_str() + .parse() + .expect("IbcEventType should be parsable"), + &src_port_id + .as_str() + .parse() + .expect("PortId should be parsable"), + &src_channel_id + .as_str() + .parse() + .expect("ChannelId should be parsable"), + &dst_port_id + .as_str() + .parse() + .expect("PortId should be parsable"), + &dst_channel_id + .as_str() + .parse() + .expect("ChannelId should be parsable"), + &u64::from(sequence).into(), + ) + .await + .map_err(|e| eyre!("Namada packet query failed: {e}"))? + .ok_or_else(|| eyre!("No write ack event"))?; + let height = event + .read_attribute::() + .expect("Height should exist"); + + Ok(Height::new(0, height.0).expect("Height conversion shouldn't fail")) +}