diff --git a/.changelog/unreleased/bug-fixes/3645-implicit-addr-balances-toml-fix.md b/.changelog/unreleased/bug-fixes/3645-implicit-addr-balances-toml-fix.md new file mode 100644 index 0000000000..6a7dd9a8d4 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/3645-implicit-addr-balances-toml-fix.md @@ -0,0 +1,3 @@ +- Fix genesis bonds from implicit accounts. Now, only addresses + of the form `tnam1...` are supported in `balances.toml`. + ([\#3645](https://github.com/anoma/namada/pull/3645)) \ No newline at end of file diff --git a/.changelog/unreleased/features/3653-masp-key-birthdays.md b/.changelog/unreleased/features/3653-masp-key-birthdays.md new file mode 100644 index 0000000000..1b85948570 --- /dev/null +++ b/.changelog/unreleased/features/3653-masp-key-birthdays.md @@ -0,0 +1,4 @@ + - Partially addresses Issue [\#2900](https://github.com/anoma/namada/issues/2900). Viewing and spending keys can now + be given birthdays in the form of block heights which are loaded into + shielded sync. Shielded sync will not try to decrypt a block before a + keys birthday with said key. ([\#3653](https://github.com/anoma/namada/pull/3653)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3615-no-parallel-gas.md b/.changelog/unreleased/improvements/3615-no-parallel-gas.md new file mode 100644 index 0000000000..2c4a768129 --- /dev/null +++ b/.changelog/unreleased/improvements/3615-no-parallel-gas.md @@ -0,0 +1,2 @@ +- Removed parallel gas accounting. + ([\#3615](https://github.com/anoma/namada/pull/3615)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3629-improve-init-proposal-validation.md b/.changelog/unreleased/improvements/3629-improve-init-proposal-validation.md new file mode 100644 index 0000000000..6f00cdc2c0 --- /dev/null +++ b/.changelog/unreleased/improvements/3629-improve-init-proposal-validation.md @@ -0,0 +1,2 @@ +- Improve governance client side validation. + ([\#3629](https://github.com/anoma/namada/pull/3629)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3632-check-masp-action.md b/.changelog/unreleased/improvements/3632-check-masp-action.md new file mode 100644 index 0000000000..affa134bf2 --- /dev/null +++ b/.changelog/unreleased/improvements/3632-check-masp-action.md @@ -0,0 +1,2 @@ +- Masp vp and protocol now ensure that a transaction can push at most one MASP + action. ([\#3632](https://github.com/anoma/namada/pull/3632)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3655-speed-up-ctx-build.md b/.changelog/unreleased/improvements/3655-speed-up-ctx-build.md new file mode 100644 index 0000000000..0b9c199567 --- /dev/null +++ b/.changelog/unreleased/improvements/3655-speed-up-ctx-build.md @@ -0,0 +1,5 @@ +- Speeds up client commands on networks with massive balances.toml + files. Previously, to retrieve the native token of some network, + we had to parse these giant files. Now, we only parse the + necessary genesis toml files required to retrieve the native token. + ([\#3655](https://github.com/anoma/namada/pull/3655)) \ No newline at end of file diff --git a/.changelog/unreleased/testing/3535-ibc-client-upgrade-test.md b/.changelog/unreleased/testing/3535-ibc-client-upgrade-test.md new file mode 100644 index 0000000000..a2476e89ef --- /dev/null +++ b/.changelog/unreleased/testing/3535-ibc-client-upgrade-test.md @@ -0,0 +1,2 @@ +- Add IBC client upgrade test + ([\#3535](https://github.com/anoma/namada/issues/3535)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/3553-win-bing-bong.md b/.changelog/v0.42.0/bug-fixes/3553-win-bing-bong.md similarity index 100% rename from .changelog/unreleased/bug-fixes/3553-win-bing-bong.md rename to .changelog/v0.42.0/bug-fixes/3553-win-bing-bong.md diff --git a/.changelog/unreleased/bug-fixes/3566-fix-update-account-client-checks.md b/.changelog/v0.42.0/bug-fixes/3566-fix-update-account-client-checks.md similarity index 100% rename from .changelog/unreleased/bug-fixes/3566-fix-update-account-client-checks.md rename to .changelog/v0.42.0/bug-fixes/3566-fix-update-account-client-checks.md diff --git a/.changelog/v0.42.0/bug-fixes/3576-remove-load-shed.md b/.changelog/v0.42.0/bug-fixes/3576-remove-load-shed.md new file mode 100644 index 0000000000..5d21be5686 --- /dev/null +++ b/.changelog/v0.42.0/bug-fixes/3576-remove-load-shed.md @@ -0,0 +1,2 @@ +- Do not load shed tower-abci info service. + ([\#3576](https://github.com/anoma/namada/pull/3576)) \ No newline at end of file diff --git a/.changelog/v0.42.0/bug-fixes/3594-client-fix.md b/.changelog/v0.42.0/bug-fixes/3594-client-fix.md new file mode 100644 index 0000000000..8e46318c14 --- /dev/null +++ b/.changelog/v0.42.0/bug-fixes/3594-client-fix.md @@ -0,0 +1,3 @@ +- No-op instead of error in wasm for withdraw txs if no tokens are available + to withdraw. Automatically submit reveal pk tx for source for shielding + transfers. ([\#3594](https://github.com/anoma/namada/pull/3594)) \ No newline at end of file diff --git a/.changelog/v0.42.0/bug-fixes/3611-fix-masp-vp-mint-case.md b/.changelog/v0.42.0/bug-fixes/3611-fix-masp-vp-mint-case.md new file mode 100644 index 0000000000..ad32f82062 --- /dev/null +++ b/.changelog/v0.42.0/bug-fixes/3611-fix-masp-vp-mint-case.md @@ -0,0 +1,2 @@ +- Fix the behavior of the MASP VP when processing an IBC Receive message + involves unescrowing. ([\#3611](https://github.com/anoma/namada/pull/3611)) \ No newline at end of file diff --git a/.changelog/v0.42.0/features/3593-ledger-tcp-transport.md b/.changelog/v0.42.0/features/3593-ledger-tcp-transport.md new file mode 100644 index 0000000000..7c2d824a63 --- /dev/null +++ b/.changelog/v0.42.0/features/3593-ledger-tcp-transport.md @@ -0,0 +1,2 @@ +- Added support for Ledger wallet TCP transport. + ([\#3593](https://github.com/anoma/namada/pull/3593)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3402-refactor-out-namada-crate.md b/.changelog/v0.42.0/improvements/3402-refactor-out-namada-crate.md similarity index 100% rename from .changelog/unreleased/improvements/3402-refactor-out-namada-crate.md rename to .changelog/v0.42.0/improvements/3402-refactor-out-namada-crate.md diff --git a/.changelog/unreleased/improvements/3466-di-shielded-token.md b/.changelog/v0.42.0/improvements/3466-di-shielded-token.md similarity index 100% rename from .changelog/unreleased/improvements/3466-di-shielded-token.md rename to .changelog/v0.42.0/improvements/3466-di-shielded-token.md diff --git a/.changelog/unreleased/improvements/3472-systems-crate.md b/.changelog/v0.42.0/improvements/3472-systems-crate.md similarity index 100% rename from .changelog/unreleased/improvements/3472-systems-crate.md rename to .changelog/v0.42.0/improvements/3472-systems-crate.md diff --git a/.changelog/unreleased/improvements/3482-di-gov.md b/.changelog/v0.42.0/improvements/3482-di-gov.md similarity index 100% rename from .changelog/unreleased/improvements/3482-di-gov.md rename to .changelog/v0.42.0/improvements/3482-di-gov.md diff --git a/.changelog/unreleased/improvements/3497-di-pos.md b/.changelog/v0.42.0/improvements/3497-di-pos.md similarity index 100% rename from .changelog/unreleased/improvements/3497-di-pos.md rename to .changelog/v0.42.0/improvements/3497-di-pos.md diff --git a/.changelog/v0.42.0/improvements/3507-decode-asset-types.md b/.changelog/v0.42.0/improvements/3507-decode-asset-types.md new file mode 100644 index 0000000000..a4ff5882fc --- /dev/null +++ b/.changelog/v0.42.0/improvements/3507-decode-asset-types.md @@ -0,0 +1,2 @@ +- Decode asset types to addresses when generating test vectors if possible. + ([\#3507](https://github.com/anoma/namada/pull/3507)) diff --git a/.changelog/unreleased/improvements/3509-di-ibc.md b/.changelog/v0.42.0/improvements/3509-di-ibc.md similarity index 100% rename from .changelog/unreleased/improvements/3509-di-ibc.md rename to .changelog/v0.42.0/improvements/3509-di-ibc.md diff --git a/.changelog/unreleased/improvements/3547-fix-fee-log-msg.md b/.changelog/v0.42.0/improvements/3547-fix-fee-log-msg.md similarity index 100% rename from .changelog/unreleased/improvements/3547-fix-fee-log-msg.md rename to .changelog/v0.42.0/improvements/3547-fix-fee-log-msg.md diff --git a/.changelog/v0.42.0/improvements/3554-rc-gas-update.md b/.changelog/v0.42.0/improvements/3554-rc-gas-update.md new file mode 100644 index 0000000000..93ecd0abc2 --- /dev/null +++ b/.changelog/v0.42.0/improvements/3554-rc-gas-update.md @@ -0,0 +1,2 @@ +- Updated the gas costs based on benchmarks ran on v41. + ([\#3554](https://github.com/anoma/namada/pull/3554)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/3577-relax-bounds.md b/.changelog/v0.42.0/improvements/3577-relax-bounds.md similarity index 100% rename from .changelog/unreleased/improvements/3577-relax-bounds.md rename to .changelog/v0.42.0/improvements/3577-relax-bounds.md diff --git a/.changelog/v0.42.0/improvements/3589-misc-improvements.md b/.changelog/v0.42.0/improvements/3589-misc-improvements.md new file mode 100644 index 0000000000..57bf265fc9 --- /dev/null +++ b/.changelog/v0.42.0/improvements/3589-misc-improvements.md @@ -0,0 +1,2 @@ +- Fxing comments and strings. + ([\#3589](https://github.com/anoma/namada/pull/3589)) \ No newline at end of file diff --git a/.changelog/v0.42.0/improvements/3591-max-block-time-estimate.md b/.changelog/v0.42.0/improvements/3591-max-block-time-estimate.md new file mode 100644 index 0000000000..fed62890a2 --- /dev/null +++ b/.changelog/v0.42.0/improvements/3591-max-block-time-estimate.md @@ -0,0 +1,2 @@ +- Improved the `max_block_time` estimate. + ([\#3591](https://github.com/anoma/namada/pull/3591)) \ No newline at end of file diff --git a/.changelog/v0.42.0/improvements/3592-improve-signers-sdk.md b/.changelog/v0.42.0/improvements/3592-improve-signers-sdk.md new file mode 100644 index 0000000000..c03bf874ff --- /dev/null +++ b/.changelog/v0.42.0/improvements/3592-improve-signers-sdk.md @@ -0,0 +1,2 @@ +- Refactor signature fetching data. + ([\#3592](https://github.com/anoma/namada/pull/3592)) \ No newline at end of file diff --git a/.changelog/v0.42.0/improvements/3598-remove-wasm-loader.md b/.changelog/v0.42.0/improvements/3598-remove-wasm-loader.md new file mode 100644 index 0000000000..62db0b06d8 --- /dev/null +++ b/.changelog/v0.42.0/improvements/3598-remove-wasm-loader.md @@ -0,0 +1,2 @@ +- Do not try to download wasms artifacts from an untrusted source. + ([\#3598](https://github.com/anoma/namada/pull/3598)) \ No newline at end of file diff --git a/.changelog/v0.42.0/improvements/3614-implicit-addr-balances-toml.md b/.changelog/v0.42.0/improvements/3614-implicit-addr-balances-toml.md new file mode 100644 index 0000000000..b09c9a259e --- /dev/null +++ b/.changelog/v0.42.0/improvements/3614-implicit-addr-balances-toml.md @@ -0,0 +1,3 @@ +- Support additional address kinds in `balances.toml` genesis file. + Previously, only established addresses and public keys were supported. + ([\#3614](https://github.com/anoma/namada/pull/3614)) \ No newline at end of file diff --git a/.changelog/v0.42.0/improvements/3617-governance-proposal-client-better-hash.md b/.changelog/v0.42.0/improvements/3617-governance-proposal-client-better-hash.md new file mode 100644 index 0000000000..1f9ced280e --- /dev/null +++ b/.changelog/v0.42.0/improvements/3617-governance-proposal-client-better-hash.md @@ -0,0 +1,2 @@ +- Display the hash of the proposal wasm code when querying proposals with + associated wasm payload. ([\#3617](https://github.com/anoma/namada/pull/3617)) \ No newline at end of file diff --git a/.changelog/v0.42.0/summary.md b/.changelog/v0.42.0/summary.md new file mode 100644 index 0000000000..a471f273ca --- /dev/null +++ b/.changelog/v0.42.0/summary.md @@ -0,0 +1,2 @@ +Namada 0.42.0 is a minor release that includes refactor of crates dependency graph using dependency injection, improvements in client check and node's stability. + diff --git a/.changelog/v0.42.0/testing/3570-hw-e2e.md b/.changelog/v0.42.0/testing/3570-hw-e2e.md new file mode 100644 index 0000000000..fd68d538ca --- /dev/null +++ b/.changelog/v0.42.0/testing/3570-hw-e2e.md @@ -0,0 +1,2 @@ +- Enable E2E tests to be run using hardware wallet. + ([\#3570](https://github.com/anoma/namada/pull/3570)) \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index dd74355249..6a4adba9d3 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,7 +1,5 @@ ## Describe your changes -## Indicate on which release or other PRs this topic is based on - -## Checklist before merging to `draft` -- [ ] I have added a changelog -- [ ] Git history is in acceptable state +## Checklist before merging +- [ ] If this PR has some consensus breaking changes, I added the corresponding `breaking::` labels + - This will require 2 reviewers to approve the changes diff --git a/.github/workflows/scripts/e2e.json b/.github/workflows/scripts/e2e.json index 562949dc87..5011893e3d 100644 --- a/.github/workflows/scripts/e2e.json +++ b/.github/workflows/scripts/e2e.json @@ -6,6 +6,7 @@ "e2e::ibc_tests::proposal_ibc_token_inflation": 1100, "e2e::ibc_tests::ibc_rate_limit": 430, "e2e::ibc_tests::ibc_namada_gaia": 180, + "e2e::ibc_tests::ibc_upgrade_client": 550, "e2e::eth_bridge_tests::test_add_to_bridge_pool": 10, "e2e::ledger_tests::double_signing_gets_slashed": 12, "e2e::ledger_tests::ledger_many_txs_in_a_block": 55, @@ -30,4 +31,4 @@ "e2e::wallet_tests::wallet_encrypted_key_cmds_env_var": 1, "e2e::wallet_tests::wallet_unencrypted_key_cmds": 1, "e2e::ledger_tests::masp_txs_and_queries": 82 -} \ No newline at end of file +} diff --git a/.github/workflows/scripts/hermes.txt b/.github/workflows/scripts/hermes.txt index 27439ea78e..ce746dcc90 100644 --- a/.github/workflows/scripts/hermes.txt +++ b/.github/workflows/scripts/hermes.txt @@ -1 +1 @@ -1.9.0-namada-beta14-rc +1.10.0-namada-beta15-rc2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d8f7be897..c43874483d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,74 @@ # CHANGELOG +## v0.42.0 + +Namada 0.42.0 is a minor release that includes refactor of crates dependency graph using dependency injection, improvements in client check and node's stability. + +### BUG FIXES + +- Workaround Windows problems to be able to build on it. + ([\#3553](https://github.com/anoma/namada/pull/3553)) +- Improve client side checks for update-account transaction. + ([\#3566](https://github.com/anoma/namada/pull/3566)) +- Do not load shed tower-abci info service. + ([\#3576](https://github.com/anoma/namada/pull/3576)) +- No-op instead of error in wasm for withdraw txs if no tokens are available + to withdraw. Automatically submit reveal pk tx for source for shielding + transfers. ([\#3594](https://github.com/anoma/namada/pull/3594)) +- Fix the behavior of the MASP VP when processing an IBC Receive message + involves unescrowing. ([\#3611](https://github.com/anoma/namada/pull/3611)) + +### FEATURES + +- Added support for Ledger wallet TCP transport. + ([\#3593](https://github.com/anoma/namada/pull/3593)) + +### IMPROVEMENTS + +- Added two new crates, namada_vm and namada_vp and removed namada crate that + contained various loosely related code. Moved the native VP implementations + to the relevant crates and replaced their cross-dependencies with dependency- + injection. ([\#3402](https://github.com/anoma/namada/pull/3402)) +- Replaced cross-system dependencies in namada_shielded_token crate with + dependency-injection. ([\#3466](https://github.com/anoma/namada/pull/3466)) +- Added a new namada_systems crate to contain abstract systems interfaces, + previously added to core crate. Also switched to use the concrete + storage error and result type instead of the generic associated + type which reduces the amount of typing needed one the caller side. + ([\#3472](https://github.com/anoma/namada/pull/3472)) +- Replaced cross-system dependencies in namada_governance crate with dependency- + injection. ([\#3482](https://github.com/anoma/namada/pull/3482)) +- Replaced cross-system dependencies in namada_proof_of_stake crate with + dependency-injection. ([\#3497](https://github.com/anoma/namada/pull/3497)) +- Decode asset types to addresses when generating test vectors if possible. + ([\#3507](https://github.com/anoma/namada/pull/3507)) +- Replaced cross-system dependencies in namada_ibc crate with dependency- + injection. ([\#3509](https://github.com/anoma/namada/pull/3509)) +- Improved tracing messages regarding MASP fee payment. + ([\#3547](https://github.com/anoma/namada/pull/3547)) +- Updated the gas costs based on benchmarks ran on v41. + ([\#3554](https://github.com/anoma/namada/pull/3554)) +- Removed unnecessary trait bound from declarations. + ([\#3577](https://github.com/anoma/namada/pull/3577)) +- Fxing comments and strings. + ([\#3589](https://github.com/anoma/namada/pull/3589)) +- Improved the `max_block_time` estimate. + ([\#3591](https://github.com/anoma/namada/pull/3591)) +- Refactor signature fetching data. + ([\#3592](https://github.com/anoma/namada/pull/3592)) +- Do not try to download wasms artifacts from an untrusted source. + ([\#3598](https://github.com/anoma/namada/pull/3598)) +- Support additional address kinds in `balances.toml` genesis file. + Previously, only established addresses and public keys were supported. + ([\#3614](https://github.com/anoma/namada/pull/3614)) +- Display the hash of the proposal wasm code when querying proposals with + associated wasm payload. ([\#3617](https://github.com/anoma/namada/pull/3617)) + +### TESTING + +- Enable E2E tests to be run using hardware wallet. + ([\#3570](https://github.com/anoma/namada/pull/3570)) + ## v0.41.0 Namada 0.41.0 is a minor release that primarily improves gas, fixes bugs related to signature verification and a memory leak from a dependency, and includes shielded sync upgrades. @@ -582,6 +651,9 @@ Namada 0.33.0 is a minor release that contains various new features, improvement - move query_ibc_tokens and lookup_ibc_token_alias to sdk ([\#2729](https://github.com/anoma/namada/issues/2729)) + +### SDK + - Add a new method to the sdk to change a validator consensus key. ([\#3037](https://github.com/anoma/namada/pull/3037)) - Improve the function to update an enstablished address via the sdk. diff --git a/Cargo.lock b/Cargo.lock index 25cfaf00cf..67366f9653 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1975,6 +1975,51 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" +[[package]] +name = "encdec" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25de94e10baa85551f7c65730423239370ed5bed60bf8d2a9cbf2683327ba421" +dependencies = [ + "encdec-base 0.9.0", + "encdec-macros", +] + +[[package]] +name = "encdec-base" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8542ff2a35da7fc94ffcf280f35dc759219c4b48fa930e0a0f268220d7fb6a" +dependencies = [ + "byteorder", + "num-traits 0.2.17", +] + +[[package]] +name = "encdec-base" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516ae3c7d00515548bf26a6531883335ceac2e9cde4938e70feea7456569be09" +dependencies = [ + "byteorder", + "heapless", + "num-traits 0.2.17", + "thiserror", +] + +[[package]] +name = "encdec-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15497932aae6b53bf8548cc63c65929b4fab6be54e28709c80fc72f5707eeed" +dependencies = [ + "darling 0.14.4", + "encdec-base 0.8.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "encoding_rs" version = "0.8.33" @@ -2281,7 +2326,7 @@ dependencies = [ "ethabi", "generic-array", "k256", - "num_enum", + "num_enum 0.7.1", "once_cell", "open-fastrlp", "rand 0.8.5", @@ -3158,7 +3203,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-apps", "ibc-clients", @@ -3171,7 +3216,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", @@ -3181,7 +3226,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "base64 0.22.1", "borsh", @@ -3202,7 +3247,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -3212,7 +3257,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -3230,7 +3275,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", @@ -3239,7 +3284,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -3256,7 +3301,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -3273,7 +3318,7 @@ dependencies = [ [[package]] name = "ibc-client-wasm-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "base64 0.22.1", "displaydoc", @@ -3287,7 +3332,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -3296,7 +3341,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -3312,7 +3357,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -3327,7 +3372,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -3350,7 +3395,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -3363,7 +3408,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -3379,7 +3424,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -3399,11 +3444,12 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", "displaydoc", + "ibc-core-host-types", "ibc-primitives", "ibc-proto", "ics23", @@ -3417,7 +3463,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-client-wasm-types", "ibc-core-client", @@ -3431,7 +3477,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -3452,7 +3498,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -3467,7 +3513,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -3491,7 +3537,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -3509,7 +3555,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -3532,7 +3578,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -3547,7 +3593,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -3561,7 +3607,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -3580,7 +3626,7 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.7.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "proc-macro2", "quote", @@ -3590,7 +3636,7 @@ dependencies = [ [[package]] name = "ibc-primitives" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -3630,7 +3676,7 @@ dependencies = [ [[package]] name = "ibc-query" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "displaydoc", "ibc", @@ -3641,7 +3687,7 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "basecoin-store", "derive_more", @@ -3653,7 +3699,7 @@ dependencies = [ "subtle-encoding", "tendermint 0.37.0", "tendermint-testgen", - "typed-builder 0.18.2", + "typed-builder", ] [[package]] @@ -4047,6 +4093,25 @@ dependencies = [ "snafu", ] +[[package]] +name = "ledger-lib" +version = "0.1.0" +source = "git+https://github.com/heliaxdev/rust-ledger?rev=f96f4559b3237d09218f7583df01acf36034ea79#f96f4559b3237d09218f7583df01acf36034ea79" +dependencies = [ + "async-trait", + "displaydoc", + "encdec", + "futures", + "ledger-proto", + "once_cell", + "strum 0.24.1", + "thiserror", + "tokio", + "tracing", + "tracing-subscriber", + "uuid 1.8.0", +] + [[package]] name = "ledger-namada-rs" version = "0.0.1" @@ -4064,6 +4129,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ledger-proto" +version = "0.1.0" +source = "git+https://github.com/heliaxdev/rust-ledger?rev=f96f4559b3237d09218f7583df01acf36034ea79#f96f4559b3237d09218f7583df01acf36034ea79" +dependencies = [ + "bitflags 2.5.0", + "displaydoc", + "encdec", + "num_enum 0.6.1", + "thiserror", +] + [[package]] name = "ledger-transport" version = "0.10.0" @@ -4476,7 +4553,7 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "namada_account" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "linkme", @@ -4490,7 +4567,7 @@ dependencies = [ [[package]] name = "namada_apps" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "bit-set", @@ -4514,7 +4591,7 @@ dependencies = [ [[package]] name = "namada_apps_lib" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "async-trait", @@ -4537,7 +4614,9 @@ dependencies = [ "itertools 0.12.1", "kdam", "lazy_static", + "ledger-lib", "ledger-namada-rs", + "ledger-transport", "ledger-transport-hid", "linkme", "masp_primitives", @@ -4576,7 +4655,7 @@ dependencies = [ [[package]] name = "namada_benchmarks" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "borsh-ext", @@ -4600,7 +4679,7 @@ dependencies = [ [[package]] name = "namada_controller" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "smooth-operator", @@ -4609,7 +4688,7 @@ dependencies = [ [[package]] name = "namada_core" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "bech32 0.8.1", @@ -4637,7 +4716,7 @@ dependencies = [ "num-rational", "num-traits 0.2.17", "num256", - "num_enum", + "num_enum 0.7.1", "pretty_assertions", "primitive-types", "proptest", @@ -4666,7 +4745,7 @@ dependencies = [ [[package]] name = "namada_encoding_spec" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "itertools 0.12.1", @@ -4680,7 +4759,7 @@ dependencies = [ [[package]] name = "namada_ethereum_bridge" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "borsh", @@ -4720,7 +4799,7 @@ dependencies = [ [[package]] name = "namada_events" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "linkme", @@ -4735,7 +4814,7 @@ dependencies = [ [[package]] name = "namada_examples" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "data-encoding", @@ -4755,7 +4834,7 @@ dependencies = [ [[package]] name = "namada_gas" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "borsh", @@ -4771,7 +4850,7 @@ dependencies = [ [[package]] name = "namada_governance" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "borsh", @@ -4802,7 +4881,7 @@ dependencies = [ [[package]] name = "namada_ibc" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "borsh", @@ -4842,7 +4921,7 @@ dependencies = [ [[package]] name = "namada_light_sdk" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "borsh-ext", @@ -4856,7 +4935,7 @@ dependencies = [ [[package]] name = "namada_macros" -version = "0.41.0" +version = "0.42.0" dependencies = [ "data-encoding", "pretty_assertions", @@ -4868,7 +4947,7 @@ dependencies = [ [[package]] name = "namada_merkle_tree" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "borsh", @@ -4887,7 +4966,7 @@ dependencies = [ [[package]] name = "namada_migrations" -version = "0.41.0" +version = "0.42.0" dependencies = [ "lazy_static", "linkme", @@ -4896,7 +4975,7 @@ dependencies = [ [[package]] name = "namada_node" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "async-trait", @@ -4962,7 +5041,7 @@ dependencies = [ [[package]] name = "namada_parameters" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_macros", @@ -4977,7 +5056,7 @@ dependencies = [ [[package]] name = "namada_proof_of_stake" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "borsh", @@ -5014,14 +5093,14 @@ dependencies = [ [[package]] name = "namada_replay_protection" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", ] [[package]] name = "namada_sdk" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "async-trait", @@ -5094,14 +5173,14 @@ dependencies = [ "tokio", "toml 0.5.11", "tracing", - "typed-builder 0.19.1", + "typed-builder", "xorf", "zeroize", ] [[package]] name = "namada_shielded_token" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "lazy_static", @@ -5132,7 +5211,7 @@ dependencies = [ [[package]] name = "namada_state" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "borsh", @@ -5162,7 +5241,7 @@ dependencies = [ [[package]] name = "namada_storage" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "itertools 0.12.1", @@ -5181,7 +5260,7 @@ dependencies = [ [[package]] name = "namada_systems" -version = "0.41.0" +version = "0.42.0" dependencies = [ "cargo_metadata", "lazy_static", @@ -5191,16 +5270,18 @@ dependencies = [ [[package]] name = "namada_test_utils" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", + "namada_state", + "prost 0.12.3", "strum 0.24.1", ] [[package]] name = "namada_tests" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_cmd", "assert_matches", @@ -5251,7 +5332,7 @@ dependencies = [ [[package]] name = "namada_token" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -5267,7 +5348,7 @@ dependencies = [ [[package]] name = "namada_trans_token" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "konst", @@ -5290,7 +5371,7 @@ dependencies = [ [[package]] name = "namada_tx" -version = "0.41.0" +version = "0.42.0" dependencies = [ "ark-bls12-381", "assert_matches", @@ -5322,7 +5403,7 @@ dependencies = [ [[package]] name = "namada_tx_env" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_events", @@ -5331,7 +5412,7 @@ dependencies = [ [[package]] name = "namada_tx_prelude" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "masp_primitives", @@ -5353,7 +5434,7 @@ dependencies = [ [[package]] name = "namada_vm" -version = "0.41.0" +version = "0.42.0" dependencies = [ "assert_matches", "borsh", @@ -5388,7 +5469,7 @@ dependencies = [ [[package]] name = "namada_vm_env" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "masp_primitives", @@ -5397,7 +5478,7 @@ dependencies = [ [[package]] name = "namada_vote_ext" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "data-encoding", @@ -5411,7 +5492,7 @@ dependencies = [ [[package]] name = "namada_vp" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_events", @@ -5426,7 +5507,7 @@ dependencies = [ [[package]] name = "namada_vp_env" -version = "0.41.0" +version = "0.42.0" dependencies = [ "derivative", "masp_primitives", @@ -5439,7 +5520,7 @@ dependencies = [ [[package]] name = "namada_vp_prelude" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_account", @@ -5670,13 +5751,33 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", +] + [[package]] name = "num_enum" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.7.1", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", ] [[package]] @@ -8605,6 +8706,7 @@ dependencies = [ "serde", "serde_json", "sharded-slab", + "smallvec", "thread_local", "tracing", "tracing-core", @@ -8637,33 +8739,13 @@ dependencies = [ "utf-8", ] -[[package]] -name = "typed-builder" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" -dependencies = [ - "typed-builder-macro 0.18.2", -] - [[package]] name = "typed-builder" version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06fbd5b8de54c5f7c91f6fe4cebb949be2125d7758e630bb58b1d831dbce600" dependencies = [ - "typed-builder-macro 0.19.1", -] - -[[package]] -name = "typed-builder-macro" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", + "typed-builder-macro", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0e5c3d445e..2e3f8a0cd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,7 @@ keywords = ["blockchain", "privacy", "crypto", "protocol", "network"] license = "GPL-3.0" readme = "README.md" repository = "https://github.com/anoma/namada" -version = "0.41.0" +version = "0.42.0" [workspace.dependencies] ark-bls12-381 = {version = "0.3"} @@ -113,9 +113,9 @@ flume = "0.11.0" fs_extra = "1.2.0" futures = "0.3" git2 = { version = "0.18.1", default-features = false } -ibc = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d", features = ["serde"] } -ibc-derive = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" } -ibc-testkit = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d", default-features = false } +ibc = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b", features = ["serde"] } +ibc-derive = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" } +ibc-testkit = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b", default-features = false } ics23 = "0.11.0" index-set = { git = "https://github.com/heliaxdev/index-set", tag = "v0.8.1", features = ["serialize-borsh", "serialize-serde"] } indexmap = { git = "https://github.com/heliaxdev/indexmap", tag = "2.2.4-heliax-1", features = ["borsh-schema", "serde"] } @@ -126,7 +126,10 @@ k256 = { version = "0.13.0", default-features = false, features = ["ecdsa", "pkc kdam = "0.5.2" konst = { version = "0.3.8", default-features = false } lazy_static = "1.4.0" +# TODO: upstreamed in https://github.com/ledger-community/rust-ledger/pull/9 +ledger-lib = { git = "https://github.com/heliaxdev/rust-ledger", rev = "f96f4559b3237d09218f7583df01acf36034ea79", default-features = false, features = ["transport_tcp"] } ledger-namada-rs = { git = "https://github.com/Zondax/ledger-namada", tag = "v0.0.24" } +ledger-transport = "0.10.0" ledger-transport-hid = "0.10.0" libc = "0.2.97" libloading = "0.7.2" diff --git a/codecov.yml b/codecov.yml index d2e1fea9db..d17d314298 100644 --- a/codecov.yml +++ b/codecov.yml @@ -35,5 +35,6 @@ ignore: - crates/test_utils - crates/benches - crates/apps/src/bin - - crates/apps/src/lib/cli - - crates/apps/src/lib/client \ No newline at end of file + - crates/apps_lib/src/cli + - crates/apps_lib/src/client + - crates/apps_lib/src/wasm_loader \ No newline at end of file diff --git a/crates/apps_lib/Cargo.toml b/crates/apps_lib/Cargo.toml index a20040a195..fef6adbd53 100644 --- a/crates/apps_lib/Cargo.toml +++ b/crates/apps_lib/Cargo.toml @@ -57,7 +57,9 @@ itertools.workspace = true kdam.workspace = true lazy_static = { workspace = true, optional = true } linkme = { workspace = true, optional = true } +ledger-lib = { workspace = true } ledger-namada-rs.workspace = true +ledger-transport.workspace = true ledger-transport-hid.workspace = true masp_primitives = { workspace = true, features = ["transparent-inputs"] } prost.workspace = true diff --git a/crates/apps_lib/src/cli.rs b/crates/apps_lib/src/cli.rs index 9f934b855d..56d1b5df09 100644 --- a/crates/apps_lib/src/cli.rs +++ b/crates/apps_lib/src/cli.rs @@ -2281,7 +2281,7 @@ pub mod cmds { fn def() -> App { App::new(Self::CMD) .about(wrap!( - "Submit a tx to reveal the public key an implicit \ + "Submit a tx to reveal the public key of an implicit \ account. Typically, you don't have to do this manually \ and the client will detect when a tx to reveal PK is \ needed and submit it automatically. This will write the \ @@ -3188,7 +3188,7 @@ pub mod args { use super::utils::*; use super::{ArgGroup, ArgMatches}; use crate::client::utils::PRE_GENESIS_DIR; - use crate::config::genesis::GenesisAddress; + use crate::config::genesis::AddrOrPk; use crate::config::{self, Action, ActionAtHeight}; use crate::facade::tendermint::Timeout; use crate::facade::tendermint_rpc::Url; @@ -3212,6 +3212,7 @@ pub mod args { Err(_) => config::get_default_namada_folder(), }), ); + pub const BIRTHDAY: ArgOpt = arg_opt("birthday"); pub const BLOCK_HEIGHT: Arg = arg("block-height"); pub const BLOCK_HEIGHT_OPT: ArgOpt = arg_opt("height"); pub const BLOCK_HEIGHT_TO_OPT: ArgOpt = arg_opt("to-height"); @@ -3254,6 +3255,10 @@ pub mod args { arg_opt("success-sleep"); pub const DATA_PATH_OPT: ArgOpt = arg_opt("data-path"); pub const DATA_PATH: Arg = arg("data-path"); + pub const DATED_SPENDING_KEYS: ArgMulti = + arg_multi("spending-keys"); + pub const DATED_VIEWING_KEYS: ArgMulti = + arg_multi("viewing-keys"); pub const DB_KEY: Arg = arg("db-key"); pub const DB_COLUMN_FAMILY: ArgDefault = arg_default( "db-column-family", @@ -3266,7 +3271,6 @@ pub mod args { arg("destination-validator"); pub const DISCORD_OPT: ArgOpt = arg_opt("discord-handle"); pub const DO_IT: ArgFlag = flag("do-it"); - pub const DONT_PREFETCH_WASM: ArgFlag = flag("dont-prefetch-wasm"); pub const DRY_RUN_TX: ArgFlag = flag("dry-run"); pub const DRY_RUN_WRAPPER_TX: ArgFlag = flag("dry-run-wrapper"); pub const DUMP_TX: ArgFlag = flag("dump-tx"); @@ -3308,7 +3312,7 @@ pub mod args { ) }), ); - pub const GENESIS_BOND_SOURCE: ArgOpt = arg_opt("source"); + pub const GENESIS_BOND_SOURCE: ArgOpt = arg_opt("source"); pub const GENESIS_PATH: Arg = arg("genesis-path"); pub const GENESIS_TIME: Arg = arg("genesis-time"); pub const GENESIS_VALIDATOR: ArgOpt = @@ -3472,6 +3476,16 @@ pub mod args { pub const WITH_INDEXER: ArgOpt = arg_opt("with-indexer"); pub const TX_PATH: Arg = arg("tx-path"); pub const TX_PATH_OPT: ArgOpt = TX_PATH.opt(); + pub const DEVICE_TRANSPORT: ArgDefault = arg_default( + "device-transport", + DefaultFn(|| { + if let Ok(val) = std::env::var(DEVICE_TRANSPORT_ENV_VAR) { + return DeviceTransport::from_str(&val).unwrap(); + } + DeviceTransport::default() + }), + ); + pub const DEVICE_TRANSPORT_ENV_VAR: &str = "NAMADA_DEVICE_TRANSPORT"; /// Global command arguments #[derive(Clone, Debug)] @@ -6577,8 +6591,8 @@ pub mod args { fn parse(matches: &ArgMatches) -> Self { let ledger_address = CONFIG_RPC_LEDGER_ADDRESS.parse(matches); let last_query_height = BLOCK_HEIGHT_TO_OPT.parse(matches); - let spending_keys = SPENDING_KEYS.parse(matches); - let viewing_keys = VIEWING_KEYS.parse(matches); + let spending_keys = DATED_SPENDING_KEYS.parse(matches); + let viewing_keys = DATED_VIEWING_KEYS.parse(matches); let with_indexer = WITH_INDEXER.parse(matches); let wait_for_last_query_height = WAIT_FOR_LAST_QUERY_HEIGHT.parse(matches); @@ -6604,13 +6618,17 @@ pub mod args { .arg(BLOCK_HEIGHT_TO_OPT.def().help(wrap!( "Option block height to sync up to. Default is latest." ))) - .arg(SPENDING_KEYS.def().help(wrap!( + .arg(DATED_SPENDING_KEYS.def().help(wrap!( "List of new spending keys with which to check note \ - ownership. These will be added to the shielded context." + ownership. These will be added to the shielded context. \ + Appending \"<<$BLOCKHEIGHT\" to the end of each key adds \ + a birthday." ))) - .arg(VIEWING_KEYS.def().help(wrap!( + .arg(DATED_VIEWING_KEYS.def().help(wrap!( "List of new viewing keys with which to check note \ - ownership. These will be added to the shielded context." + ownership. These will be added to the shielded context. \ + Appending \"<<$BLOCKHEIGHT\" to the end of each key adds \ + a birthday." ))) .arg(WITH_INDEXER.def().help(wrap!( "Address of a `namada-masp-indexer` live instance. If \ @@ -6979,6 +6997,8 @@ pub mod args { type BpConversionTable = PathBuf; type ConfigRpcTendermintAddress = ConfigRpcAddress; type Data = PathBuf; + type DatedSpendingKey = WalletDatedSpendingKey; + type DatedViewingKey = WalletDatedViewingKey; type EthereumAddress = String; type Keypair = WalletKeypair; type MaspIndexerAddress = String; @@ -7040,6 +7060,7 @@ pub mod args { wrapper_fee_payer: self.wrapper_fee_payer.map(|x| ctx.get(&x)), memo: self.memo, use_device: self.use_device, + device_transport: self.device_transport, }) } } @@ -7050,7 +7071,8 @@ pub mod args { DRY_RUN_TX .def() .help(wrap!("Simulate the transaction application.")) - .conflicts_with(DRY_RUN_WRAPPER_TX.name), + .conflicts_with(DRY_RUN_WRAPPER_TX.name) + .conflicts_with(USE_DEVICE.name), ) .arg( DRY_RUN_WRAPPER_TX @@ -7160,10 +7182,24 @@ pub mod args { )) .conflicts_with(DISPOSABLE_SIGNING_KEY.name), ) - .arg(USE_DEVICE.def().help(wrap!( - "Use an attached hardware wallet device to sign the \ - transaction." - ))) + .arg( + USE_DEVICE + .def() + .help(wrap!( + "Use an attached hardware wallet device to sign the \ + transaction." + )) + .conflicts_with(DRY_RUN_TX.name), + ) + .arg( + DEVICE_TRANSPORT + .def() + .help(wrap!( + "Select transport for hardware wallet from \"hid\" \ + (default) or \"tcp\"." + )) + .conflicts_with(DRY_RUN_TX.name), + ) .arg( MEMO_OPT .def() @@ -7205,6 +7241,7 @@ pub mod args { None => TxExpiration::Default, } }; + let device_transport = DEVICE_TRANSPORT.parse(matches); Self { dry_run, dry_run_wrapper, @@ -7228,6 +7265,7 @@ pub mod args { output_folder, memo, use_device, + device_transport, } } } @@ -7317,7 +7355,8 @@ pub mod args { find_viewing_key(&mut wallet) } else { find_viewing_key(&mut ctx.borrow_mut_chain_or_exit().wallet) - }; + } + .key; Ok(PayAddressGen:: { alias: self.alias, @@ -7356,23 +7395,27 @@ pub mod args { let shielded = SHIELDED.parse(matches); let alias = ALIAS.parse(matches); let alias_force = ALIAS_FORCE.parse(matches); + let birthday = BIRTHDAY.parse(matches); let unsafe_dont_encrypt = UNSAFE_DONT_ENCRYPT.parse(matches); - let use_device = USE_DEVICE.parse(matches); let derivation_path = HD_DERIVATION_PATH.parse(matches); let allow_non_compliant = HD_ALLOW_NON_COMPLIANT_DERIVATION_PATH.parse(matches); let prompt_bip39_passphrase = HD_PROMPT_BIP39_PASSPHRASE.parse(matches); + let use_device = USE_DEVICE.parse(matches); + let device_transport = DEVICE_TRANSPORT.parse(matches); Self { scheme, shielded, alias, alias_force, unsafe_dont_encrypt, - use_device, derivation_path, allow_non_compliant, prompt_bip39_passphrase, + use_device, + device_transport, + birthday, } } @@ -7394,6 +7437,11 @@ pub mod args { "Force overwrite the alias if it already exists." )), ) + .arg(BIRTHDAY.def().help(wrap!( + "A block height after which this key is being created. Used \ + for optimizing MASP operations. If none is provided, \ + defaults to the first block height." + ))) .arg(UNSAFE_DONT_ENCRYPT.def().help(wrap!( "UNSAFE: Do not encrypt the keypair. Do not use this for keys \ used in a live network." @@ -7402,6 +7450,10 @@ pub mod args { "Derive an address and public key from the seed stored on the \ connected hardware wallet." ))) + .arg(DEVICE_TRANSPORT.def().help(wrap!( + "Select transport for hardware wallet from \"hid\" (default) \ + or \"tcp\"." + ))) .arg(HD_DERIVATION_PATH.def().help(wrap!( "HD key derivation path. Use keyword `default` to refer to a \ scheme default path:\n- m/44'/60'/0'/0/0 for the transparent \ @@ -7438,6 +7490,7 @@ pub mod args { let raw = RAW_KEY_GEN.parse(matches); let alias = ALIAS.parse(matches); let alias_force = ALIAS_FORCE.parse(matches); + let birthday = BIRTHDAY.parse(matches); let unsafe_dont_encrypt = UNSAFE_DONT_ENCRYPT.parse(matches); let derivation_path = HD_DERIVATION_PATH.parse(matches); let allow_non_compliant = @@ -7450,6 +7503,7 @@ pub mod args { raw, alias, alias_force, + birthday, unsafe_dont_encrypt, derivation_path, allow_non_compliant, @@ -7482,6 +7536,11 @@ pub mod args { .arg(ALIAS_FORCE.def().help(wrap!( "Override the alias without confirmation if it already exists." ))) + .arg(BIRTHDAY.def().help(wrap!( + "A block height after which this key is being created. Used \ + for optimizing MASP operations. If none is provided, \ + defaults to the first block height." + ))) .arg(UNSAFE_DONT_ENCRYPT.def().help(wrap!( "UNSAFE: Do not encrypt the keypair. Do not use this for keys \ used in a live network." @@ -7653,11 +7712,13 @@ pub mod args { fn parse(matches: &ArgMatches) -> Self { let alias = ALIAS.parse(matches); let alias_force = ALIAS_FORCE.parse(matches); + let birthday = BIRTHDAY.parse(matches); let value = VALUE.parse(matches); let unsafe_dont_encrypt = UNSAFE_DONT_ENCRYPT.parse(matches); Self { alias, alias_force, + birthday, value, unsafe_dont_encrypt, } @@ -7672,6 +7733,11 @@ pub mod args { .arg(ALIAS_FORCE.def().help(wrap!( "Override the alias without confirmation if it already exists." ))) + .arg(BIRTHDAY.def().help(wrap!( + "A block height after which this key is being created. Used \ + for optimizing MASP operations. If none is provided, \ + defaults to the first block height." + ))) .arg(VALUE.def().help(wrap!( "Any value of the following:\n- transparent pool secret \ key\n- transparent pool public key\n- transparent pool \ @@ -7767,7 +7833,6 @@ pub mod args { pub chain_id: ChainId, pub genesis_validator: Option, pub pre_genesis_path: Option, - pub dont_prefetch_wasm: bool, pub allow_duplicate_ip: bool, pub add_persistent_peers: bool, } @@ -7777,14 +7842,12 @@ pub mod args { let chain_id = CHAIN_ID.parse(matches); let genesis_validator = GENESIS_VALIDATOR.parse(matches); let pre_genesis_path = PRE_GENESIS_PATH.parse(matches); - let dont_prefetch_wasm = DONT_PREFETCH_WASM.parse(matches); let allow_duplicate_ip = ALLOW_DUPLICATE_IP.parse(matches); let add_persistent_peers = ADD_PERSISTENT_PEERS.parse(matches); Self { chain_id, genesis_validator, pre_genesis_path, - dont_prefetch_wasm, allow_duplicate_ip, add_persistent_peers, } @@ -7795,9 +7858,6 @@ pub mod args { https://github.com/heliaxdev/anoma-network-config"))) .arg(GENESIS_VALIDATOR.def().help(wrap!("The alias of the genesis validator that you want to set up as, if any."))) .arg(PRE_GENESIS_PATH.def().help(wrap!("The path to the pre-genesis directory for genesis validator, if any. Defaults to \"{base-dir}/pre-genesis/{genesis-validator}\"."))) - .arg(DONT_PREFETCH_WASM.def().help(wrap!( - "Do not pre-fetch WASM.") - )) .arg(ALLOW_DUPLICATE_IP.def().help(wrap!( "Toggle to disable guard against peers connecting from the \ same IP. This option shouldn't be used in mainnet.") @@ -7982,7 +8042,7 @@ pub mod args { #[derive(Clone, Debug)] pub struct GenesisBond { - pub source: GenesisAddress, + pub source: AddrOrPk, pub validator: EstablishedAddress, pub bond_amount: token::DenominatedAmount, pub output: PathBuf, @@ -7993,7 +8053,7 @@ pub mod args { let validator = GENESIS_VALIDATOR_ADDRESS.parse(matches); let source = GENESIS_BOND_SOURCE.parse(matches).unwrap_or_else(|| { - GenesisAddress::EstablishedAddress(validator.clone()) + AddrOrPk::Address(Address::Established(validator.clone())) }); let bond_amount = AMOUNT.parse(matches); let output = PATH.parse(matches); @@ -8198,6 +8258,7 @@ pub mod args { pub output: Option, pub validator_alias: Option, pub use_device: bool, + pub device_transport: DeviceTransport, } impl Args for SignGenesisTxs { @@ -8206,11 +8267,13 @@ pub mod args { let output = OUTPUT.parse(matches); let validator_alias = ALIAS_OPT.parse(matches); let use_device = USE_DEVICE.parse(matches); + let device_transport = DEVICE_TRANSPORT.parse(matches); Self { path, output, validator_alias, use_device, + device_transport, } } @@ -8233,6 +8296,10 @@ pub mod args { "Derive an address and public key from the seed stored on the \ connected hardware wallet." ))) + .arg(DEVICE_TRANSPORT.def().help(wrap!( + "Select transport for hardware wallet from \"hid\" (default) \ + or \"tcp\"." + ))) } } diff --git a/crates/apps_lib/src/cli/client.rs b/crates/apps_lib/src/cli/client.rs index 51623f5a87..581f53b392 100644 --- a/crates/apps_lib/src/cli/client.rs +++ b/crates/apps_lib/src/cli/client.rs @@ -773,7 +773,7 @@ impl CliApi { utils::init_network(global_args, args); } ClientUtils::GenesisBond(GenesisBond(args)) => { - utils::genesis_bond(args) + utils::genesis_bond(global_args, args) } ClientUtils::DeriveGenesisAddresses( DeriveGenesisAddresses(args), diff --git a/crates/apps_lib/src/cli/context.rs b/crates/apps_lib/src/cli/context.rs index aa0e6c6141..aa6c05bf2a 100644 --- a/crates/apps_lib/src/cli/context.rs +++ b/crates/apps_lib/src/cli/context.rs @@ -14,7 +14,7 @@ use namada_sdk::io::Io; use namada_sdk::key::*; use namada_sdk::masp::fs::FsShieldedUtils; use namada_sdk::masp::{ShieldedContext, *}; -use namada_sdk::wallet::Wallet; +use namada_sdk::wallet::{DatedSpendingKey, DatedViewingKey, Wallet}; use namada_sdk::{Namada, NamadaImpl}; use super::args; @@ -45,6 +45,10 @@ pub type WalletAddrOrNativeToken = FromContext; /// spending key in the wallet pub type WalletSpendingKey = FromContext; +/// A raw dated extended spending key (bech32m encoding) or an alias of an +/// extended spending key in the wallet +pub type WalletDatedSpendingKey = FromContext; + /// A raw payment address (bech32m encoding) or an alias of a payment address /// in the wallet pub type WalletPaymentAddr = FromContext; @@ -53,6 +57,10 @@ pub type WalletPaymentAddr = FromContext; /// in the wallet pub type WalletViewingKey = FromContext; +/// A raw full dated viewing key (bech32m encoding) or an alias of a full +/// viewing key in the wallet +pub type WalletDatedViewingKey = FromContext; + /// A raw address or a raw extended spending key (bech32m encoding) or an alias /// of either in the wallet pub type WalletTransferSource = FromContext; @@ -162,10 +170,9 @@ impl Context { let mut config = Config::load(&global_args.base_dir, chain_id, None); let chain_dir = global_args.base_dir.join(chain_id.as_str()); - let genesis = - genesis::chain::Finalized::read_toml_files(&chain_dir) + let native_token = + genesis::chain::Finalized::read_native_token(&chain_dir) .expect("Missing genesis files"); - let native_token = genesis.get_native_token().clone(); let wallet = if wallet::exists(&chain_dir) { wallet::load(&chain_dir).unwrap() } else { @@ -561,6 +568,23 @@ impl ArgFromContext for common::PublicKey { } impl ArgFromMutContext for ExtendedSpendingKey { + fn arg_from_mut_ctx( + ctx: &mut ChainContext, + raw: impl AsRef, + ) -> Result { + let raw = raw.as_ref(); + // Either the string is a raw extended spending key + FromStr::from_str(raw).or_else(|_parse_err| { + // Or it is a stored alias of one + ctx.wallet + .find_spending_key(raw, None) + .map(|k| k.key) + .map_err(|_find_err| format!("Unknown spending key {}", raw)) + }) + } +} + +impl ArgFromMutContext for DatedSpendingKey { fn arg_from_mut_ctx( ctx: &mut ChainContext, raw: impl AsRef, @@ -577,6 +601,24 @@ impl ArgFromMutContext for ExtendedSpendingKey { } impl ArgFromMutContext for ExtendedViewingKey { + fn arg_from_mut_ctx( + ctx: &mut ChainContext, + raw: impl AsRef, + ) -> Result { + let raw = raw.as_ref(); + // Either the string is a raw full viewing key + FromStr::from_str(raw).or_else(|_parse_err| { + // Or it is a stored alias of one + ctx.wallet + .find_viewing_key(raw) + .copied() + .map(|k| k.key) + .map_err(|_find_err| format!("Unknown viewing key {}", raw)) + }) + } +} + +impl ArgFromMutContext for DatedViewingKey { fn arg_from_mut_ctx( ctx: &mut ChainContext, raw: impl AsRef, diff --git a/crates/apps_lib/src/cli/wallet.rs b/crates/apps_lib/src/cli/wallet.rs index 546b3a8dac..ebdce5d35c 100644 --- a/crates/apps_lib/src/cli/wallet.rs +++ b/crates/apps_lib/src/cli/wallet.rs @@ -9,9 +9,7 @@ use borsh_ext::BorshSerializeExt; use color_eyre::eyre::Result; use itertools::sorted; use ledger_namada_rs::{BIP44Path, NamadaApp}; -use ledger_transport_hid::hidapi::HidApi; -use ledger_transport_hid::TransportNativeHID; -use masp_primitives::zip32::ExtendedFullViewingKey; +use namada_core::storage::BlockHeight; use namada_sdk::address::{Address, DecodeError}; use namada_sdk::io::Io; use namada_sdk::key::*; @@ -31,7 +29,7 @@ use crate::cli::{args, cmds, Context}; use crate::client::utils::PRE_GENESIS_DIR; use crate::tendermint_node::validator_key_to_json; use crate::wallet::{ - self, read_and_confirm_encryption_password, CliWalletUtils, + self, read_and_confirm_encryption_password, CliWalletUtils, WalletTransport, }; impl CliApi { @@ -195,6 +193,7 @@ fn shielded_key_derive( allow_non_compliant, prompt_bip39_passphrase, use_device, + birthday, .. }: args::KeyDerive, ) { @@ -218,6 +217,7 @@ fn shielded_key_derive( .derive_store_spending_key_from_mnemonic_code( alias, alias_force, + birthday, derivation_path, None, prompt_bip39_passphrase, @@ -256,6 +256,7 @@ fn shielded_key_gen( derivation_path, allow_non_compliant, prompt_bip39_passphrase, + birthday, .. }: args::KeyGen, ) { @@ -263,7 +264,13 @@ fn shielded_key_gen( let alias = alias.to_lowercase(); let password = read_and_confirm_encryption_password(unsafe_dont_encrypt); let alias = if raw { - wallet.gen_store_spending_key(alias, password, alias_force, &mut OsRng) + wallet.gen_store_spending_key( + alias, + birthday, + password, + alias_force, + &mut OsRng, + ) } else { let derivation_path = decode_shielded_derivation_path(derivation_path) .unwrap_or_else(|err| { @@ -283,9 +290,10 @@ fn shielded_key_gen( &mut OsRng, prompt_bip39_passphrase, ); - wallet.derive_store_hd_spendind_key( + wallet.derive_store_hd_spending_key( alias, alias_force, + birthday, seed, derivation_path, password, @@ -321,7 +329,7 @@ fn payment_address_gen( ) { let mut wallet = load_wallet(ctx); let alias = alias.to_lowercase(); - let viewing_key = ExtendedFullViewingKey::from(viewing_key).fvk.vk; + let viewing_key = viewing_key.as_viewing_key(); let (div, _g_d) = find_valid_diversifier(&mut OsRng); let masp_payment_addr = viewing_key .to_payment_address(div) @@ -348,6 +356,7 @@ fn shielded_key_address_add( io: &impl Io, alias: String, alias_force: bool, + birthday: Option, masp_value: MaspValue, unsafe_dont_encrypt: bool, ) { @@ -356,7 +365,7 @@ fn shielded_key_address_add( let (alias, typ) = match masp_value { MaspValue::FullViewingKey(viewing_key) => { let alias = wallet - .insert_viewing_key(alias, viewing_key, alias_force) + .insert_viewing_key(alias, viewing_key, birthday, alias_force) .unwrap_or_else(|| { edisplay_line!(io, "Viewing key not added"); cli::safe_exit(1); @@ -371,6 +380,7 @@ fn shielded_key_address_add( alias, alias_force, spending_key, + birthday, password, None, ) @@ -446,6 +456,7 @@ async fn transparent_key_and_address_derive( allow_non_compliant, prompt_bip39_passphrase, use_device, + device_transport, .. }: args::KeyDerive, ) { @@ -485,16 +496,8 @@ async fn transparent_key_and_address_derive( }) .0 } else { - let hidapi = HidApi::new().unwrap_or_else(|err| { - edisplay_line!(io, "Failed to create HidApi: {}", err); - cli::safe_exit(1) - }); - let app = NamadaApp::new( - TransportNativeHID::new(&hidapi).unwrap_or_else(|err| { - edisplay_line!(io, "Unable to connect to Ledger: {}", err); - cli::safe_exit(1) - }), - ); + let transport = WalletTransport::from_arg(device_transport); + let app = NamadaApp::new(transport); let response = app .get_address_and_pubkey( &BIP44Path { @@ -797,6 +800,7 @@ fn add_key_or_address( io: &impl Io, alias: String, alias_force: bool, + birthday: Option, value: KeyAddrAddValue, unsafe_dont_encrypt: bool, ) { @@ -822,6 +826,7 @@ fn add_key_or_address( io, alias, alias_force, + birthday, masp_value, unsafe_dont_encrypt, ), @@ -836,8 +841,8 @@ fn key_address_add( alias, alias_force, value, + birthday, unsafe_dont_encrypt, - .. }: args::KeyAddressAdd, ) { let value = KeyAddrAddValue::from_str(&value).unwrap_or_else(|err| { @@ -845,7 +850,15 @@ fn key_address_add( display_line!(io, "No changes are persisted. Exiting."); cli::safe_exit(1) }); - add_key_or_address(ctx, io, alias, alias_force, value, unsafe_dont_encrypt) + add_key_or_address( + ctx, + io, + alias, + alias_force, + birthday, + value, + unsafe_dont_encrypt, + ) } /// Remove keys and addresses @@ -1302,6 +1315,7 @@ fn key_import( io, alias, alias_force, + None, masp_value, unsafe_dont_encrypt, ); diff --git a/crates/apps_lib/src/client/masp.rs b/crates/apps_lib/src/client/masp.rs index 4a36488c77..3a6abd32bd 100644 --- a/crates/apps_lib/src/client/masp.rs +++ b/crates/apps_lib/src/client/masp.rs @@ -1,7 +1,6 @@ use std::time::Duration; use color_eyre::owo_colors::OwoColorize; -use masp_primitives::zip32::ExtendedFullViewingKey; use namada_sdk::args::ShieldedSync; use namada_sdk::control_flow::install_shutdown_signal; use namada_sdk::error::Error; @@ -71,16 +70,12 @@ pub async fn syncing< } }; - let sks = args - .spending_keys - .into_iter() - .map(|sk| sk.into()) - .collect::>(); - let fvks = args + let vks = args .viewing_keys .into_iter() - .map(|vk| ExtendedFullViewingKey::from(vk).fvk.vk) + .map(|vk| vk.map(|vk| vk.as_viewing_key())) .collect::>(); + macro_rules! dispatch_client { ($client:expr) => {{ let config = ShieldedSyncConfig::builder() @@ -95,7 +90,13 @@ pub async fn syncing< let env = MaspLocalTaskEnv::new(500)?; let ctx = shielded - .sync(env, config, args.last_query_height, &sks, &fvks) + .sync( + env, + config, + args.last_query_height, + &args.spending_keys, + &vks, + ) .await .map(|_| shielded); diff --git a/crates/apps_lib/src/client/rpc.rs b/crates/apps_lib/src/client/rpc.rs index 9db5fde5e1..160fdff26e 100644 --- a/crates/apps_lib/src/client/rpc.rs +++ b/crates/apps_lib/src/client/rpc.rs @@ -435,16 +435,15 @@ async fn query_shielded_balance( } } -pub async fn query_proposal_result( - context: &impl Namada, +pub async fn query_proposal_result( + context: &N, args: args::QueryProposalResult, ) { let proposal_id = args.proposal_id; let current_epoch = query_epoch(context.client()).await.unwrap(); let proposal_result = - namada_sdk::rpc::query_proposal_result(context.client(), proposal_id) - .await; + namada_sdk::rpc::query_proposal_result(context, proposal_id).await; let proposal_query = namada_sdk::rpc::query_proposal_by_id(context.client(), proposal_id) .await; @@ -669,7 +668,7 @@ pub async fn query_protocol_parameters( display_line!(context.io(), "{:8}{}: {:?}", "", token, gas_cost); } - display_line!(context.io(), "PoS parameters"); + display_line!(context.io(), "\nPoS parameters"); let pos_params = query_pos_parameters(context.client()).await; display_line!( context.io(), @@ -697,9 +696,9 @@ pub async fn query_protocol_parameters( ); display_line!( context.io(), - "{:4}Validator stake threshold: {}", + "{:4}Validator stake threshold: {} NAM", "", - pos_params.validator_stake_threshold + pos_params.validator_stake_threshold.to_string_native() ); display_line!( context.io(), diff --git a/crates/apps_lib/src/client/tx.rs b/crates/apps_lib/src/client/tx.rs index 835ff33c93..c640aec100 100644 --- a/crates/apps_lib/src/client/tx.rs +++ b/crates/apps_lib/src/client/tx.rs @@ -4,8 +4,6 @@ use std::io::Write; use borsh::BorshDeserialize; use borsh_ext::BorshSerializeExt; use ledger_namada_rs::{BIP44Path, NamadaApp}; -use ledger_transport_hid::hidapi::HidApi; -use ledger_transport_hid::TransportNativeHID; use namada_sdk::address::{Address, ImplicitAddress}; use namada_sdk::args::TxBecomeValidator; use namada_sdk::collections::HashSet; @@ -32,7 +30,9 @@ use crate::client::tx::tx::ProcessTxResponse; use crate::config::TendermintMode; use crate::facade::tendermint_rpc::endpoint::broadcast::tx_sync::Response; use crate::tendermint_node; -use crate::wallet::{gen_validator_keys, read_and_confirm_encryption_password}; +use crate::wallet::{ + gen_validator_keys, read_and_confirm_encryption_password, WalletTransport, +}; /// Wrapper around `signing::aux_signing_data` that stores the optional /// disposable address to the wallet @@ -43,7 +43,8 @@ pub async fn aux_signing_data( default_signer: Option
, ) -> Result { let signing_data = - signing::aux_signing_data(context, args, owner, default_signer).await?; + signing::aux_signing_data(context, args, owner, default_signer, vec![]) + .await?; if args.disposable_signing_key { if !(args.dry_run || args.dry_run_wrapper) { @@ -65,12 +66,17 @@ pub async fn aux_signing_data( Ok(signing_data) } -pub async fn with_hardware_wallet<'a, U: WalletIo + Clone>( +pub async fn with_hardware_wallet<'a, U, T>( mut tx: Tx, pubkey: common::PublicKey, parts: HashSet, - (wallet, app): (&RwLock>, &NamadaApp), -) -> Result { + (wallet, app): (&RwLock>, &NamadaApp), +) -> Result +where + U: WalletIo + Clone, + T: ledger_transport::Exchange + Send + Sync, + ::Error: std::error::Error, +{ // Obtain derivation path let path = wallet .read() @@ -157,18 +163,8 @@ pub async fn sign( ) -> Result<(), error::Error> { // Setup a reusable context for signing transactions using the Ledger if args.use_device { - // Setup a reusable context for signing transactions using the Ledger - let hidapi = HidApi::new().map_err(|err| { - error::Error::Other(format!("Failed to create Hidapi: {}", err)) - })?; - let app = NamadaApp::new(TransportNativeHID::new(&hidapi).map_err( - |err| { - error::Error::Other(format!( - "Unable to connect to Ledger: {}", - err - )) - }, - )?); + let transport = WalletTransport::from_arg(args.device_transport); + let app = NamadaApp::new(transport); let with_hw_data = (context.wallet_lock(), &app); // Finally, begin the signing with the Ledger as backup context @@ -176,7 +172,7 @@ pub async fn sign( tx, args, signing_data, - with_hardware_wallet::, + with_hardware_wallet::, with_hw_data, ) .await?; @@ -765,18 +761,9 @@ pub async fn submit_transparent_transfer( )); } - submit_reveal_aux( - namada, - args.tx.clone(), - &args - .data - .first() - .ok_or_else(|| { - error::Error::Other("Missing transfer data".to_string()) - })? - .source, - ) - .await?; + for datum in args.data.iter() { + submit_reveal_aux(namada, args.tx.clone(), &datum.source).await?; + } let (mut tx, signing_data) = args.clone().build(namada).await?; @@ -809,6 +796,10 @@ pub async fn submit_shielding_transfer( namada: &impl Namada, args: args::TxShieldingTransfer, ) -> Result<(), error::Error> { + for datum in args.data.iter() { + submit_reveal_aux(namada, args.tx.clone(), &datum.source).await?; + } + // Repeat once if the tx fails on a crossover of an epoch for _ in 0..2 { let (mut tx, signing_data, tx_epoch) = diff --git a/crates/apps_lib/src/client/utils.rs b/crates/apps_lib/src/client/utils.rs index 0d88cd54d5..702ebbcb06 100644 --- a/crates/apps_lib/src/client/utils.rs +++ b/crates/apps_lib/src/client/utils.rs @@ -9,6 +9,8 @@ use flate2::read::GzDecoder; use flate2::write::GzEncoder; use flate2::Compression; use itertools::Either; +use namada_sdk::address::Address; +use namada_sdk::args::DeviceTransport; use namada_sdk::chain::ChainId; use namada_sdk::dec::Dec; use namada_sdk::key::*; @@ -28,6 +30,7 @@ use crate::config::genesis::chain::DeriveEstablishedAddress; use crate::config::genesis::transactions::{ sign_delegation_bond_tx, sign_validator_account_tx, UnsignedTransactions, }; +use crate::config::genesis::{AddrOrPk, GenesisAddress}; use crate::config::global::GlobalConfig; use crate::config::{self, genesis, get_default_namada_folder, TendermintMode}; use crate::facade::tendermint::node::Id as TendermintNodeId; @@ -54,7 +57,6 @@ pub async fn join_network( chain_id, genesis_validator, pre_genesis_path, - dont_prefetch_wasm, allow_duplicate_ip, add_persistent_peers, }: args::JoinNetwork, @@ -250,9 +252,8 @@ pub async fn join_network( config.wasm_dir = wasm_dir_full; } - if !dont_prefetch_wasm { - fetch_wasms_aux(&chain_id, &config.wasm_dir).await; - } + // Validate the wasm artifacts checksums + validate_wasm_artifacts_aux(&chain_id, &config.wasm_dir).await; // Save the config and the wallet config.write(&base_dir, &chain_id, true).unwrap(); @@ -261,9 +262,9 @@ pub async fn join_network( println!("Successfully configured for chain ID {chain_id}"); } -async fn fetch_wasms_aux(chain_id: &ChainId, wasm_dir: &Path) { - println!("Fetching missing wasms for chain ID {chain_id}..."); - wasm_loader::pre_fetch_wasm(wasm_dir).await; +async fn validate_wasm_artifacts_aux(chain_id: &ChainId, wasm_dir: &Path) { + println!("Validating wasms artifacts for chain ID {chain_id}..."); + wasm_loader::validate_wasm_artifacts(wasm_dir).await; } pub fn validate_wasm(args::ValidateWasm { code_path }: args::ValidateWasm) { @@ -603,13 +604,40 @@ pub fn init_genesis_established_account( } /// Bond to a validator at pre-genesis. -pub fn genesis_bond(args: args::GenesisBond) { +pub fn genesis_bond(global_args: args::Global, args: args::GenesisBond) { let args::GenesisBond { source, validator, bond_amount, output: toml_path, } = args; + + let (wallet, _wallet_file) = + load_pre_genesis_wallet_or_exit(&global_args.base_dir); + let source = match source { + AddrOrPk::Address(addr) => match &addr { + Address::Established(established) => { + GenesisAddress::EstablishedAddress(established.clone()) + } + Address::Implicit(internal) => { + match wallet.find_public_key_from_implicit_addr(internal) { + Ok(pk) => GenesisAddress::PublicKey(StringEncoded::new(pk)), + Err(err) => { + eprintln!( + "Couldn't find the PK associated with the given \ + implicit address {addr} in the wallet: {err}" + ); + safe_exit(1) + } + } + } + Address::Internal(_) => { + eprintln!("Unexpected internal address as bond source"); + safe_exit(1); + } + }, + AddrOrPk::PublicKey(pk) => GenesisAddress::PublicKey(pk), + }; let txs = genesis::transactions::init_bond(source, validator, bond_amount); let toml_path_str = toml_path.to_string_lossy(); @@ -865,6 +893,7 @@ async fn append_signature_to_signed_toml( input_txs: &Path, wallet: &RwLock>, use_device: bool, + device_transport: DeviceTransport, ) -> genesis::transactions::Transactions { // Parse signed txs toml to append new signatures to let mut genesis_txs = genesis::templates::read_transactions(input_txs) @@ -885,6 +914,7 @@ async fn append_signature_to_signed_toml( wallet, &genesis_txs.established_account, use_device, + device_transport, ) .await, ); @@ -904,6 +934,7 @@ async fn append_signature_to_signed_toml( validator account txs", ), use_device, + device_transport, ) .await, ); @@ -921,6 +952,7 @@ pub async fn sign_genesis_tx( output, validator_alias, use_device, + device_transport, }: args::SignGenesisTxs, ) { let (wallet, _wallet_file) = @@ -947,6 +979,7 @@ pub async fn sign_genesis_tx( &wallet_lock, maybe_pre_genesis_wallet.as_ref(), use_device, + device_transport, ) .await; if let Some(output_path) = output.as_ref() { @@ -964,7 +997,13 @@ pub async fn sign_genesis_tx( // In case we fail to parse unsigned txs, we will attempt to // parse signed txs and append new signatures to the existing // toml file - append_signature_to_signed_toml(&path, &wallet_lock, use_device).await + append_signature_to_signed_toml( + &path, + &wallet_lock, + use_device, + device_transport, + ) + .await }; match output { Some(output_path) => { diff --git a/crates/apps_lib/src/config/genesis.rs b/crates/apps_lib/src/config/genesis.rs index 5d7d4a8534..b2efd1a227 100644 --- a/crates/apps_lib/src/config/genesis.rs +++ b/crates/apps_lib/src/config/genesis.rs @@ -148,6 +148,107 @@ impl FromStr for GenesisAddress { } } +#[derive( + Clone, + Debug, + BorshSerialize, + BorshDeserialize, + BorshDeserializer, + PartialEq, + Eq, + Ord, + PartialOrd, + Hash, +)] +#[allow(missing_docs)] +pub enum AddrOrPk { + PublicKey(StringEncoded), + Address(Address), +} + +impl AddrOrPk { + /// Return an [`Address`] from this [`AddrOrPk`]. + #[inline] + pub fn address(&self) -> Address { + match self { + Self::Address(addr) => addr.clone(), + Self::PublicKey(pk) => (&pk.raw).into(), + } + } +} + +impl Serialize for AddrOrPk { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self { + AddrOrPk::Address(address) => { + Serialize::serialize(&address, serializer) + } + AddrOrPk::PublicKey(pk) => Serialize::serialize(pk, serializer), + } + } +} + +impl<'de> Deserialize<'de> for AddrOrPk { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct FieldVisitor; + + impl<'de> serde::de::Visitor<'de> for FieldVisitor { + type Value = AddrOrPk; + + fn expecting( + &self, + formatter: &mut Formatter<'_>, + ) -> std::fmt::Result { + formatter + .write_str("a bech32m encoded public key or an address") + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + AddrOrPk::from_str(value).map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_str(FieldVisitor) + } +} + +impl Display for AddrOrPk { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AddrOrPk::Address(address) => write!(f, "{address}"), + AddrOrPk::PublicKey(pk) => write!(f, "{}", pk), + } + } +} + +impl FromStr for AddrOrPk { + type Err = String; + + fn from_str(value: &str) -> Result { + // Try to deserialize a PK first + let maybe_pk = StringEncoded::::from_str(value); + match maybe_pk { + Ok(pk) => Ok(AddrOrPk::PublicKey(pk)), + Err(_) => { + // If that doesn't work, attempt to retrieve + // an address + let address = + Address::from_str(value).map_err(|err| err.to_string())?; + Ok(AddrOrPk::Address(address)) + } + } + } +} + #[derive(Debug, BorshSerialize, BorshDeserialize, BorshDeserializer)] #[borsh(init=init)] pub struct Genesis { @@ -426,8 +527,7 @@ pub fn make_dev_genesis( .unwrap() .first() .unwrap(); - let genesis_addr = - GenesisAddress::EstablishedAddress(tx.tx.data.address.raw.clone()); + let genesis_addr = Address::Established(tx.tx.data.address.raw.clone()); let balance = *nam_balances.0.get(&genesis_addr).unwrap(); let bonded = { @@ -543,11 +643,9 @@ pub fn make_dev_genesis( .get_mut(&Alias::from_str("nam").unwrap()) .unwrap(); - let validator_addr = - GenesisAddress::EstablishedAddress(validator_address.clone()); - let account_pk = GenesisAddress::PublicKey(StringEncoded::new( - consensus_keypair.ref_to(), - )); + let validator_addr: Address = + Address::Established(validator_address.clone()); + let account_pk: Address = (&consensus_keypair.ref_to()).into(); nam_balances.0.insert(validator_addr, first_val_balance); nam_balances.0.insert(account_pk, first_val_balance); diff --git a/crates/apps_lib/src/config/genesis/chain.rs b/crates/apps_lib/src/config/genesis/chain.rs index fac84c20d0..df50cb07b5 100644 --- a/crates/apps_lib/src/config/genesis/chain.rs +++ b/crates/apps_lib/src/config/genesis/chain.rs @@ -86,6 +86,24 @@ impl Finalized { Ok(()) } + /// Attempt to read the address of the native token. + pub fn read_native_token(input_dir: &Path) -> eyre::Result
{ + let tokens_file = input_dir.join(templates::TOKENS_FILE_NAME); + let parameters_file = input_dir.join(templates::PARAMETERS_FILE_NAME); + + let mut tokens: FinalizedTokens = read_toml(&tokens_file, "Tokens")?; + let parameters: FinalizedParameters = + read_toml(¶meters_file, "Parameters")?; + + let alias = ¶meters.parameters.native_token; + + Ok(tokens + .token + .remove(alias) + .expect("The native token must exist") + .address) + } + /// Try to read all genesis and the chain metadata TOML files from the given /// directory. pub fn read_toml_files(input_dir: &Path) -> eyre::Result { diff --git a/crates/apps_lib/src/config/genesis/templates.rs b/crates/apps_lib/src/config/genesis/templates.rs index dd4592ed62..29194f29f5 100644 --- a/crates/apps_lib/src/config/genesis/templates.rs +++ b/crates/apps_lib/src/config/genesis/templates.rs @@ -24,7 +24,6 @@ use super::transactions::{self, Transactions}; use super::utils::{read_toml, write_toml}; use crate::config::genesis::chain::DeriveEstablishedAddress; use crate::config::genesis::transactions::{BondTx, SignedBondTx}; -use crate::config::genesis::GenesisAddress; use crate::wallet::Alias; pub const BALANCES_FILE_NAME: &str = "balances.toml"; @@ -140,9 +139,7 @@ pub struct DenominatedBalances { PartialEq, Eq, )] -pub struct RawTokenBalances( - pub BTreeMap, -); +pub struct RawTokenBalances(pub BTreeMap); /// Genesis balances for a given token #[derive( @@ -156,9 +153,7 @@ pub struct RawTokenBalances( PartialEq, Eq, )] -pub struct TokenBalances( - pub BTreeMap, -); +pub struct TokenBalances(pub BTreeMap); /// Genesis validity predicates #[derive( @@ -522,7 +517,7 @@ pub struct IbcParams { } impl TokenBalances { - pub fn get(&self, addr: &GenesisAddress) -> Option { + pub fn get(&self, addr: &Address) -> Option { self.0.get(addr).map(|amt| amt.amount()) } } @@ -991,7 +986,6 @@ mod tests { use namada_sdk::key; use namada_sdk::key::RefTo; - use namada_sdk::string_encoding::StringEncoded; use tempfile::tempdir; use super::*; @@ -1026,20 +1020,34 @@ mod tests { ); } + /// Validate the `genesis/hardware` genesis templates. + #[test] + fn test_validate_hardware_genesis_templates() { + let templates_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .parent() + .unwrap() + .join("genesis/hardware"); + assert!( + load_and_validate(&templates_dir).is_some(), + "Hardware genesis templates must be valid" + ); + } + #[test] fn test_read_balances() { let test_dir = tempdir().unwrap(); let path = test_dir.path().join(BALANCES_FILE_NAME); let sk = key::testing::keypair_1(); let pk = sk.ref_to(); - let address = - GenesisAddress::PublicKey(StringEncoded { raw: pk.clone() }); + let address: Address = (&pk).into(); let balance = token::Amount::from(101_000_001); let token_alias = Alias::from("Some_token".to_string()); let contents = format!( r#" [token.{token_alias}] - {pk} = "{}" + {address} = "{}" "#, balance.to_string_native() ); diff --git a/crates/apps_lib/src/config/genesis/transactions.rs b/crates/apps_lib/src/config/genesis/transactions.rs index f066b429a7..3239ad18e1 100644 --- a/crates/apps_lib/src/config/genesis/transactions.rs +++ b/crates/apps_lib/src/config/genesis/transactions.rs @@ -8,14 +8,12 @@ use borsh::{BorshDeserialize, BorshSerialize}; use borsh_ext::BorshSerializeExt; use itertools::{Either, Itertools}; use ledger_namada_rs::NamadaApp; -use ledger_transport_hid::hidapi::HidApi; -use ledger_transport_hid::TransportNativeHID; use namada_macros::BorshDeserializer; #[cfg(feature = "migrations")] use namada_migrations::*; use namada_sdk::account::AccountPublicKeysMap; use namada_sdk::address::{Address, EstablishedAddress}; -use namada_sdk::args::Tx as TxArgs; +use namada_sdk::args::{DeviceTransport, Tx as TxArgs}; use namada_sdk::chain::ChainId; use namada_sdk::collections::HashSet; use namada_sdk::dec::Dec; @@ -45,7 +43,7 @@ use crate::config::genesis::templates::{ TemplateValidation, Unvalidated, Validated, }; use crate::config::genesis::{utils, GenesisAddress}; -use crate::wallet::CliWalletUtils; +use crate::wallet::{CliWalletUtils, WalletTransport}; /// Dummy chain id used to sign [`Tx`] objects at pre-genesis. const NAMADA_GENESIS_TX_CHAIN_ID: &str = "namada-genesis"; @@ -93,6 +91,7 @@ fn get_tx_args(use_device: bool) -> TxArgs { password: None, memo: None, use_device, + device_transport: DeviceTransport::default(), } } @@ -165,6 +164,7 @@ pub async fn sign_txs( wallet: &RwLock>, validator_wallet: Option<&ValidatorWallet>, use_device: bool, + device_transport: DeviceTransport, ) -> Transactions { let UnsignedTransactions { established_account, @@ -182,6 +182,7 @@ pub async fn sign_txs( wallet, &established_account, use_device, + device_transport, ) .await, ); @@ -208,6 +209,7 @@ pub async fn sign_txs( validator account txs", ), use_device, + device_transport, ) .await, ); @@ -354,6 +356,7 @@ pub async fn sign_validator_account_tx( wallet: &RwLock>, established_accounts: &[EstablishedAccountTx], use_device: bool, + device_transport: DeviceTransport, ) -> SignedValidatorAccountTx { let mut to_sign = match to_sign { Either::Right(signed_tx) => signed_tx, @@ -434,7 +437,9 @@ pub async fn sign_validator_account_tx( } }; - to_sign.sign(established_accounts, wallet, use_device).await; + to_sign + .sign(established_accounts, wallet, use_device, device_transport) + .await; to_sign } @@ -443,11 +448,14 @@ pub async fn sign_delegation_bond_tx( wallet: &RwLock>, established_accounts: &Option>, use_device: bool, + device_transport: DeviceTransport, ) -> SignedBondTx { let default = vec![]; let established_accounts = established_accounts.as_ref().unwrap_or(&default); - to_sign.sign(established_accounts, wallet, use_device).await; + to_sign + .sign(established_accounts, wallet, use_device, device_transport) + .await; to_sign } @@ -741,6 +749,7 @@ impl Signed { established_accounts: &[EstablishedAccountTx], wallet_lock: &RwLock>, use_device: bool, + device_transport: DeviceTransport, ) where T: BorshSerialize + TxToSign, { @@ -757,11 +766,8 @@ impl Signed { let mut tx = self.data.tx_to_sign(); if use_device { - let hidapi = HidApi::new().expect("Failed to create Hidapi"); - let transport = TransportNativeHID::new(&hidapi) - .expect("Failed to create hardware wallet connection"); + let transport = WalletTransport::from_arg(device_transport); let app = NamadaApp::new(transport); - sign_tx( wallet_lock, &get_tx_args(use_device), @@ -771,7 +777,7 @@ impl Signed { (wallet_lock, &app), ) .await - .expect("Failed to sign pre-genesis transaction."); + .expect("Failed to sign pre-genesis transaction.") } else { async fn software_wallet_sign( tx: Tx, @@ -1191,9 +1197,10 @@ fn validate_bond( // Check and update token balance of the source let native_token = ¶meters.parameters.native_token; + let source = source.address(); match balances.get_mut(native_token) { Some(balances) => { - let balance = balances.amounts.get_mut(source); + let balance = balances.amounts.get_mut(&source); match balance { Some(balance) => { if *balance < *amount { @@ -1207,7 +1214,7 @@ fn validate_bond( } else { // Deduct the amount from source if amount == balance { - balances.amounts.remove(source); + balances.amounts.remove(&source); } else if let Some(new_balance) = balance.checked_sub(*amount) { @@ -1248,7 +1255,7 @@ fn validate_bond( #[derive(Clone, Debug)] pub struct TokenBalancesForValidation { /// Accumulator for tokens transferred to accounts - pub amounts: BTreeMap, + pub amounts: BTreeMap, } pub fn validate_established_account( diff --git a/crates/apps_lib/src/config/genesis/utils.rs b/crates/apps_lib/src/config/genesis/utils.rs index ee8d6bcadd..c5971d9d2c 100644 --- a/crates/apps_lib/src/config/genesis/utils.rs +++ b/crates/apps_lib/src/config/genesis/utils.rs @@ -2,7 +2,6 @@ use std::path::Path; use eyre::Context; use ledger_namada_rs::NamadaApp; -use ledger_transport_hid::TransportNativeHID; use namada_sdk::collections::HashSet; use namada_sdk::key::common; use namada_sdk::tx::Tx; @@ -50,15 +49,16 @@ pub fn write_toml( }) } -pub(super) async fn with_hardware_wallet<'a>( +pub(super) async fn with_hardware_wallet<'a, T>( tx: Tx, pubkey: common::PublicKey, parts: HashSet, - (wallet, app): ( - &RwLock>, - &NamadaApp, - ), -) -> Result { + (wallet, app): (&RwLock>, &NamadaApp), +) -> Result +where + T: ledger_transport::Exchange + Send + Sync, + ::Error: std::error::Error, +{ if parts.contains(&signing::Signable::FeeHeader) { Ok(tx) } else { diff --git a/crates/apps_lib/src/wallet/defaults.rs b/crates/apps_lib/src/wallet/defaults.rs index 7ea0c136d9..9a97a60ff3 100644 --- a/crates/apps_lib/src/wallet/defaults.rs +++ b/crates/apps_lib/src/wallet/defaults.rs @@ -4,12 +4,15 @@ pub use dev::{ addresses, albert_address, albert_keypair, bertha_address, bertha_keypair, christel_address, christel_keypair, daewon_address, daewon_keypair, - ester_address, ester_keypair, keys, tokens, validator_account_keypair, - validator_address, validator_keypair, validator_keys, + derive_template_dir, ester_address, ester_keypair, get_unencrypted_keypair, + is_use_device, keys, tokens, validator_account_keypair, validator_address, + validator_keypair, validator_keys, }; #[cfg(any(test, feature = "testing", feature = "benches"))] mod dev { + use std::path::{Path, PathBuf}; + use lazy_static::lazy_static; use namada_sdk::address::testing::{ apfel, btc, dot, eth, kartoffel, nam, schnitzel, @@ -182,12 +185,36 @@ mod dev { get_unencrypted_keypair("validator-0-account-key") } + /// Env. var to enable the usage of hardware wallets in tests + pub const ENV_VAR_USE_DEVICE: &str = "NAMADA_E2E_USE_DEVICE"; + + /// Check whether the ENV_VAR_USE_DEVICE environment variable is set + pub fn is_use_device() -> bool { + match std::env::var(ENV_VAR_USE_DEVICE) { + Ok(val) => val.to_ascii_lowercase() != "false", + _ => false, + } + } + + /// Derive the genesis path depending on whether the hardware wallet is in + /// use + pub fn derive_template_dir(working_dir: &Path) -> PathBuf { + // The E2E tests genesis config source. + // This file must contain a single validator with alias "validator-0". + // To add more validators, use the [`set_validators`] function in the + // call to setup the [`network`]. + if is_use_device() { + working_dir.join("genesis").join("hardware") + } else { + working_dir.join("genesis").join("localnet") + } + } + /// The name of a file that is unique to the project's root directory. const PROJECT_ROOT_UNIQUE_FILE: &str = "rust-toolchain.toml"; /// The pre-genesis directory of `validator-0`. - const VALIDATOR_0_PREGENESIS_DIR: &str = - "genesis/localnet/src/pre-genesis/validator-0"; + const VALIDATOR_0_PREGENESIS_DIR: &str = "src/pre-genesis/validator-0"; lazy_static! { static ref PREGENESIS_WALLET: Wallet = { @@ -199,7 +226,7 @@ mod dev { while !root_dir.join(PROJECT_ROOT_UNIQUE_FILE).exists() { root_dir.pop(); } - let path = root_dir.join("genesis/localnet/src/pre-genesis"); + let path = derive_template_dir(&root_dir).join("src/pre-genesis"); crate::wallet::load(&path).unwrap() }; @@ -213,7 +240,7 @@ mod dev { root_dir.pop(); } let path = - root_dir.join(VALIDATOR_0_PREGENESIS_DIR); + derive_template_dir(&root_dir).join(VALIDATOR_0_PREGENESIS_DIR); crate::wallet::pre_genesis::load(&path).unwrap() }; } diff --git a/crates/apps_lib/src/wallet/mod.rs b/crates/apps_lib/src/wallet/mod.rs index c95bdebf0d..b841240c59 100644 --- a/crates/apps_lib/src/wallet/mod.rs +++ b/crates/apps_lib/src/wallet/mod.rs @@ -1,6 +1,7 @@ pub mod defaults; pub mod pre_genesis; mod store; +mod transport; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -17,6 +18,7 @@ use namada_sdk::wallet::{ pub use namada_sdk::wallet::{ValidatorData, ValidatorKeys}; use rand_core::OsRng; pub use store::wallet_file; +pub use transport::{TransportTcp, WalletTransport}; use zeroize::Zeroizing; use crate::cli; diff --git a/crates/apps_lib/src/wallet/transport.rs b/crates/apps_lib/src/wallet/transport.rs new file mode 100644 index 0000000000..f8353de362 --- /dev/null +++ b/crates/apps_lib/src/wallet/transport.rs @@ -0,0 +1,95 @@ +//! Hardware wallet transport over HID or TCP + +use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; +use std::ops::Deref; +use std::str::FromStr; + +use ledger_lib::transport::TcpInfo; +use ledger_lib::Transport; +use ledger_transport::{APDUAnswer, APDUCommand}; +use ledger_transport_hid::hidapi::HidApi; +use ledger_transport_hid::TransportNativeHID; +use namada_sdk::args; + +/// Hardware wallet transport +pub enum WalletTransport { + /// HID transport + HID(TransportNativeHID), + /// TCP transport + TCP(TransportTcp), +} + +impl WalletTransport { + pub fn from_arg(arg: args::DeviceTransport) -> Self { + match arg { + args::DeviceTransport::Hid => { + let hidapi = HidApi::new() + .expect("Must be able to instantiate a hidapi context"); + let transport = TransportNativeHID::new(&hidapi) + .expect("Must be able to connect to a HID wallet"); + Self::HID(transport) + } + args::DeviceTransport::Tcp => Self::TCP(TransportTcp), + } + } +} + +#[ledger_transport::async_trait] +impl ledger_transport::Exchange for WalletTransport { + type AnswerType = Vec; + type Error = std::io::Error; + + async fn exchange( + &self, + command: &APDUCommand, + ) -> Result, Self::Error> + where + I: Deref + Send + Sync, + { + match self { + WalletTransport::HID(transport) => transport + .exchange(command) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)), + WalletTransport::TCP(transport) => transport + .exchange(command) + .await + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)), + } + } +} + +/// Hardware wallet TCP transport +#[derive(Default)] +pub struct TransportTcp; + +#[ledger_transport::async_trait] +impl ledger_transport::Exchange for TransportTcp { + type AnswerType = Vec; + type Error = ledger_lib::Error; + + async fn exchange( + &self, + command: &APDUCommand, + ) -> Result, Self::Error> + where + I: Deref + Send + Sync, + { + use ledger_lib::Exchange; + let mut transport = ledger_lib::transport::TcpTransport::default(); + let ip = std::env::var("LEDGER_PROXY_ADDRESS") + .map(|s| Ipv4Addr::from_str(&s).unwrap()) + .unwrap_or(Ipv4Addr::LOCALHOST); + let port = std::env::var("LEDGER_PROXY_PORT") + .map(|s| u16::from_str(&s).unwrap()) + .unwrap_or(9999); + let mut device = transport + .connect(TcpInfo { + addr: SocketAddr::V4(SocketAddrV4::new(ip, port)), + }) + .await?; + let res = device + .exchange(&command.serialize(), std::time::Duration::from_secs(60)) + .await?; + Ok(APDUAnswer::from_answer(res).unwrap()) + } +} diff --git a/crates/apps_lib/src/wasm_loader/mod.rs b/crates/apps_lib/src/wasm_loader/mod.rs index f9f9be70f4..a5de01a6a4 100644 --- a/crates/apps_lib/src/wasm_loader/mod.rs +++ b/crates/apps_lib/src/wasm_loader/mod.rs @@ -1,5 +1,4 @@ //! A module for loading WASM files and downloading pre-built WASMs. -use core::borrow::Borrow; use std::fs; use std::path::Path; @@ -35,10 +34,6 @@ pub enum Error { #[serde(transparent)] pub struct Checksums(pub HashMap); -/// Github URL prefix of released Namada network configs -pub const ENV_VAR_WASM_SERVER: &str = "NAMADA_NETWORK_WASM_SERVER"; -const DEFAULT_WASM_SERVER: &str = "https://artifacts.heliax.click/namada-wasm"; - impl Checksums { /// Read WASM checksums from the given path pub fn read_checksums_file( @@ -115,12 +110,6 @@ impl Checksums { } } -fn wasm_url(wasm_name: &str) -> String { - let prefix_url = std::env::var(ENV_VAR_WASM_SERVER) - .unwrap_or_else(|_| DEFAULT_WASM_SERVER.to_string()); - format!("{}/{}", prefix_url, wasm_name) -} - fn valid_wasm_checksum( wasm_payload: &[u8], name: &str, @@ -141,9 +130,8 @@ fn valid_wasm_checksum( } } -/// Download all the pre-built wasms, or if they're already downloaded, verify -/// their checksums. -pub async fn pre_fetch_wasm(wasm_directory: impl AsRef) { +/// Validate wasm artifacts +pub async fn validate_wasm_artifacts(wasm_directory: impl AsRef) { // load json with wasm hashes let checksums = Checksums::read_checksums_async(&wasm_directory).await; @@ -154,69 +142,29 @@ pub async fn pre_fetch_wasm(wasm_directory: impl AsRef) { tokio::spawn(async move { let wasm_path = wasm_directory.join(&full_name); match tokio::fs::read(&wasm_path).await { - // if the file exist, first check the hash. If not matching - // download it again. + // if the file exist, check the hash Ok(bytes) => { if let Err(derived_name) = valid_wasm_checksum(&bytes, &name, &full_name) { tracing::info!( "WASM checksum mismatch: Got {}, expected {}. \ - Fetching new version...", + Check your wasms artifacts.", derived_name, full_name ); - } else { - return; - } - - match download_wasm(&name, &full_name).await { - Ok(bytes) => { - if let Err(e) = - tokio::fs::write(wasm_path, &bytes).await - { - eprintln!( - "Error while creating file for {}: {}", - &name, e - ); - safe_exit(1); - } - } - Err(e) => { - eprintln!("Error downloading wasm: {}", e); - safe_exit(1); - } + safe_exit(1); } } // if the doesn't file exist, download it. - Err(err) => match err.kind() { - std::io::ErrorKind::NotFound => { - match download_wasm(&name, &full_name).await { - Ok(bytes) => { - if let Err(e) = - tokio::fs::write(wasm_path, &bytes).await - { - eprintln!( - "Error while creating file for {}: {}", - &name, e - ); - safe_exit(1); - } - } - Err(e) => { - eprintln!("Error downloading wasm: {}", e); - safe_exit(1); - } - } - } - _ => { - eprintln!( - "Can't read {}.", - wasm_path.as_os_str().to_string_lossy() - ); - safe_exit(1); - } - }, + Err(err) => { + eprintln!( + "Can't read {}: {}", + wasm_path.as_os_str().to_string_lossy(), + err + ); + safe_exit(1); + } } }) })) @@ -270,33 +218,3 @@ pub fn read_wasm_or_exit( } } } - -async fn download_wasm(name: &str, full_name: &str) -> Result, Error> { - let url = wasm_url(full_name); - - tracing::info!("Downloading WASM {url}..."); - - let response = reqwest::get(&url).await; - - match response { - Ok(body) => { - let status = body.status(); - if status.is_success() { - let bytes = body.bytes().await.unwrap(); - let bytes: &[u8] = bytes.borrow(); - - valid_wasm_checksum(bytes, name, full_name) - .map_err(Error::ChecksumMismatch)?; - - let bytes: Vec = bytes.to_owned(); - - Ok(bytes) - } else if status.is_server_error() { - Err(Error::WasmNotFound(url)) - } else { - Err(Error::ServerError(url, status.to_string())) - } - } - Err(e) => Err(Error::Download(url, e)), - } -} diff --git a/crates/benches/native_vps.rs b/crates/benches/native_vps.rs index 499c2e14bf..536d337f23 100644 --- a/crates/benches/native_vps.rs +++ b/crates/benches/native_vps.rs @@ -34,7 +34,9 @@ use namada_apps_lib::ibc::core::host::types::identifiers::{ ClientId, ConnectionId, PortId, }; use namada_apps_lib::ibc::primitives::ToProto; -use namada_apps_lib::ibc::{IbcActions, NftTransferModule, TransferModule}; +use namada_apps_lib::ibc::{ + IbcActions, NftTransferModule, TransferModule, COMMITMENT_PREFIX, +}; use namada_apps_lib::masp::{ partial_deauthorize, preload_verifying_keys, PVKs, TransferSource, TransferTarget, @@ -330,7 +332,9 @@ fn prepare_ibc_tx_and_ctx(bench_name: &str) -> (BenchShieldedCtx, BatchedTx) { counterparty: Counterparty::new( ClientId::from_str("07-tendermint-1").unwrap(), None, - CommitmentPrefix::try_from(b"ibc".to_vec()).unwrap(), + CommitmentPrefix::from( + COMMITMENT_PREFIX.as_bytes().to_vec(), + ), ), version: Some(Version::compatibles().first().unwrap().clone()), delay_period: std::time::Duration::new(100, 0), @@ -399,7 +403,7 @@ fn prepare_ibc_tx_and_ctx(bench_name: &str) -> (BenchShieldedCtx, BatchedTx) { shielded_ctx.shell.write().commit_block(); shielded_ctx.generate_shielded_action( Amount::native_whole(10), - TransferSource::ExtendedSpendingKey(albert_spending_key), + TransferSource::ExtendedSpendingKey(albert_spending_key.key), defaults::bertha_address().to_string(), ) } @@ -591,12 +595,12 @@ fn setup_storage_for_masp_verification( ), "unshielding" => shielded_ctx.generate_masp_tx( amount, - TransferSource::ExtendedSpendingKey(albert_spending_key), + TransferSource::ExtendedSpendingKey(albert_spending_key.key), TransferTarget::Address(defaults::albert_address()), ), "shielded" => shielded_ctx.generate_masp_tx( amount, - TransferSource::ExtendedSpendingKey(albert_spending_key), + TransferSource::ExtendedSpendingKey(albert_spending_key.key), TransferTarget::PaymentAddress(bertha_payment_addr), ), _ => panic!("Unexpected bench test"), @@ -768,7 +772,7 @@ fn masp_check_convert(c: &mut Criterion) { } fn masp_check_output(c: &mut Criterion) { - c.bench_function("masp_vp_check_output", |b| { + c.bench_function("vp_masp_check_output", |b| { b.iter_batched( || { let (_, _verifiers_from_tx, signed_tx) = @@ -994,7 +998,9 @@ fn customize_masp_tx_data( ) } -// benchmark the cost of validating two signatures in a batch. +// Benchmark the cost of validating two signatures in a batch (two leverage +// multiscalar multiplication speedups). The gas cost per single signature +// verification should be the result of this bench divided by two. fn masp_batch_signature_verification(c: &mut Criterion) { let (_, _, tx) = setup_storage_for_masp_verification("unshielding"); let transaction = tx @@ -1040,8 +1046,7 @@ fn masp_batch_signature_verification(c: &mut Criterion) { // Benchmark both one and two proofs and take the difference as the variable // cost for every proofs. Charge the full cost for the first note and then -// charge the variable cost multiplied by the number of remaining notes and -// divided by the number of cores +// charge the variable cost multiplied by the number of remaining notes fn masp_batch_spend_proofs_validate(c: &mut Criterion) { let mut group = c.benchmark_group("masp_batch_spend_proofs_validate"); let PVKs { spend_vk, .. } = preload_verifying_keys(); @@ -1086,8 +1091,7 @@ fn masp_batch_spend_proofs_validate(c: &mut Criterion) { // Benchmark both one and two proofs and take the difference as the variable // cost for every proofs. Charge the full cost for the first note and then -// charge the variable cost multiplied by the number of remaining notes and -// divided by the number of cores +// charge the variable cost multiplied by the number of remaining notes fn masp_batch_convert_proofs_validate(c: &mut Criterion) { let mut group = c.benchmark_group("masp_batch_convert_proofs_validate"); let PVKs { convert_vk, .. } = preload_verifying_keys(); @@ -1132,8 +1136,7 @@ fn masp_batch_convert_proofs_validate(c: &mut Criterion) { // Benchmark both one and two proofs and take the difference as the variable // cost for every proofs. Charge the full cost for the first note and then -// charge the variable cost multiplied by the number of remaining notes and -// divided by the number of cores +// charge the variable cost multiplied by the number of remaining notes fn masp_batch_output_proofs_validate(c: &mut Criterion) { let mut group = c.benchmark_group("masp_batch_output_proofs_validate"); let PVKs { output_vk, .. } = preload_verifying_keys(); diff --git a/crates/benches/process_wrapper.rs b/crates/benches/process_wrapper.rs index 2b5f1db458..715df4cc07 100644 --- a/crates/benches/process_wrapper.rs +++ b/crates/benches/process_wrapper.rs @@ -86,6 +86,13 @@ fn process_tx(c: &mut Criterion) { )| { assert_eq!( // Assert that the wrapper transaction was valid + // NOTE: this function invovles a loop on the inner txs to + // check that they are allowlisted. The cost of that should + // technically depend on the number of inner txs and should + // be computed at runtime. From some tests though, we can + // see that the cost of that operation is minimale (200 + // ns), so we can just approximate it to a constant cost + // included in this benchmark shell .check_proposal_tx( &wrapper, @@ -106,5 +113,5 @@ fn process_tx(c: &mut Criterion) { }); } -criterion_group!(process_wrapper, process_tx); +criterion_group!(process_wrapper, process_tx,); criterion_main!(process_wrapper); diff --git a/crates/benches/wasm_opcodes.rs b/crates/benches/wasm_opcodes.rs index ceae69bc51..add5d4dd14 100644 --- a/crates/benches/wasm_opcodes.rs +++ b/crates/benches/wasm_opcodes.rs @@ -17,13 +17,27 @@ use wasm_instrument::parity_wasm::elements::Instruction::*; use wasm_instrument::parity_wasm::elements::{ BlockType, BrTableData, SignExtInstruction, }; -use wasmer::{imports, Instance, Module, Store, Value}; +use wasmer::{imports, Instance, Module, Store}; // Don't reduce this value too much or it will be impossible to see the // differences in execution times between the diffent instructions const ITERATIONS: u64 = 10_000; const ENTRY_POINT: &str = "op"; +lazy_static! { + static ref EMPTY_MODULE: String = format!( + r#" + (module + (func $f0 nop) + (func $f1 (result i32) i32.const 1 return) + (table 1 funcref) + (elem (i32.const 0) $f0) + (global $iter (mut i32) (i32.const 0)) + (memory 1) + (func (export "{ENTRY_POINT}") (param $local_var i32)"# + ); +} + lazy_static! { static ref WASM_OPTS: Vec = vec![ // Unreachable unconditionally traps, so no need to divide its cost by ITERATIONS because we only execute it once @@ -386,18 +400,7 @@ struct WatBuilder { impl Display for WatBuilder { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!( - f, - r#" - (module - (func $f0 nop) - (func $f1 (result i32) i32.const 1 return) - (table 1 funcref) - (elem (i32.const 0) $f0) - (global $iter (mut i32) (i32.const 0)) - (memory 1) - (func (export "{ENTRY_POINT}") (param $local_var i32)"# - )?; + writeln!(f, r#"{}"#, *EMPTY_MODULE)?; for _ in 0..ITERATIONS { writeln!(f, r#"{}"#, self.wat)?; @@ -420,20 +423,19 @@ fn get_wasm_store() -> Store { // An empty wasm module to serve as the base reference for all the other // instructions since the bigger part of the cost is the function call itself fn empty_module(c: &mut Criterion) { - let module_wat = format!( - r#" - (module - (func (export "{ENTRY_POINT}") (param $local_var i32)) - ) - "#, - ); + let module_wat = format!(r#"{}))"#, *EMPTY_MODULE); let mut store = get_wasm_store(); let module = Module::new(&store, module_wat).unwrap(); let instance = Instance::new(&mut store, &module, &imports! {}).unwrap(); - let function = instance.exports.get_function(ENTRY_POINT).unwrap(); + let function = instance + .exports + .get_function(ENTRY_POINT) + .unwrap() + .typed::(&store) + .unwrap(); c.bench_function("empty_module", |b| { - b.iter(|| function.call(&mut store, &[Value::I32(0)]).unwrap()); + b.iter(|| function.call(&mut store, 0).unwrap()); }); } @@ -445,15 +447,18 @@ fn ops(c: &mut Criterion) { let module = Module::new(&store, builder.to_string()).unwrap(); let instance = Instance::new(&mut store, &module, &imports! {}).unwrap(); - let function = instance.exports.get_function(ENTRY_POINT).unwrap(); + let function = instance + .exports + .get_function(ENTRY_POINT) + .unwrap() + .typed::(&store) + .unwrap(); group.bench_function(format!("{}", builder.instruction), |b| { if let Unreachable = builder.instruction { - b.iter(|| { - function.call(&mut store, &[Value::I32(0)]).unwrap_err() - }); + b.iter(|| function.call(&mut store, 0).unwrap_err()); } else { - b.iter(|| function.call(&mut store, &[Value::I32(0)]).unwrap()); + b.iter(|| function.call(&mut store, 0).unwrap()); } }); } diff --git a/crates/core/src/address.rs b/crates/core/src/address.rs index 409622d747..a2035c5fb9 100644 --- a/crates/core/src/address.rs +++ b/crates/core/src/address.rs @@ -609,7 +609,7 @@ impl Display for InternalAddress { Self::Erc20(eth_addr) => format!("Erc20: {}", eth_addr), Self::Nut(eth_addr) => format!("Non-usable token: {eth_addr}"), Self::Multitoken => "Multitoken".to_string(), - Self::Pgf => "PublicGoodFundings".to_string(), + Self::Pgf => "PGF".to_string(), Self::Masp => "MASP".to_string(), Self::ReplayProtection => "ReplayProtection".to_string(), Self::TempStorage => "TempStorage".to_string(), @@ -629,6 +629,7 @@ impl InternalAddress { "governance" => Some(InternalAddress::Governance), "masp" => Some(InternalAddress::Masp), "replayprotection" => Some(InternalAddress::ReplayProtection), + "pgf" => Some(InternalAddress::Pgf), _ => None, } } diff --git a/crates/core/src/masp.rs b/crates/core/src/masp.rs index a3b6736b05..b814532091 100644 --- a/crates/core/src/masp.rs +++ b/crates/core/src/masp.rs @@ -8,6 +8,7 @@ use std::str::FromStr; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use borsh_ext::BorshSerializeExt; use masp_primitives::asset_type::AssetType; +use masp_primitives::sapling::ViewingKey; use masp_primitives::transaction::TransparentAddress; use namada_macros::BorshDeserializer; #[cfg(feature = "migrations")] @@ -257,6 +258,11 @@ impl ExtendedViewingKey { masp_primitives::zip32::ExtendedFullViewingKey::read(&mut &bytes[..]) .map(Self) } + + /// Get the underlying viewing key + pub fn as_viewing_key(&self) -> ViewingKey { + self.0.fvk.vk + } } impl string_encoding::Format for ExtendedViewingKey { diff --git a/crates/core/src/uint.rs b/crates/core/src/uint.rs index d77e08369b..8736379e9b 100644 --- a/crates/core/src/uint.rs +++ b/crates/core/src/uint.rs @@ -472,7 +472,7 @@ impl Uint { } /// The maximum absolute value a [`I256`] may have. -/// Note the the last digit is 2^63 - 1. We add this cap so +/// Note the last digit is 2^63 - 1. We add this cap so /// we can use two's complement. pub const MAX_SIGNED_VALUE: Uint = Uint([u64::MAX, u64::MAX, u64::MAX, 9223372036854775807]); diff --git a/crates/gas/src/lib.rs b/crates/gas/src/lib.rs index 5cd92511d7..2847c9c0ac 100644 --- a/crates/gas/src/lib.rs +++ b/crates/gas/src/lib.rs @@ -50,74 +50,164 @@ pub enum GasParseError { Overflow, } -const COMPILE_GAS_PER_BYTE: u64 = 1_955; -const PARALLEL_GAS_DIVIDER: u64 = 10; -const WASM_CODE_VALIDATION_GAS_PER_BYTE: u64 = 67; -const WRAPPER_TX_VALIDATION_GAS: u64 = 3_245_500; +// RAW GAS COSTS +// ============================================================================= +// The raw gas costs exctracted from the benchmarks. +// +const COMPILE_GAS_PER_BYTE_RAW: u64 = 1_664; +const WASM_CODE_VALIDATION_GAS_PER_BYTE_RAW: u64 = 59; +const WRAPPER_TX_VALIDATION_GAS_RAW: u64 = 1_526_700; // There's no benchmark to calculate the cost of storage occupation, so we // define it as the cost of storage latency (which is needed for any storage // operation and it's based on actual execution time), plus the same cost // multiplied by an arbitrary factor that represents the higher cost of storage // space as a resource. This way, the storage occupation cost is not completely // free-floating but it's tied to the other costs -const STORAGE_OCCUPATION_GAS_PER_BYTE: u64 = - PHYSICAL_STORAGE_LATENCY_PER_BYTE * (1 + 10); +const STORAGE_OCCUPATION_GAS_PER_BYTE_RAW: u64 = + PHYSICAL_STORAGE_LATENCY_PER_BYTE_RAW * (1 + 10); // NOTE: this accounts for the latency of a physical drive access. For read // accesses we have no way to tell if data was in cache or in storage. Moreover, // the latency shouldn't really be accounted per single byte but rather per // storage blob but this would make it more tedious to compute gas in the // codebase. For these two reasons we just set an arbitrary value (based on // actual SSDs latency) per byte here -const PHYSICAL_STORAGE_LATENCY_PER_BYTE: u64 = 1_000_000; +const PHYSICAL_STORAGE_LATENCY_PER_BYTE_RAW: u64 = 20; // This is based on the global average bandwidth -const NETWORK_TRANSMISSION_GAS_PER_BYTE: u64 = 848; - +const NETWORK_TRANSMISSION_GAS_PER_BYTE_RAW: u64 = 848; + +// The cost of accessing data from memory (both read and write mode), per byte +const MEMORY_ACCESS_GAS_PER_BYTE_RAW: u64 = 39; +// The cost of accessing data from storage, per byte +const STORAGE_ACCESS_GAS_PER_BYTE_RAW: u64 = + 93 + PHYSICAL_STORAGE_LATENCY_PER_BYTE_RAW; +// The cost of writing data to storage, per byte +const STORAGE_WRITE_GAS_PER_BYTE_RAW: u64 = MEMORY_ACCESS_GAS_PER_BYTE_RAW + + 17_583 + + STORAGE_OCCUPATION_GAS_PER_BYTE_RAW; +// The cost of removing data from storage, per byte +const STORAGE_DELETE_GAS_PER_BYTE_RAW: u64 = MEMORY_ACCESS_GAS_PER_BYTE_RAW + + 17_583 + + PHYSICAL_STORAGE_LATENCY_PER_BYTE_RAW; +// The cost of verifying a single signature of a transaction +const VERIFY_TX_SIG_GAS_RAW: u64 = 435_190; +// The cost for requesting one more page in wasm (64KiB) +const WASM_MEMORY_PAGE_GAS_RAW: u64 = + MEMORY_ACCESS_GAS_PER_BYTE_RAW * 64 * 1_024; +// The cost to validate an Ibc action +const IBC_ACTION_VALIDATE_GAS_RAW: u64 = 290_935; +// The cost to execute an Ibc action +const IBC_ACTION_EXECUTE_GAS_RAW: u64 = 1_685_733; +// The cost of masp sig verification +const MASP_VERIFY_SIG_GAS_RAW: u64 = 1_908_750; +// The fixed cost of spend note verification +const MASP_FIXED_SPEND_GAS_RAW: u64 = 59_521_000; +// The variable cost of spend note verification +const MASP_VARIABLE_SPEND_GAS_RAW: u64 = 9_849_000; +// The fixed cost of convert note verification +const MASP_FIXED_CONVERT_GAS_RAW: u64 = 46_197_000; +// The variable cost of convert note verification +const MASP_VARIABLE_CONVERT_GAS_RAW: u64 = 10_245_000; +// The fixed cost of output note verification +const MASP_FIXED_OUTPUT_GAS_RAW: u64 = 53_439_000; +// The variable cost of output note verification +const MASP_VARIABLE_OUTPUT_GAS_RAW: u64 = 9_710_000; +// The cost to process a masp spend note in the bundle +const MASP_SPEND_CHECK_GAS_RAW: u64 = 405_070; +// The cost to process a masp convert note in the bundle +const MASP_CONVERT_CHECK_GAS_RAW: u64 = 188_590; +// The cost to process a masp output note in the bundle +const MASP_OUTPUT_CHECK_GAS_RAW: u64 = 204_430; +// The cost to run the final masp check in the bundle +const MASP_FINAL_CHECK_GAS_RAW: u64 = 43; +// ============================================================================= + +// A correction factor for non-WASM-opcodes costs. We can see that the +// gas cost we get for wasm codes (txs and vps) is much greater than what we +// would expect from the benchmarks. This is likely due to some imperfections in +// the injection tool but, most importantly, to the fact that the code we end up +// executing is an optimized version of the one we instrument. Therefore we +// provide this factor to correct the costs of non-WASM gas based on the avarage +// speedup we can observe. NOTE: we should really reduce the gas costs of WASM +// opcodes instead of increasing the gas costs of non-WASM gas, but the former +// would involve some complicated adjustments for host function calls so we +// prefer to go with the latter. +const GAS_COST_CORRECTION: u64 = 5; + +// ADJUSTED GAS COSTS +// ============================================================================= +// The gas costs adjusted for the correction factor. +// + +// The compilation cost is reduced by a factor to compensate for the (most +// likely) presence of the cache +const COMPILE_GAS_PER_BYTE: u64 = + COMPILE_GAS_PER_BYTE_RAW * GAS_COST_CORRECTION / 100; +const WASM_CODE_VALIDATION_GAS_PER_BYTE: u64 = + WASM_CODE_VALIDATION_GAS_PER_BYTE_RAW * GAS_COST_CORRECTION; +const WRAPPER_TX_VALIDATION_GAS: u64 = + WRAPPER_TX_VALIDATION_GAS_RAW * GAS_COST_CORRECTION; +const STORAGE_OCCUPATION_GAS_PER_BYTE: u64 = + STORAGE_OCCUPATION_GAS_PER_BYTE_RAW * GAS_COST_CORRECTION; +const NETWORK_TRANSMISSION_GAS_PER_BYTE: u64 = + NETWORK_TRANSMISSION_GAS_PER_BYTE_RAW * GAS_COST_CORRECTION; /// The cost of accessing data from memory (both read and write mode), per byte -pub const MEMORY_ACCESS_GAS_PER_BYTE: u64 = 104; +pub const MEMORY_ACCESS_GAS_PER_BYTE: u64 = + MEMORY_ACCESS_GAS_PER_BYTE_RAW * GAS_COST_CORRECTION; /// The cost of accessing data from storage, per byte pub const STORAGE_ACCESS_GAS_PER_BYTE: u64 = - 163 + PHYSICAL_STORAGE_LATENCY_PER_BYTE; + STORAGE_ACCESS_GAS_PER_BYTE_RAW * GAS_COST_CORRECTION; /// The cost of writing data to storage, per byte pub const STORAGE_WRITE_GAS_PER_BYTE: u64 = - MEMORY_ACCESS_GAS_PER_BYTE + 69_634 + STORAGE_OCCUPATION_GAS_PER_BYTE; + STORAGE_WRITE_GAS_PER_BYTE_RAW * GAS_COST_CORRECTION; /// The cost of removing data from storage, per byte pub const STORAGE_DELETE_GAS_PER_BYTE: u64 = - MEMORY_ACCESS_GAS_PER_BYTE + 69_634 + PHYSICAL_STORAGE_LATENCY_PER_BYTE; + STORAGE_DELETE_GAS_PER_BYTE_RAW * GAS_COST_CORRECTION; /// The cost of verifying a single signature of a transaction -pub const VERIFY_TX_SIG_GAS: u64 = 594_290; +pub const VERIFY_TX_SIG_GAS: u64 = VERIFY_TX_SIG_GAS_RAW * GAS_COST_CORRECTION; /// The cost for requesting one more page in wasm (64KiB) #[allow(clippy::cast_possible_truncation)] // const in u32 range pub const WASM_MEMORY_PAGE_GAS: u32 = - MEMORY_ACCESS_GAS_PER_BYTE as u32 * 64 * 1_024; + (WASM_MEMORY_PAGE_GAS_RAW * GAS_COST_CORRECTION) as u32; /// The cost to validate an Ibc action -pub const IBC_ACTION_VALIDATE_GAS: u64 = 1_472_023; +pub const IBC_ACTION_VALIDATE_GAS: u64 = + IBC_ACTION_VALIDATE_GAS_RAW * GAS_COST_CORRECTION; /// The cost to execute an Ibc action -pub const IBC_ACTION_EXECUTE_GAS: u64 = 3_678_745; +pub const IBC_ACTION_EXECUTE_GAS: u64 = + IBC_ACTION_EXECUTE_GAS_RAW * GAS_COST_CORRECTION; /// The cost of masp sig verification -pub const MASP_VERIFY_SIG_GAS: u64 = 5_443_000; +pub const MASP_VERIFY_SIG_GAS: u64 = + MASP_VERIFY_SIG_GAS_RAW * GAS_COST_CORRECTION; /// The fixed cost of spend note verification -pub const MASP_FIXED_SPEND_GAS: u64 = 87_866_000; +pub const MASP_FIXED_SPEND_GAS: u64 = + MASP_FIXED_SPEND_GAS_RAW * GAS_COST_CORRECTION; /// The variable cost of spend note verification -pub const MASP_VARIABLE_SPEND_GAS: u64 = 14_384_000; +pub const MASP_VARIABLE_SPEND_GAS: u64 = + MASP_VARIABLE_SPEND_GAS_RAW * GAS_COST_CORRECTION; /// The fixed cost of convert note verification -pub const MASP_FIXED_CONVERT_GAS: u64 = 70_308_000; +pub const MASP_FIXED_CONVERT_GAS: u64 = + MASP_FIXED_CONVERT_GAS_RAW * GAS_COST_CORRECTION; /// The variable cost of convert note verification -pub const MASP_VARIABLE_CONVERT_GAS: u64 = 12_664_000; +pub const MASP_VARIABLE_CONVERT_GAS: u64 = + MASP_VARIABLE_CONVERT_GAS_RAW * GAS_COST_CORRECTION; /// The fixed cost of output note verification -pub const MASP_FIXED_OUTPUT_GAS: u64 = 78_203_000; +pub const MASP_FIXED_OUTPUT_GAS: u64 = + MASP_FIXED_OUTPUT_GAS_RAW * GAS_COST_CORRECTION; /// The variable cost of output note verification -pub const MASP_VARIABLE_OUTPUT_GAS: u64 = 14_586_000; +pub const MASP_VARIABLE_OUTPUT_GAS: u64 = + MASP_VARIABLE_OUTPUT_GAS_RAW * GAS_COST_CORRECTION; /// The cost to process a masp spend note in the bundle -pub const MASP_SPEND_CHECK_GAS: u64 = 479_730; +pub const MASP_SPEND_CHECK_GAS: u64 = + MASP_SPEND_CHECK_GAS_RAW * GAS_COST_CORRECTION; /// The cost to process a masp convert note in the bundle -pub const MASP_CONVERT_CHECK_GAS: u64 = 173_570; +pub const MASP_CONVERT_CHECK_GAS: u64 = + MASP_CONVERT_CHECK_GAS_RAW * GAS_COST_CORRECTION; /// The cost to process a masp output note in the bundle -pub const MASP_OUTPUT_CHECK_GAS: u64 = 310_260; +pub const MASP_OUTPUT_CHECK_GAS: u64 = + MASP_OUTPUT_CHECK_GAS_RAW * GAS_COST_CORRECTION; /// The cost to run the final masp check in the bundle -pub const MASP_FINAL_CHECK_GAS: u64 = 44; -/// Gas divider specific for the masp vp. Only allocates half of the cores to -/// the masp vp since we can expect the other half to be busy with other vps -pub const MASP_PARALLEL_GAS_DIVIDER: u64 = PARALLEL_GAS_DIVIDER / 2; +pub const MASP_FINAL_CHECK_GAS: u64 = + MASP_FINAL_CHECK_GAS_RAW * GAS_COST_CORRECTION; +// ============================================================================= /// Gas module result for functions that may fail pub type Result = std::result::Result; @@ -282,6 +372,20 @@ pub trait GasMetering { /// Get the gas limit fn get_gas_limit(&self) -> Gas; + + /// Check if the vps went out of gas. Starts with the gas consumed by the + /// transaction. + fn check_vps_limit(&self, vps_gas: Gas) -> Result<()> { + let total = self + .get_tx_consumed_gas() + .checked_add(vps_gas) + .ok_or(Error::GasOverflow)?; + if total > self.get_gas_limit() { + return Err(Error::TransactionGasExceededError); + } + + Ok(()) + } } /// Gas metering in a transaction @@ -307,23 +411,6 @@ pub struct VpGasMeter { current_gas: Gas, } -/// Gas meter for VPs parallel runs -#[derive( - Clone, - Debug, - Default, - BorshSerialize, - BorshDeserialize, - BorshDeserializer, - BorshSchema, - Serialize, - Deserialize, -)] -pub struct VpsGas { - max: Gas, - rest: Vec, -} - impl GasMetering for TxGasMeter { fn consume(&mut self, gas: u64) -> Result<()> { if self.gas_overflow { @@ -391,11 +478,6 @@ impl TxGasMeter { ) } - /// Add the gas cost used in validity predicates to the current transaction. - pub fn add_vps_gas(&mut self, vps_gas: &VpsGas) -> Result<()> { - self.consume(vps_gas.get_current_gas()?.into()) - } - /// Get the amount of gas still available to the transaction pub fn get_available_gas(&self) -> Gas { self.tx_gas_limit @@ -470,64 +552,10 @@ impl VpGasMeter { current_gas: Gas::default(), } } -} - -impl VpsGas { - /// Set the gas cost from a VP run. It consumes the [`VpGasMeter`] - /// instance which shouldn't be accessed passed this point. - pub fn set(&mut self, vp_gas_meter: VpGasMeter) -> Result<()> { - if vp_gas_meter.current_gas > self.max { - self.rest.push(self.max); - self.max = vp_gas_meter.current_gas; - } else { - self.rest.push(vp_gas_meter.current_gas); - } - - self.check_limit(&vp_gas_meter) - } - - /// Merge validity predicates gas meters from parallelized runs. Consumes - /// the other `VpsGas` instance which shouldn't be used passed this point. - pub fn merge( - &mut self, - mut other: VpsGas, - tx_gas_meter: &TxGasMeter, - ) -> Result<()> { - if self.max < other.max { - self.rest.push(self.max); - self.max = other.max; - } else { - self.rest.push(other.max); - } - self.rest.append(&mut other.rest); - - self.check_limit(tx_gas_meter) - } - - /// Check if the vp went out of gas. Starts from the gas consumed by the - /// transaction. - fn check_limit(&self, gas_meter: &impl GasMetering) -> Result<()> { - let total = gas_meter - .get_tx_consumed_gas() - .checked_add(self.get_current_gas()?) - .ok_or(Error::GasOverflow)?; - if total > gas_meter.get_gas_limit() { - return Err(Error::TransactionGasExceededError); - } - Ok(()) - } - /// Get the gas consumed by the parallelized VPs - fn get_current_gas(&self) -> Result { - let parallel_gas = self - .rest - .iter() - .try_fold(Gas::default(), |acc, gas| { - acc.checked_add(*gas).ok_or(Error::GasOverflow) - })? - .checked_div(PARALLEL_GAS_DIVIDER) - .expect("Div by non-zero int cannot fail"); - self.max.checked_add(parallel_gas).ok_or(Error::GasOverflow) + /// Get the gas consumed by the VP alone + pub fn get_vp_consumed_gas(&self) -> Gas { + self.current_gas } } diff --git a/crates/governance/src/cli/onchain.rs b/crates/governance/src/cli/onchain.rs index f904ef0094..5186009b48 100644 --- a/crates/governance/src/cli/onchain.rs +++ b/crates/governance/src/cli/onchain.rs @@ -71,17 +71,12 @@ impl DefaultProposal { if force { return Ok(self); } - is_valid_start_epoch( - self.proposal.voting_start_epoch, - current_epoch, - governance_parameters.min_proposal_voting_period, - )?; + is_valid_start_epoch(self.proposal.voting_start_epoch, current_epoch)?; is_valid_end_epoch( self.proposal.voting_start_epoch, self.proposal.voting_end_epoch, current_epoch, governance_parameters.min_proposal_voting_period, - governance_parameters.min_proposal_voting_period, governance_parameters.max_proposal_period, )?; is_valid_activation_epoch( @@ -149,17 +144,12 @@ impl PgfStewardProposal { if force { return Ok(self); } - is_valid_start_epoch( - self.proposal.voting_start_epoch, - current_epoch, - governance_parameters.min_proposal_voting_period, - )?; + is_valid_start_epoch(self.proposal.voting_start_epoch, current_epoch)?; is_valid_end_epoch( self.proposal.voting_start_epoch, self.proposal.voting_end_epoch, current_epoch, governance_parameters.min_proposal_voting_period, - governance_parameters.min_proposal_voting_period, governance_parameters.max_proposal_period, )?; is_valid_activation_epoch( @@ -222,17 +212,12 @@ impl PgfFundingProposal { if force { return Ok(self); } - is_valid_start_epoch( - self.proposal.voting_start_epoch, - current_epoch, - governance_parameters.min_proposal_voting_period, - )?; + is_valid_start_epoch(self.proposal.voting_start_epoch, current_epoch)?; is_valid_end_epoch( self.proposal.voting_start_epoch, self.proposal.voting_end_epoch, current_epoch, governance_parameters.min_proposal_voting_period, - governance_parameters.min_proposal_voting_period, governance_parameters.max_proposal_period, )?; is_valid_activation_epoch( diff --git a/crates/governance/src/cli/validation.rs b/crates/governance/src/cli/validation.rs index 90982a6077..37c8707fa8 100644 --- a/crates/governance/src/cli/validation.rs +++ b/crates/governance/src/cli/validation.rs @@ -17,14 +17,13 @@ pub enum ProposalValidation { /// The proposal start epoch is invalid #[error( "Invalid proposal start epoch: {0} must be greater than current epoch \ - {1} and a multiple of {2}" + {1}" )] - InvalidStartEpoch(Epoch, Epoch, u64), + InvalidStartEpoch(Epoch, Epoch), /// The proposal difference between start and end epoch is invalid #[error( "Invalid proposal end epoch: difference between proposal start and \ - end epoch must be at least {0}, at max {1} and the end epoch must be \ - a multiple of {0}" + end epoch must be at least {0}, at max {1}" )] InvalidStartEndDifference(u64, u64), /// The proposal difference between end and activation epoch is invalid @@ -85,19 +84,15 @@ pub fn is_valid_author_balance( pub fn is_valid_start_epoch( proposal_start_epoch: Epoch, current_epoch: Epoch, - proposal_epoch_multiplier: u64, ) -> Result<(), ProposalValidation> { let start_epoch_greater_than_current = proposal_start_epoch > current_epoch; - let start_epoch_is_multipler = - checked!(proposal_start_epoch.0 % proposal_epoch_multiplier)? == 0; - if start_epoch_greater_than_current && start_epoch_is_multipler { + if start_epoch_greater_than_current { Ok(()) } else { Err(ProposalValidation::InvalidStartEpoch( proposal_start_epoch, current_epoch, - proposal_epoch_multiplier, )) } } @@ -106,21 +101,16 @@ pub fn is_valid_end_epoch( proposal_start_epoch: Epoch, proposal_end_epoch: Epoch, _current_epoch: Epoch, - proposal_epoch_multiplier: u64, min_proposal_voting_period: u64, max_proposal_period: u64, ) -> Result<(), ProposalValidation> { let voting_period = checked!(proposal_end_epoch.0 - proposal_start_epoch.0)?; - let end_epoch_is_multipler = - checked!(proposal_end_epoch % proposal_epoch_multiplier) - .map_err(ProposalValidation::Arith)? - == Epoch(0); let is_valid_voting_period = voting_period > 0 && voting_period >= min_proposal_voting_period && min_proposal_voting_period <= max_proposal_period; - if end_epoch_is_multipler && is_valid_voting_period { + if is_valid_voting_period { Ok(()) } else { Err(ProposalValidation::InvalidStartEndDifference( diff --git a/crates/governance/src/storage/mod.rs b/crates/governance/src/storage/mod.rs index 50ac876dc8..fea46850ec 100644 --- a/crates/governance/src/storage/mod.rs +++ b/crates/governance/src/storage/mod.rs @@ -12,6 +12,7 @@ use std::collections::{BTreeMap, BTreeSet}; use namada_core::address::Address; use namada_core::borsh::BorshDeserialize; use namada_core::collections::HashSet; +use namada_core::hash::Hash; use namada_core::storage::Epoch; use namada_core::token; use namada_state::{ @@ -169,7 +170,21 @@ where let proposal_type: Option = storage.read(&proposal_type_key)?; - let proposal = proposal_type.map(|proposal_type| StorageProposal { + let proposal_type = if let Some(proposal_type) = proposal_type { + if let ProposalType::DefaultWithWasm(_) = proposal_type { + let proposal_code_key = governance_keys::get_proposal_code_key(id); + let proposal_code: Vec = + storage.read(&proposal_code_key)?.unwrap_or_default(); + let proposal_code_hash = Hash::sha256(proposal_code); + ProposalType::DefaultWithWasm(proposal_code_hash) + } else { + proposal_type + } + } else { + return Ok(None); + }; + + Ok(Some(StorageProposal { id, content: content.unwrap(), author: author.unwrap(), @@ -177,9 +192,7 @@ where voting_start_epoch: voting_start_epoch.unwrap(), voting_end_epoch: voting_end_epoch.unwrap(), activation_epoch: activation_epoch.unwrap(), - }); - - Ok(proposal) + })) } /// Query all the votes for a proposal_id diff --git a/crates/governance/src/vp/mod.rs b/crates/governance/src/vp/mod.rs index 5c660b85da..26d105ef34 100644 --- a/crates/governance/src/vp/mod.rs +++ b/crates/governance/src/vp/mod.rs @@ -1366,7 +1366,7 @@ mod test { .write_log_mut() .write(&balance_key, amount.serialize_to_vec()) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); } #[cfg(test)] @@ -1612,7 +1612,7 @@ mod test { Ok(_) ); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().unwrap(); let governance_balance_key = balance_key(&nam(), &ADDRESS); @@ -2330,7 +2330,7 @@ mod test { Ok(_) ); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().unwrap(); let height = state.in_mem().get_block_height().0 + (7 * 2); @@ -2459,7 +2459,7 @@ mod test { Ok(_) ); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().unwrap(); let height = state.in_mem().get_block_height().0 + (7 * 2); @@ -2588,7 +2588,7 @@ mod test { Ok(_) ); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().unwrap(); let height = state.in_mem().get_block_height().0 + (7 * 2); @@ -2717,7 +2717,7 @@ mod test { Ok(_) ); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().unwrap(); let height = state.in_mem().get_block_height().0 + (9 * 2); @@ -2863,7 +2863,7 @@ mod test { Ok(_) ); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().unwrap(); let height = state.in_mem().get_block_height().0 + (10 * 2); @@ -3009,7 +3009,7 @@ mod test { Ok(_) ); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().unwrap(); let height = state.in_mem().get_block_height().0 + (10 * 2); diff --git a/crates/ibc/src/context/validation.rs b/crates/ibc/src/context/validation.rs index be9aad20d5..0f00feefcf 100644 --- a/crates/ibc/src/context/validation.rs +++ b/crates/ibc/src/context/validation.rs @@ -34,8 +34,6 @@ use super::common::IbcCommonContext; use super::IbcContext; use crate::storage; -const COMMITMENT_PREFIX: &[u8] = b"ibc"; - impl ExtClientValidationContext for IbcContext where C: IbcCommonContext, @@ -193,8 +191,7 @@ where } fn commitment_prefix(&self) -> CommitmentPrefix { - CommitmentPrefix::try_from(COMMITMENT_PREFIX.to_vec()) - .expect("the prefix should be parsable") + CommitmentPrefix::from(crate::COMMITMENT_PREFIX.as_bytes().to_vec()) } fn connection_counter(&self) -> Result { diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index e9e5ae81c3..293b6d48ad 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -101,7 +101,11 @@ pub use nft::*; use primitives::Timestamp; use prost::Message; use thiserror::Error; -use trace::{convert_to_address, ibc_trace_for_nft, is_sender_chain_source}; +use trace::{ + convert_to_address, ibc_trace_for_nft, + is_receiver_chain_source as is_receiver_chain_source_str, + is_sender_chain_source, +}; use crate::storage::{ channel_counter_key, client_counter_key, connection_counter_key, @@ -114,6 +118,8 @@ pub const EVENT_TYPE_PACKET: &str = "fungible_token_packet"; pub const EVENT_TYPE_NFT_PACKET: &str = "non_fungible_token_packet"; /// The escrow address for IBC transfer pub const IBC_ESCROW_ADDRESS: Address = address::IBC; +/// The commitment prefix for the ICS23 commitment proof +pub const COMMITMENT_PREFIX: &str = "ibc"; #[allow(missing_docs)] #[derive(Error, Debug)] @@ -387,6 +393,7 @@ where Ok(()) } +// Check that the packet receipt key has been changed fn check_packet_receiving( msg: &IbcMsgRecvPacket, keys_changed: &BTreeSet, @@ -398,7 +405,7 @@ fn check_packet_receiving( ); if !keys_changed.contains(&receipt_key) { return Err(namada_storage::Error::new_alloc(format!( - "The packet has not been received: Port ID {}, Channel ID {}, \ + "The packet has not been received: Port ID {}, Channel ID {}, \ Sequence {}", msg.packet.port_id_on_b, msg.packet.chan_id_on_b, @@ -434,7 +441,7 @@ where let token = convert_to_address(ibc_trace).into_storage_result()?; let delta = ValueSum::from_pair(token, *amount); // If there is a transfer to the IBC account, then deduplicate the - // balance increase since we already accounted for it above + // balance increase since we already account for it below if is_sender_chain_source(ibc_trace, src_port_id, src_channel_id) { let ibc_taddr = addr_taddr(address::IBC); let post_entry = accum @@ -475,7 +482,8 @@ where S: StorageRead, { // Ensure that the event corresponds to the current changes to storage - let ack_key = storage::ack_key(dst_port_id, dst_channel_id, sequence); // If the receive is a success, then the commitment is unique + let ack_key = storage::ack_key(dst_port_id, dst_channel_id, sequence); + // If the receive is a success, then the commitment is unique let succ_ack_commitment = compute_ack_commitment( &AcknowledgementStatus::success(ack_success_b64()).into(), ); @@ -501,8 +509,8 @@ fn apply_recv_msg( where S: StorageRead, { + // First check that the packet receipt is reflecteed in the state changes check_packet_receiving(msg, keys_changed)?; - // If the transfer was a failure, then enable funds to // be withdrawn from the IBC internal address if is_receiving_success( @@ -512,31 +520,41 @@ where msg.packet.seq_on_a, )? { for ibc_trace in ibc_traces { - // Get the received token - let token = received_ibc_token( - ibc_trace, + // Only artificially increase the IBC internal address pre-balance + // if receiving involves minting. We do not do this in the unescrow + // case since the pre-balance already accounts for the amount being + // received. + if !is_receiver_chain_source_str( + &ibc_trace, &msg.packet.port_id_on_a, &msg.packet.chan_id_on_a, - &msg.packet.port_id_on_b, - &msg.packet.chan_id_on_b, - ) - .into_storage_result()?; - let delta = ValueSum::from_pair(token.clone(), amount); - // Enable funds to be taken from the IBC internal - // address and be deposited elsewhere - // Required for the IBC internal Address to release - // funds - let ibc_taddr = addr_taddr(address::IBC); - let pre_entry = accum - .pre - .get(&ibc_taddr) - .cloned() - .unwrap_or(ValueSum::zero()); - accum.pre.insert( - ibc_taddr, - checked!(pre_entry + &delta) - .map_err(namada_storage::Error::new)?, - ); + ) { + // Get the received token + let token = received_ibc_token( + ibc_trace, + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + &msg.packet.port_id_on_b, + &msg.packet.chan_id_on_b, + ) + .into_storage_result()?; + let delta = ValueSum::from_pair(token.clone(), amount); + // Enable funds to be taken from the IBC internal + // address and be deposited elsewhere + // Required for the IBC internal Address to release + // funds + let ibc_taddr = addr_taddr(address::IBC); + let pre_entry = accum + .pre + .get(&ibc_taddr) + .cloned() + .unwrap_or(ValueSum::zero()); + accum.pre.insert( + ibc_taddr, + checked!(pre_entry + &delta) + .map_err(namada_storage::Error::new)?, + ); + } } } Ok(accum) diff --git a/crates/ibc/src/storage.rs b/crates/ibc/src/storage.rs index d0ff4febd5..6909ae99ec 100644 --- a/crates/ibc/src/storage.rs +++ b/crates/ibc/src/storage.rs @@ -10,7 +10,8 @@ use ibc::core::host::types::identifiers::{ use ibc::core::host::types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, ClientConsensusStatePath, ClientStatePath, CommitmentPath, ConnectionPath, Path, PortPath, - ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, + ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, UpgradeClientStatePath, + UpgradeConsensusStatePath, }; use namada_core::address::{Address, InternalAddress}; use namada_core::storage::{DbKeySeg, Key, KeySeg}; @@ -186,6 +187,29 @@ pub fn consensus_state_prefix(client_id: &ClientId) -> Key { .expect("Creating a key prefix of the consensus state shouldn't fail") } +/// Returns a key for the upgraded client state +pub fn upgraded_client_state_key(upgraded_height: Height) -> Key { + let path = Path::UpgradeClientState( + UpgradeClientStatePath::new_with_default_path( + upgraded_height.revision_height(), + ), + ); + ibc_key(path.to_string()) + .expect("Creating a key for the upgraded client state shouldn't fail") +} + +/// Returns a key for the upgraded consensus state +pub fn upgraded_consensus_state_key(upgraded_height: Height) -> Key { + let path = Path::UpgradeConsensusState( + UpgradeConsensusStatePath::new_with_default_path( + upgraded_height.revision_height(), + ), + ); + ibc_key(path.to_string()).expect( + "Creating a key for the upgraded consensus state shouldn't fail", + ) +} + /// Returns a key for the connection end pub fn connection_key(conn_id: &ConnectionId) -> Key { let path = Path::Connection(ConnectionPath(conn_id.clone())); diff --git a/crates/ibc/src/trace.rs b/crates/ibc/src/trace.rs index 6bb9d3bea8..bceff94fcb 100644 --- a/crates/ibc/src/trace.rs +++ b/crates/ibc/src/trace.rs @@ -108,13 +108,24 @@ pub fn is_nft_trace( } } -/// Return true if the source of the given IBC trace is this chain +/// Returns true if the denomination originally came from the sender chain, and +/// false otherwise. pub fn is_sender_chain_source( trace: impl AsRef, src_port_id: &PortId, src_channel_id: &ChannelId, ) -> bool { - !trace + !is_receiver_chain_source(trace, src_port_id, src_channel_id) +} + +/// Returns true if the denomination originally came from the receiving chain, +/// and false otherwise. +pub fn is_receiver_chain_source( + trace: impl AsRef, + src_port_id: &PortId, + src_channel_id: &ChannelId, +) -> bool { + trace .as_ref() .starts_with(&format!("{src_port_id}/{src_channel_id}")) } diff --git a/crates/ibc/src/vp/mod.rs b/crates/ibc/src/vp/mod.rs index 88f657636e..45d8a38cfc 100644 --- a/crates/ibc/src/vp/mod.rs +++ b/crates/ibc/src/vp/mod.rs @@ -30,6 +30,7 @@ use namada_vp::VpEnv; use thiserror::Error; use crate::core::host::types::identifiers::ChainId as IbcChainId; +use crate::core::host::types::path::UPGRADED_IBC_STATE; use crate::event::IbcEvent; use crate::storage::{ deposit_key, get_limits, is_ibc_key, is_ibc_trace_key, mint_amount_key, @@ -38,7 +39,7 @@ use crate::storage::{ use crate::trace::calc_hash; use crate::{ Error as ActionError, IbcActions, NftTransferModule, TransferModule, - ValidationParams, + ValidationParams, COMMITMENT_PREFIX, }; #[allow(missing_docs)] @@ -340,7 +341,10 @@ where .try_into() .expect("Converting the proof specs shouldn't fail"), unbonding_period: Duration::from_secs(unbonding_period_secs), - upgrade_path: Vec::new(), + upgrade_path: vec![ + COMMITMENT_PREFIX.to_string(), + UPGRADED_IBC_STATE.to_string(), + ], }) } @@ -625,7 +629,6 @@ mod tests { >; const ADDRESS: Address = Address::Internal(InternalAddress::Ibc); - const COMMITMENT_PREFIX: &[u8] = b"ibc"; const TX_GAS_LIMIT: u64 = 10_000_000_000; fn get_client_id() -> ClientId { @@ -721,7 +724,7 @@ mod tests { .write_log_mut() .write(&client_update_height_key, host_height.encode_vec()) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); } fn get_connection_id() -> ConnectionId { @@ -756,8 +759,7 @@ mod tests { ClientId::new(&client_type().to_string(), 22).unwrap(); let counterpart_conn_id = ConnectionId::new(32); let commitment_prefix = - CommitmentPrefix::try_from(COMMITMENT_PREFIX.to_vec()) - .expect("the prefix should be parsable"); + CommitmentPrefix::from(COMMITMENT_PREFIX.as_bytes().to_vec()); ConnCounterparty::new( counterpart_client_id, Some(counterpart_conn_id), @@ -1146,7 +1148,7 @@ mod tests { let mut keys_changed = BTreeSet::new(); let mut state = init_storage(); insert_init_client(&mut state); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block @@ -1270,7 +1272,7 @@ mod tests { let mut keys_changed = BTreeSet::new(); let mut state = init_storage(); insert_init_client(&mut state); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -1473,7 +1475,7 @@ mod tests { let mut keys_changed = BTreeSet::new(); let mut state = init_storage(); insert_init_client(&mut state); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -1602,7 +1604,7 @@ mod tests { .write_log_mut() .write(&conn_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -1711,7 +1713,7 @@ mod tests { .write_log_mut() .write(&conn_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -1807,7 +1809,7 @@ mod tests { .write_log_mut() .write(&conn_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -1929,7 +1931,7 @@ mod tests { .write_log_mut() .write(&conn_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -2059,7 +2061,7 @@ mod tests { .write_log_mut() .write(&channel_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -2166,7 +2168,7 @@ mod tests { .write_log_mut() .write(&channel_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -2279,7 +2281,7 @@ mod tests { .write_log_mut() .write(&balance_key, amount.serialize_to_vec()) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -2424,7 +2426,7 @@ mod tests { .write_log_mut() .write(&channel_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -2669,7 +2671,7 @@ mod tests { .write_log_mut() .write(&commitment_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -2832,7 +2834,7 @@ mod tests { .write_log_mut() .write(&commitment_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -2989,7 +2991,7 @@ mod tests { .write_log_mut() .write(&commitment_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -3131,7 +3133,7 @@ mod tests { .write(&metadata_key, metadata.serialize_to_vec()) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state @@ -3283,7 +3285,7 @@ mod tests { .write_log_mut() .write(&channel_key, bytes) .expect("write failed"); - state.write_log_mut().commit_batch(); + state.write_log_mut().commit_batch_and_current_tx(); state.commit_block().expect("commit failed"); // for next block state diff --git a/crates/node/src/bench_utils.rs b/crates/node/src/bench_utils.rs index 026e2b2362..e552d2a892 100644 --- a/crates/node/src/bench_utils.rs +++ b/crates/node/src/bench_utils.rs @@ -67,7 +67,7 @@ use namada_sdk::ibc::primitives::Timestamp as IbcTimestamp; use namada_sdk::ibc::storage::{ channel_key, connection_key, mint_limit_key, port_key, throughput_limit_key, }; -use namada_sdk::ibc::MsgTransfer; +use namada_sdk::ibc::{MsgTransfer, COMMITMENT_PREFIX}; use namada_sdk::io::StdIo; use namada_sdk::key::common::SecretKey; use namada_sdk::masp::utils::RetryStrategy; @@ -387,7 +387,7 @@ impl BenchShellInner { Counterparty::new( client_id.clone(), Some(ConnectionId::new(1)), - CommitmentPrefix::try_from(b"ibc".to_vec()).unwrap(), + CommitmentPrefix::from(COMMITMENT_PREFIX.as_bytes().to_vec()), ), Version::compatibles(), std::time::Duration::new(100, 0), @@ -1103,12 +1103,14 @@ impl Default for BenchShieldedCtx { chain_ctx.wallet.gen_store_spending_key( ALBERT_SPENDING_KEY.to_string(), None, + None, true, &mut OsRng, ); chain_ctx.wallet.gen_store_spending_key( BERTHA_SPENDING_KEY.to_string(), None, + None, true, &mut OsRng, ); @@ -1126,6 +1128,7 @@ impl Default for BenchShieldedCtx { .wallet .find_viewing_key(viewing_alias) .unwrap() + .key .to_string(), ); let viewing_key = ExtendedFullViewingKey::from( diff --git a/crates/node/src/ethereum_oracle/events.rs b/crates/node/src/ethereum_oracle/events.rs index a081c106e2..46fa60e3a7 100644 --- a/crates/node/src/ethereum_oracle/events.rs +++ b/crates/node/src/ethereum_oracle/events.rs @@ -43,7 +43,7 @@ pub mod eth_events { impl PendingEvent { /// Decodes bytes into an [`EthereumEvent`] based on the signature. - /// This is is turned into a [`PendingEvent`] along with the block + /// This is turned into a [`PendingEvent`] along with the block /// height passed in here. /// /// If the event contains a confirmations field, diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index a7c0e73b0a..ff756f5fa3 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -51,7 +51,6 @@ use once_cell::unsync::Lazy; use sysinfo::{RefreshKind, System, SystemExt}; use tokio::sync::mpsc; use tokio::task; -use tower::ServiceBuilder; use self::abortable::AbortableSpawner; use self::ethereum_oracle::last_processed_block; @@ -523,8 +522,7 @@ async fn run_aux_setup( wasm_dir: &PathBuf, scheduled_migration: Option, ) -> RunAuxSetup { - // Prefetch needed wasm artifacts - wasm_loader::pre_fetch_wasm(wasm_dir).await; + wasm_loader::validate_wasm_artifacts(wasm_dir).await; // Find the system available memory let available_memory_bytes = Lazy::new(|| { @@ -746,13 +744,7 @@ async fn run_abci( .consensus(consensus) .snapshot(snapshot) .mempool(mempool) // don't load_shed, it will make CometBFT crash - .info( - ServiceBuilder::new() - .load_shed() - .buffer(100) - .rate_limit(50, std::time::Duration::from_secs(1)) - .service(info), - ) + .info(info) // don't load_shed, it will make tower-abci crash .finish() .unwrap(); tokio::select! { diff --git a/crates/node/src/protocol.rs b/crates/node/src/protocol.rs index 5e961af1c5..46a3e69307 100644 --- a/crates/node/src/protocol.rs +++ b/crates/node/src/protocol.rs @@ -11,7 +11,7 @@ use namada_sdk::events::extend::{ ComposeEvent, Height as HeightAttr, TxHash as TxHashAttr, UserAccount, }; use namada_sdk::events::EventLevel; -use namada_sdk::gas::{Gas, GasMetering, TxGasMeter, VpGasMeter}; +use namada_sdk::gas::{self, Gas, GasMetering, TxGasMeter, VpGasMeter}; use namada_sdk::hash::Hash; use namada_sdk::ibc::{IbcTxDataHash, IbcTxDataRefs}; use namada_sdk::masp::{MaspTxRefs, TxId}; @@ -405,7 +405,13 @@ where let actions = state.read_actions().map_err(Error::StateError)?; if let Some(masp_section_ref) = - action::get_masp_section_ref(&actions) + action::get_masp_section_ref(&actions).map_err( + |msg| { + Error::StateError(state::Error::Temporary { + error: msg.to_string(), + }) + }, + )? { extended_tx_result .masp_tx_refs @@ -488,7 +494,10 @@ where // Commit tx to the block write log even in case of subsequent errors (if // the fee payment failed instead, than the previous two functions must // have propagated an error) - shell_params.state.write_log_mut().commit_batch(); + shell_params + .state + .write_log_mut() + .commit_batch_and_current_tx(); let (batch_results, masp_section_refs) = payment_result.map_or_else( || (TxResult::default(), None), @@ -753,9 +762,14 @@ where if is_masp_transfer(&result.changed_keys) && result.is_accepted() { - if let Some(masp_tx_id) = - action::get_masp_section_ref(&actions) - { + if let Some(masp_tx_id) = action::get_masp_section_ref( + &actions, + ) + .map_err(|msg| { + Error::StateError(state::Error::Temporary { + error: msg.to_string(), + }) + })? { Some(MaspTxResult { tx_result: result, masp_section_ref: Either::Left(masp_tx_id), @@ -1092,7 +1106,7 @@ where .write_log() .verifiers_and_changed_keys(verifiers_from_tx); - let vps_result = execute_vps( + let (vps_result, vps_gas) = execute_vps( verifiers, keys_changed, tx, @@ -1101,10 +1115,10 @@ where tx_gas_meter, vp_wasm_cache, )?; - tracing::debug!("Total VPs gas cost {:?}", vps_result.gas_used); + tracing::debug!("Total VPs gas cost {:?}", vps_gas); tx_gas_meter - .add_vps_gas(&vps_result.gas_used) + .consume(vps_gas.into()) .map_err(|err| Error::GasError(err.to_string()))?; Ok(vps_result) @@ -1120,62 +1134,72 @@ fn execute_vps( state: &S, tx_gas_meter: &TxGasMeter, vp_wasm_cache: &mut VpCache, -) -> Result +) -> Result<(VpsResult, namada_sdk::gas::Gas)> where S: 'static + State + Sync, CA: 'static + WasmCacheAccess + Sync, { - let vps_result = verifiers - .par_iter() - .try_fold(VpsResult::default, |mut result, addr| { - let gas_meter = - RefCell::new(VpGasMeter::new_from_tx_meter(tx_gas_meter)); - let tx_accepted = match &addr { - Address::Implicit(_) | Address::Established(_) => { - let (vp_hash, gas) = state + let vps_result = + verifiers + .par_iter() + .try_fold( + || (VpsResult::default(), Gas::from(0)), + |(mut result, mut vps_gas), addr| { + let gas_meter = RefCell::new( + VpGasMeter::new_from_tx_meter(tx_gas_meter), + ); + let tx_accepted = + match &addr { + Address::Implicit(_) | Address::Established(_) => { + let (vp_hash, gas) = state .validity_predicate::>(addr) .map_err(Error::StateError)?; - gas_meter - .borrow_mut() - .consume(gas) - .map_err(|err| Error::GasError(err.to_string()))?; - let Some(vp_code_hash) = vp_hash else { - return Err(Error::MissingAddress(addr.clone())); - }; - - wasm::run::vp( - vp_code_hash, - batched_tx, - tx_index, - addr, - state, - &gas_meter, - &keys_changed, - &verifiers, - vp_wasm_cache.clone(), - ) - .map_err(|err| match err { + gas_meter.borrow_mut().consume(gas).map_err( + |err| Error::GasError(err.to_string()), + )?; + let Some(vp_code_hash) = vp_hash else { + return Err(Error::MissingAddress( + addr.clone(), + )); + }; + + wasm::run::vp( + vp_code_hash, + batched_tx, + tx_index, + addr, + state, + &gas_meter, + &keys_changed, + &verifiers, + vp_wasm_cache.clone(), + ) + .map_err( + |err| { + match err { wasm::run::Error::GasError(msg) => Error::GasError(msg), wasm::run::Error::InvalidSectionSignature(msg) => { Error::InvalidSectionSignature(msg) } _ => Error::VpRunnerError(err), - }) - } - Address::Internal(internal_addr) => { - let ctx = NativeVpCtx::new( - addr, - state, - batched_tx.tx, - batched_tx.cmt, - tx_index, - &gas_meter, - &keys_changed, - &verifiers, - vp_wasm_cache.clone(), - ); + } + }, + ) + } + Address::Internal(internal_addr) => { + let ctx = NativeVpCtx::new( + addr, + state, + batched_tx.tx, + batched_tx.cmt, + tx_index, + &gas_meter, + &keys_changed, + &verifiers, + vp_wasm_cache.clone(), + ); - match internal_addr { + match internal_addr { InternalAddress::PoS => { let pos = PosVp::new(ctx); pos.validate_tx( @@ -1301,49 +1325,56 @@ where Error::AccessForbidden((*internal_addr).clone()), ), } - } - }; + } + }; + + tx_accepted.map_or_else( + |err| { + result + .status_flags + .insert(err.invalid_section_signature_flag()); + result.rejected_vps.insert(addr.clone()); + result.errors.push((addr.clone(), err.to_string())); + }, + |()| { + result.accepted_vps.insert(addr.clone()); + }, + ); - tx_accepted.map_or_else( - |err| { - result - .status_flags - .insert(err.invalid_section_signature_flag()); - result.rejected_vps.insert(addr.clone()); - result.errors.push((addr.clone(), err.to_string())); - }, - |()| { - result.accepted_vps.insert(addr.clone()); - }, - ); + // Execution of VPs can (and must) be short-circuited + // only in case of a gas overflow to prevent the + // transaction from consuming resources that have not + // been acquired in the corresponding wrapper tx. For + // all the other errors we keep evaluating the vps. This + // allows to display a consistent VpsResult across all + // nodes and find any invalid signatures + vps_gas = vps_gas + .checked_add(gas_meter.borrow().get_vp_consumed_gas()) + .ok_or(Error::GasError( + gas::Error::GasOverflow.to_string(), + ))?; + gas_meter + .borrow() + .check_vps_limit(vps_gas) + .map_err(|err| Error::GasError(err.to_string()))?; - // Execution of VPs can (and must) be short-circuited - // only in case of a gas overflow to prevent the - // transaction from consuming resources that have not - // been acquired in the corresponding wrapper tx. For - // all the other errors we keep evaluating the vps. This - // allows to display a consistent VpsResult across all - // nodes and find any invalid signatures - result - .gas_used - .set(gas_meter.into_inner()) - .map_err(|err| Error::GasError(err.to_string()))?; - - Ok(result) - }) - .try_reduce(VpsResult::default, |a, b| { - merge_vp_results(a, b, tx_gas_meter) - })?; + Ok((result, vps_gas)) + }, + ) + .try_reduce( + || (VpsResult::default(), Gas::from(0)), + |a, b| merge_vp_results(a, b, tx_gas_meter), + )?; Ok(vps_result) } /// Merge VP results from parallel runs fn merge_vp_results( - a: VpsResult, - mut b: VpsResult, + (a, a_gas): (VpsResult, Gas), + (mut b, b_gas): (VpsResult, Gas), tx_gas_meter: &TxGasMeter, -) -> Result { +) -> Result<(VpsResult, Gas)> { let mut accepted_vps = a.accepted_vps; let mut rejected_vps = a.rejected_vps; accepted_vps.extend(b.accepted_vps); @@ -1351,19 +1382,23 @@ fn merge_vp_results( let mut errors = a.errors; errors.append(&mut b.errors); let status_flags = a.status_flags | b.status_flags; - let mut gas_used = a.gas_used; - gas_used - .merge(b.gas_used, tx_gas_meter) + let vps_gas = a_gas + .checked_add(b_gas) + .ok_or(Error::GasError(gas::Error::GasOverflow.to_string()))?; + tx_gas_meter + .check_vps_limit(vps_gas) .map_err(|err| Error::GasError(err.to_string()))?; - Ok(VpsResult { - accepted_vps, - rejected_vps, - gas_used, - errors, - status_flags, - }) + Ok(( + VpsResult { + accepted_vps, + rejected_vps, + errors, + status_flags, + }, + vps_gas, + )) } #[cfg(test)] diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs index 2b3ad3fa45..ae72f4cc05 100644 --- a/crates/node/src/shell/finalize_block.rs +++ b/crates/node/src/shell/finalize_block.rs @@ -349,7 +349,7 @@ where match extended_dispatch_result { Ok(extended_tx_result) => match tx_data.tx.header.tx_type { TxType::Wrapper(_) => { - self.state.write_log_mut().commit_batch(); + self.state.write_log_mut().commit_batch_and_current_tx(); // Return withouth emitting any events return Some(WrapperCache { @@ -392,7 +392,7 @@ where .extend(Code(ResultCode::InvalidTx)); // Drop the batch write log which could contain invalid data. // Important data that could be valid (e.g. a valid fee payment) - // must have already been moved to the bloc kwrite log by now + // must have already been moved to the block write log by now self.state.write_log_mut().drop_batch(); } Err(dispatch_error) => { @@ -476,7 +476,7 @@ where self.state.write_log_mut().drop_batch(); tx_logs.tx_event.extend(Code(ResultCode::WasmRuntimeError)); } else { - self.state.write_log_mut().commit_batch(); + self.state.write_log_mut().commit_batch_and_current_tx(); self.state .in_mem_mut() .block @@ -550,8 +550,12 @@ where .results .accept(tx_data.tx_index); temp_log.commit(tx_logs, response); - // Commit the successful inner transactions before the error - self.state.write_log_mut().commit_batch(); + // Commit the successful inner transactions before the error. Drop + // the current tx write log which might be still populated with data + // to be discarded (this is the case when we propagate an error + // from the function that runs the actual batch) + self.state.write_log_mut().drop_tx(); + self.state.write_log_mut().commit_batch_only(); } if commit_batch_hash { diff --git a/crates/node/src/shell/governance.rs b/crates/node/src/shell/governance.rs index 7329b9bc36..cc4a3a3412 100644 --- a/crates/node/src/shell/governance.rs +++ b/crates/node/src/shell/governance.rs @@ -122,14 +122,6 @@ where TallyResult::Passed => { let proposal_event = match proposal_type { ProposalType::Default => { - let proposal_code = - gov_api::get_proposal_code(&shell.state, id)? - .unwrap_or_default(); - let _result = execute_default_proposal( - shell, - id, - proposal_code.clone(), - )?; tracing::info!( "Governance proposal #{} (default) has passed.", id, @@ -176,7 +168,7 @@ where } ProposalType::PGFPayment(payments) => { let native_token = &shell.state.get_native_token()?; - let _result = execute_pgf_funding_proposal( + execute_pgf_funding_proposal( &mut shell.state, events, native_token, diff --git a/crates/node/src/shell/init_chain.rs b/crates/node/src/shell/init_chain.rs index 498ee5d6bc..74d324aba3 100644 --- a/crates/node/src/shell/init_chain.rs +++ b/crates/node/src/shell/init_chain.rs @@ -512,15 +512,6 @@ where }; for (owner, balance) in balances { - if let genesis::GenesisAddress::PublicKey(pk) = owner { - namada_sdk::account::init_account_storage( - &mut self.state, - &owner.address(), - std::slice::from_ref(&pk.raw), - 1, - ) - .unwrap(); - } tracing::info!( "Crediting {} {} tokens to {}", balance, @@ -530,7 +521,7 @@ where credit_tokens( &mut self.state, token_address, - &owner.address(), + owner, balance.amount(), ) .expect("Couldn't credit initial balance"); @@ -568,6 +559,7 @@ where let public_keys: Vec<_> = public_keys.iter().map(|pk| pk.raw.clone()).collect(); + namada_sdk::account::init_account_storage( &mut self.state, address, @@ -575,6 +567,18 @@ where *threshold, ) .unwrap(); + + for pk in &public_keys { + let implicit_addr = pk.into(); + + namada_sdk::account::init_account_storage( + &mut self.state, + &implicit_addr, + std::slice::from_ref(pk), + 1, + ) + .unwrap(); + } } } self.proceed_with(()) diff --git a/crates/node/src/shell/prepare_proposal.rs b/crates/node/src/shell/prepare_proposal.rs index 5f9f3a8776..ac0812a74d 100644 --- a/crates/node/src/shell/prepare_proposal.rs +++ b/crates/node/src/shell/prepare_proposal.rs @@ -142,7 +142,7 @@ where ); match result { Ok(gas) => { - temp_state.write_log_mut().commit_batch(); + temp_state.write_log_mut().commit_batch_and_current_tx(); Some((tx_bytes.to_owned(), gas)) }, Err(()) => { diff --git a/crates/node/src/shell/process_proposal.rs b/crates/node/src/shell/process_proposal.rs index fecbd20e11..ee2a3ed650 100644 --- a/crates/node/src/shell/process_proposal.rs +++ b/crates/node/src/shell/process_proposal.rs @@ -153,7 +153,7 @@ where ); let error_code = ResultCode::from_u32(result.code).unwrap(); if let ResultCode::Ok = error_code { - temp_state.write_log_mut().commit_batch(); + temp_state.write_log_mut().commit_batch_and_current_tx(); } else { tracing::info!( "Process proposal rejected an invalid tx. Error code: \ diff --git a/crates/parameters/src/lib.rs b/crates/parameters/src/lib.rs index 55a91c75d5..3b2b954de5 100644 --- a/crates/parameters/src/lib.rs +++ b/crates/parameters/src/lib.rs @@ -297,7 +297,7 @@ where .into_storage_result() } -/// Read the the epoch duration parameter from store +/// Read the epoch duration parameter from store pub fn read_epoch_duration_parameter( storage: &S, ) -> namada_storage::Result @@ -312,7 +312,7 @@ where .into_storage_result() } -/// Read the the masp epoch multiplier parameter from store +/// Read the masp epoch multiplier parameter from store pub fn read_masp_epoch_multiplier_parameter( storage: &S, ) -> namada_storage::Result @@ -622,18 +622,9 @@ where last_block_height, num_blocks_to_read, )?; - let max_block_time_estimate = - estimate_max_block_time_from_parameters(storage)?; - - Ok(maybe_max_block_time.map_or( - max_block_time_estimate, - |max_block_time_over_num_blocks_to_read| { - std::cmp::max( - max_block_time_over_num_blocks_to_read, - max_block_time_estimate, - ) - }, - )) + + maybe_max_block_time + .map_or_else(|| estimate_max_block_time_from_parameters(storage), Ok) } #[cfg(test)] diff --git a/crates/proof_of_stake/src/error.rs b/crates/proof_of_stake/src/error.rs index c692e0decf..c8f2cfb1b0 100644 --- a/crates/proof_of_stake/src/error.rs +++ b/crates/proof_of_stake/src/error.rs @@ -7,7 +7,7 @@ use namada_core::storage::Epoch; use thiserror::Error; use crate::rewards; -use crate::types::{BondId, ValidatorState}; +use crate::types::ValidatorState; #[allow(missing_docs)] #[derive(Error, Debug)] @@ -67,15 +67,6 @@ pub enum UnbondError { ValidatorIsFrozen(Address), } -#[allow(missing_docs)] -#[derive(Error, Debug)] -pub enum WithdrawError { - #[error("No unbond could be found for {0}")] - NoUnbondFound(BondId), - #[error("No unbond may be withdrawn yet for {0}")] - NoWithdrawableUnbond(BondId), -} - #[allow(missing_docs)] #[derive(Error, Debug)] pub enum SlashError { @@ -194,12 +185,6 @@ impl From for namada_storage::Error { } } -impl From for namada_storage::Error { - fn from(err: WithdrawError) -> Self { - Self::new(err) - } -} - impl From for namada_storage::Error { fn from(err: CommissionRateChangeError) -> Self { Self::new(err) diff --git a/crates/proof_of_stake/src/lib.rs b/crates/proof_of_stake/src/lib.rs index ca7204fb94..8b0737bc36 100644 --- a/crates/proof_of_stake/src/lib.rs +++ b/crates/proof_of_stake/src/lib.rs @@ -1478,11 +1478,7 @@ where // Check that there are unbonded tokens available for withdrawal if unbond_handle.is_empty(storage)? { - return Err(WithdrawError::NoUnbondFound(BondId { - source: source.clone(), - validator: validator.clone(), - }) - .into()); + return Ok(token::Amount::zero()); } let mut unbonds_and_redelegated_unbonds: BTreeMap< diff --git a/crates/proof_of_stake/src/tests/test_validator.rs b/crates/proof_of_stake/src/tests/test_validator.rs index 73287eb0e1..62d41910e0 100644 --- a/crates/proof_of_stake/src/tests/test_validator.rs +++ b/crates/proof_of_stake/src/tests/test_validator.rs @@ -625,7 +625,7 @@ fn test_validator_sets() { ); assert_eq!(tm_updates[1], ValidatorSetUpdate::Deactivated(pk2)); - // Unbond some stake from val1, it should be be swapped with the greatest + // Unbond some stake from val1, it should be swapped with the greatest // below-capacity validator val2 into the below-capacity set. The stake of // val1 will go below 1 NAM, which is the validator_stake_threshold, so it // will enter the below-threshold validator set. @@ -836,7 +836,7 @@ fn test_validator_sets() { ); assert_eq!(tm_updates[1], ValidatorSetUpdate::Deactivated(pk1)); - // Bond some stake to val6, it should be be swapped with the lowest + // Bond some stake to val6, it should be swapped with the lowest // consensus validator val2 into the consensus set let bond = token::Amount::from_uint(500_000, 0).unwrap(); let stake6 = stake6 + bond; diff --git a/crates/sdk/src/args.rs b/crates/sdk/src/args.rs index 1de576fc0a..59845d5c23 100644 --- a/crates/sdk/src/args.rs +++ b/crates/sdk/src/args.rs @@ -29,6 +29,7 @@ use crate::eth_bridge::bridge_pool; use crate::ibc::core::host::types::identifiers::{ChannelId, PortId}; use crate::masp::utils::RetryStrategy; use crate::signing::SigningTxData; +use crate::wallet::{DatedSpendingKey, DatedViewingKey}; use crate::{rpc, tx, Namada}; /// [`Duration`](StdDuration) wrapper that provides a @@ -67,6 +68,10 @@ pub trait NamadaTypes: Clone + std::fmt::Debug { type ViewingKey: Clone + std::fmt::Debug; /// Represents a shielded spending key type SpendingKey: Clone + std::fmt::Debug; + /// Represents a shielded viewing key + type DatedViewingKey: Clone + std::fmt::Debug; + /// Represents a shielded spending key + type DatedSpendingKey: Clone + std::fmt::Debug; /// Represents a shielded payment address type PaymentAddress: Clone + std::fmt::Debug; /// Represents the owner of a balance @@ -107,6 +112,8 @@ impl NamadaTypes for SdkTypes { type BpConversionTable = HashMap; type ConfigRpcTendermintAddress = tendermint_rpc::Url; type Data = Vec; + type DatedSpendingKey = DatedSpendingKey; + type DatedViewingKey = DatedViewingKey; type EthereumAddress = (); type Keypair = namada_core::key::common::SecretKey; type MaspIndexerAddress = String; @@ -2124,9 +2131,9 @@ pub struct ShieldedSync { /// Height to sync up to. Defaults to most recent pub last_query_height: Option, /// Spending keys used to determine note ownership - pub spending_keys: Vec, + pub spending_keys: Vec, /// Viewing keys used to determine note ownership - pub viewing_keys: Vec, + pub viewing_keys: Vec, /// Address of a `namada-masp-indexer` live instance /// /// If present, the shielded sync will be performed @@ -2289,6 +2296,33 @@ pub struct Tx { pub memo: Option, /// Use device to sign the transaction pub use_device: bool, + /// Hardware Wallet transport - HID (USB) or TCP + pub device_transport: DeviceTransport, +} + +/// Hardware Wallet transport - HID (USB) or TCP +#[derive(Debug, Clone, Copy, Default)] +pub enum DeviceTransport { + /// HID transport (USB connected hardware wallet) + #[default] + Hid, + /// TCP transport + Tcp, +} + +impl FromStr for DeviceTransport { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.trim().to_ascii_lowercase().as_str() { + "hid" => Ok(Self::Hid), + "tcp" => Ok(Self::Tcp), + raw => Err(format!( + "Unexpected device transport \"{raw}\". Valid options are \ + \"hid\" or \"tcp\"." + )), + } + } } /// Builder functions for Tx @@ -2454,6 +2488,9 @@ pub struct KeyGen { pub prompt_bip39_passphrase: bool, /// Allow non-compliant derivation path pub allow_non_compliant: bool, + /// Optional block height after which this key was created. + /// Only used for MASP keys. + pub birthday: Option, } /// Wallet restore key and implicit address arguments @@ -2477,6 +2514,11 @@ pub struct KeyDerive { pub prompt_bip39_passphrase: bool, /// Use device to generate key and address pub use_device: bool, + /// Hardware Wallet transport - HID (USB) or TCP + pub device_transport: DeviceTransport, + /// Optional blockheight after which this key was created. + /// Only used for MASP keys + pub birthday: Option, } /// Wallet list arguments @@ -2554,6 +2596,9 @@ pub struct KeyAddressAdd { pub alias_force: bool, /// Any supported value pub value: String, + /// Optional block height after which this key was created. + /// Only used for MASP keys. + pub birthday: Option, /// Don't encrypt the key pub unsafe_dont_encrypt: bool, } diff --git a/crates/sdk/src/eth_bridge/bridge_pool.rs b/crates/sdk/src/eth_bridge/bridge_pool.rs index 69d8a7c505..90c4686e44 100644 --- a/crates/sdk/src/eth_bridge/bridge_pool.rs +++ b/crates/sdk/src/eth_bridge/bridge_pool.rs @@ -84,6 +84,7 @@ pub async fn build_bridge_pool_tx( Some(sender_.clone()), // tx signer Some(sender_), + vec![] ), )?; let (fee_amount, _) = diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index 5e446931db..b89d702a33 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -51,7 +51,7 @@ pub use std::marker::Sync as MaybeSync; use std::path::PathBuf; use std::str::FromStr; -use args::{InputAmount, SdkTypes}; +use args::{DeviceTransport, InputAmount, SdkTypes}; use io::Io; use masp::{ShieldedContext, ShieldedUtils}; use namada_core::address::Address; @@ -82,7 +82,7 @@ use tx::{ use wallet::{Wallet, WalletIo, WalletStorage}; /// Default gas-limit -pub const DEFAULT_GAS_LIMIT: u64 = 100_000; +pub const DEFAULT_GAS_LIMIT: u64 = 150_000; #[allow(missing_docs)] #[cfg(not(feature = "async-send"))] @@ -168,6 +168,7 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { password: None, memo: None, use_device: false, + device_transport: DeviceTransport::default(), } } @@ -739,6 +740,7 @@ where password: None, memo: None, use_device: false, + device_transport: DeviceTransport::default(), }, } } diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 3dcbd6b8c9..0fc0430ade 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -79,6 +79,7 @@ pub use crate::masp::shielded_sync::{ use crate::queries::Client; use crate::rpc::{query_conversion, query_denom}; use crate::task_env::TaskEnvironment; +use crate::wallet::{DatedKeypair, DatedSpendingKey}; use crate::{ control_flow, display_line, edisplay_line, query_native_token, rpc, MaybeSend, MaybeSync, Namada, @@ -504,8 +505,8 @@ impl ShieldedContext { env: impl TaskEnvironment, config: ShieldedSyncConfig, last_query_height: Option, - sks: &[MaspExtendedSpendingKey], - fvks: &[ViewingKey], + sks: &[DatedSpendingKey], + fvks: &[DatedKeypair], ) -> Result<(), Error> where M: MaspClient + Send + Sync + Unpin + 'static, diff --git a/crates/sdk/src/masp/shielded_sync/dispatcher.rs b/crates/sdk/src/masp/shielded_sync/dispatcher.rs index 1654b7a6ab..1f3d444fe7 100644 --- a/crates/sdk/src/masp/shielded_sync/dispatcher.rs +++ b/crates/sdk/src/masp/shielded_sync/dispatcher.rs @@ -13,11 +13,10 @@ use futures::task::AtomicWaker; use masp_primitives::merkle_tree::{CommitmentTree, IncrementalWitness}; use masp_primitives::sapling::{Node, ViewingKey}; use masp_primitives::transaction::Transaction; -use masp_primitives::zip32::ExtendedSpendingKey; use namada_core::collections::HashMap; use namada_core::control_flow::time::{Duration, LinearBackoff, Sleep}; use namada_core::hints; -use namada_core::storage::{BlockHeight, TxIndex}; +use namada_core::storage::BlockHeight; use namada_tx::IndexedTx; use super::utils::{IndexedNoteEntry, MaspClient}; @@ -29,9 +28,11 @@ use crate::masp::utils::{ blocks_left_to_fetch, DecryptedData, Fetched, RetryStrategy, TrialDecrypted, }; use crate::masp::{ - to_viewing_key, NoteIndex, ShieldedContext, ShieldedUtils, WitnessMap, + to_viewing_key, MaspExtendedSpendingKey, NoteIndex, ShieldedContext, + ShieldedUtils, WitnessMap, }; use crate::task_env::TaskSpawner; +use crate::wallet::{DatedKeypair, DatedSpendingKey}; use crate::{MaybeSend, MaybeSync}; struct AsyncCounterInner { @@ -316,8 +317,8 @@ where mut self, start_query_height: Option, last_query_height: Option, - sks: &[ExtendedSpendingKey], - fvks: &[ViewingKey], + sks: &[DatedSpendingKey], + fvks: &[DatedKeypair], ) -> Result>, Error> { let initial_state = self .perform_initial_setup( @@ -441,11 +442,8 @@ where h.as_ref().map(|itx| &itx.height) < Some(last_query_height) }) { - *h = Some(IndexedTx { - height: *last_query_height, - // NB: the entire block is synced - index: TxIndex(u32::MAX), - }); + // NB: the entire block is synced + *h = Some(IndexedTx::entire_block(*last_query_height)); } Ok(()) @@ -455,8 +453,8 @@ where &mut self, start_query_height: Option, last_query_height: Option, - sks: &[ExtendedSpendingKey], - fvks: &[ViewingKey], + sks: &[DatedSpendingKey], + fvks: &[DatedKeypair], ) -> Result { if start_query_height > last_query_height { return Err(Error::Other(format!( @@ -466,12 +464,25 @@ where ))); } - for esk in sks { - let vk = to_viewing_key(esk).vk; - self.ctx.vk_heights.entry(vk).or_default(); - } - for vk in fvks { - self.ctx.vk_heights.entry(*vk).or_default(); + for vk in sks + .iter() + .map(|esk| { + esk.map(|k| { + to_viewing_key(&MaspExtendedSpendingKey::from(k)).vk + }) + }) + .chain(fvks.iter().copied()) + { + if let Some(h) = self.ctx.vk_heights.entry(vk.key).or_default() { + let birthday = IndexedTx::entire_block(vk.birthday); + if birthday > *h { + *h = birthday; + } + } else if vk.birthday >= BlockHeight::first() { + self.ctx + .vk_heights + .insert(vk.key, Some(IndexedTx::entire_block(vk.birthday))); + } } // the latest block height which has been added to the witness Merkle @@ -773,11 +784,14 @@ where fn spawn_trial_decryptions(&self, itx: IndexedTx, txs: &[Transaction]) { for tx in txs { - for vk in self.ctx.vk_heights.keys() { - let vk = *vk; + for (vk, vk_height) in self.ctx.vk_heights.iter() { + let key_is_outdated = vk_height.as_ref() < Some(&itx); + let cached = self.cache.trial_decrypted.get(&itx, vk).is_some(); - if self.cache.trial_decrypted.get(&itx, &vk).is_none() { + if key_is_outdated && !cached { let tx = tx.clone(); + let vk = *vk; + self.spawn_sync(move |interrupt| { Message::TrialDecrypt( itx, @@ -846,7 +860,7 @@ mod dispatcher_tests { use std::hint::spin_loop; use futures::join; - use namada_core::storage::BlockHeight; + use namada_core::storage::{BlockHeight, TxIndex}; use namada_tx::IndexedTx; use tempfile::tempdir; @@ -856,10 +870,11 @@ mod dispatcher_tests { use crate::masp::fs::FsShieldedUtils; use crate::masp::test_utils::{ arbitrary_masp_tx, arbitrary_masp_tx_with_fee_unshielding, - arbitrary_vk, TestingMaspClient, + arbitrary_vk, dated_arbitrary_vk, TestingMaspClient, }; use crate::masp::{MaspLocalTaskEnv, ShieldedSyncConfig}; use crate::task_env::TaskEnvironment; + use crate::wallet::StoredKeypair; #[tokio::test] async fn test_applying_cache_drains_decrypted_data() { @@ -908,10 +923,7 @@ mod dispatcher_tests { assert!(dispatcher.cache.trial_decrypted.is_empty()); let expected = BTreeMap::from([( arbitrary_vk(), - Some(IndexedTx { - height: 9.into(), - index: TxIndex(u32::MAX), - }), + Some(IndexedTx::entire_block(9.into())), )]); assert_eq!(expected, dispatcher.ctx.vk_heights); }) @@ -1141,7 +1153,7 @@ mod dispatcher_tests { .client(client) .retry_strategy(RetryStrategy::Times(0)) .build(); - let vk = arbitrary_vk(); + let vk = dated_arbitrary_vk(); // we first test that with no retries, a fetching failure // stops process @@ -1212,11 +1224,8 @@ mod dispatcher_tests { assert_eq!(keys, expected); assert_eq!( - *ctx.vk_heights[&vk].as_ref().unwrap(), - IndexedTx { - height: 2.into(), - index: TxIndex(u32::MAX), - } + *ctx.vk_heights[&vk.key].as_ref().unwrap(), + IndexedTx::entire_block(2.into(),) ); assert_eq!(ctx.note_map.len(), 2); }) @@ -1243,7 +1252,7 @@ mod dispatcher_tests { .block_batch_size(1) .build(); - let vk = arbitrary_vk(); + let vk = dated_arbitrary_vk(); MaspLocalTaskEnv::new(4) .expect("Test failed") .run(|s| async { @@ -1340,7 +1349,7 @@ mod dispatcher_tests { send.send_replace(true); let res = dispatcher - .run(None, None, &[], &[arbitrary_vk()]) + .run(None, None, &[], &[dated_arbitrary_vk()]) .await .expect("Test failed"); assert!(res.is_none()); @@ -1360,4 +1369,96 @@ mod dispatcher_tests { }) .await; } + /// Test the the birthdays of keys are properly reflected in the key + /// sync heights when starting shielded sync. + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_key_birthdays() { + let temp_dir = tempdir().unwrap(); + let mut shielded_ctx = + FsShieldedUtils::new(temp_dir.path().to_path_buf()); + let (client, masp_tx_sender) = TestingMaspClient::new(2.into()); + // First test the case where no keys have been seen yet + let mut vk = DatedKeypair::new(arbitrary_vk(), Some(10.into())); + let StoredKeypair::Raw(mut sk) = serde_json::from_str::<'_, StoredKeypair::>(r#""unencrypted:zsknam1q02rgh4mqqqqpqqm68m2lmd0xe9k5vf4fscmdxuvewqhdhwl0h492fj40tzl5f6gwfk6kgnaxpgct7mx9cw2he4724858jdfhrzdh3e4hu3us463gphqyl6k5hvkjwkv9r7rx3jtcueurgflgj6dx9qn4rg0caf0t9zawfcdwt3ramxlrs4jyan4wyp4nh9hj8s806ru0smk3437ejy56ewtw9ljz8rc3vkyznxdf3l5c70skcw6aatpv5de9zhxuxs5k6l6jz6zktgg0udvl<<30""#).expect("Test failed") else { + panic!("Test failed") + }; + let masp_tx = arbitrary_masp_tx(); + masp_tx_sender + .send(Some(( + IndexedTx { + height: 1.into(), + index: TxIndex(1), + }, + vec![masp_tx.clone()], + ))) + .expect("Test failed"); + let (_shutdown_send, shutdown_sig) = shutdown_signal(); + let config = ShieldedSyncConfig::builder() + .client(client) + .fetched_tracker(DevNullProgressBar) + .scanned_tracker(DevNullProgressBar) + .applied_tracker(DevNullProgressBar) + .retry_strategy(RetryStrategy::Times(0)) + .shutdown_signal(shutdown_sig) + .build(); + shielded_ctx + .sync( + MaspLocalTaskEnv::new(4).unwrap(), + config.clone(), + None, + &[sk], + &[vk], + ) + .await + .expect("Test failed"); + let birthdays = shielded_ctx + .vk_heights + .values() + .cloned() + .collect::>(); + assert_eq!( + birthdays, + vec![ + Some(IndexedTx::entire_block(BlockHeight(30))), + Some(IndexedTx::entire_block(BlockHeight(10))) + ] + ); + + // Test two cases: + // * A birthday is less than the synced height of key + // * A birthday is greater than the synced height of key + vk.birthday = 5.into(); + sk.birthday = 60.into(); + masp_tx_sender + .send(Some(( + IndexedTx { + height: 1.into(), + index: TxIndex(1), + }, + vec![masp_tx.clone()], + ))) + .expect("Test failed"); + shielded_ctx + .sync( + MaspLocalTaskEnv::new(4).unwrap(), + config, + None, + &[sk], + &[vk], + ) + .await + .expect("Test failed"); + let birthdays = shielded_ctx + .vk_heights + .values() + .cloned() + .collect::>(); + assert_eq!( + birthdays, + vec![ + Some(IndexedTx::entire_block(BlockHeight(60))), + Some(IndexedTx::entire_block(BlockHeight(10))) + ] + ) + } } diff --git a/crates/sdk/src/masp/test_utils.rs b/crates/sdk/src/masp/test_utils.rs index 85a4c5d866..7ed4e14734 100644 --- a/crates/sdk/src/masp/test_utils.rs +++ b/crates/sdk/src/masp/test_utils.rs @@ -15,10 +15,15 @@ use crate::error::Error; use crate::masp::utils::{ IndexedNoteEntry, MaspClient, MaspClientCapabilities, }; +use crate::wallet::DatedKeypair; /// A viewing key derived from A_SPENDING_KEY pub const AA_VIEWING_KEY: &str = "zvknam1qqqqqqqqqqqqqq9v0sls5r5de7njx8ehu49pqgmqr9ygelg87l5x8y4s9r0pjlvu6x74w9gjpw856zcu826qesdre628y6tjc26uhgj6d9zqur9l5u3p99d9ggc74ald6s8y3sdtka74qmheyqvdrasqpwyv2fsmxlz57lj4grm2pthzj3sflxc0jx0edrakx3vdcngrfjmru8ywkguru8mxss2uuqxdlglaz6undx5h8w7g70t2es850g48xzdkqay5qs0yw06rtxcpjdve6"; +pub fn dated_arbitrary_vk() -> DatedKeypair { + arbitrary_vk().into() +} + pub fn arbitrary_vk() -> ViewingKey { ExtendedFullViewingKey::from( ExtendedViewingKey::from_str(AA_VIEWING_KEY).expect("Test failed"), diff --git a/crates/sdk/src/rpc.rs b/crates/sdk/src/rpc.rs index 6111774823..7651822ce0 100644 --- a/crates/sdk/src/rpc.rs +++ b/crates/sdk/src/rpc.rs @@ -936,32 +936,49 @@ pub async fn get_public_key_at( } /// Query the proposal result -pub async fn query_proposal_result( - client: &C, +pub async fn query_proposal_result( + context: &N, proposal_id: u64, ) -> Result, Error> { - let proposal = query_proposal_by_id(client, proposal_id).await?; + let proposal = query_proposal_by_id(context.client(), proposal_id).await?; let proposal = if let Some(proposal) = proposal { proposal } else { return Ok(None); }; - let stored_proposal_result = convert_response::>( - RPC.vp().gov().proposal_result(client, &proposal_id).await, - )?; + + let current_epoch = query_epoch(context.client()).await?; + if current_epoch < proposal.voting_start_epoch { + display_line!( + context.io(), + "Proposal {} is still pending, voting period will start in {} \ + epochs.", + proposal_id, + proposal.voting_end_epoch.0 - current_epoch.0 + ); + } + + let stored_proposal_result = + convert_response::>( + RPC.vp() + .gov() + .proposal_result(context.client(), &proposal_id) + .await, + )?; + let proposal_result = match stored_proposal_result { Some(proposal_result) => proposal_result, None => { let tally_epoch = proposal.voting_end_epoch; let is_author_pgf_steward = - is_steward(client, &proposal.author).await; - let votes = query_proposal_votes(client, proposal_id) + is_steward(context.client(), &proposal.author).await; + let votes = query_proposal_votes(context.client(), proposal_id) .await .unwrap_or_default(); let tally_type = proposal.get_tally_type(is_author_pgf_steward); let total_active_voting_power = - get_total_active_voting_power(client, tally_epoch) + get_total_active_voting_power(context.client(), tally_epoch) .await .unwrap_or_default(); @@ -971,7 +988,7 @@ pub async fn query_proposal_result( match vote.is_validator() { true => { let voting_power = get_validator_stake( - client, + context.client(), tally_epoch, &vote.validator, ) @@ -986,7 +1003,7 @@ pub async fn query_proposal_result( } false => { let voting_power = get_bond_amount_at( - client, + context.client(), &vote.delegator, &vote.validator, tally_epoch, diff --git a/crates/sdk/src/signing.rs b/crates/sdk/src/signing.rs index 57bf85a872..5300cf34c7 100644 --- a/crates/sdk/src/signing.rs +++ b/crates/sdk/src/signing.rs @@ -295,25 +295,24 @@ where } /// Return the necessary data regarding an account to be able to generate a -/// multisignature section +/// signature section pub async fn aux_signing_data( context: &impl Namada, args: &args::Tx, owner: Option
, default_signer: Option
, + extra_public_keys: Vec, ) -> Result { - let public_keys = if owner.is_some() || args.wrapper_fee_payer.is_none() { - tx_signers(context, args, default_signer.clone()).await? - } else { - vec![] - }; + let mut public_keys = + tx_signers(context, args, default_signer.clone()).await?; + public_keys.extend(extra_public_keys.clone()); let (account_public_keys_map, threshold) = match &owner { Some(owner @ Address::Established(_)) => { let account = rpc::get_account_info(context.client(), owner).await?; if let Some(account) = account { - (Some(account.public_keys_map), account.threshold) + (Some(account.clone().public_keys_map), account.threshold) } else { return Err(Error::from(TxSubmitError::InvalidAccount( owner.encode(), @@ -332,7 +331,10 @@ pub async fn aux_signing_data( ))); } }, - None => (None, 0u8), + None => ( + Some(AccountPublicKeysMap::from_iter(public_keys.clone())), + 0u8, + ), }; let fee_payer = if args.disposable_signing_key { @@ -360,47 +362,6 @@ pub async fn aux_signing_data( }) } -/// Initialize validator signing data -pub async fn init_validator_signing_data( - context: &impl Namada, - args: &args::Tx, - validator_keys: Vec, -) -> Result { - let mut public_keys = if args.wrapper_fee_payer.is_none() { - tx_signers(context, args, None).await? - } else { - vec![] - }; - public_keys.extend(validator_keys.clone()); - - let account_public_keys_map = - Some(AccountPublicKeysMap::from_iter(validator_keys)); - - let fee_payer = if args.disposable_signing_key { - context - .wallet_mut() - .await - .gen_disposable_signing_key(&mut OsRng) - .to_public() - } else { - match &args.wrapper_fee_payer { - Some(keypair) => keypair.clone(), - None => public_keys - .first() - .ok_or(TxSubmitError::InvalidFeePayer)? - .clone(), - } - }; - - Ok(SigningTxData { - owner: None, - public_keys, - threshold: 0, - account_public_keys_map, - fee_payer, - }) -} - /// Information about the post-fee balance of the tx's source. Used to correctly /// handle balance validation in the inner tx pub struct TxSourcePostBalance { @@ -625,7 +586,7 @@ async fn make_ledger_amount_asset( )); } else { output.extend(vec![ - format!("{}Token : {}", prefix, token), + format!("{}Token : {}", prefix, decoded.token), format!( "{}Amount : {}", prefix, @@ -1059,9 +1020,10 @@ pub async fn to_ledger_vector( Error::from(EncodingError::Conversion(err.to_string())) })?; - tv.name = "Init_Validator_0".to_string(); + tv.name = "Become_Validator_0".to_string(); - tv.output.extend(vec!["Type : Init Validator".to_string()]); + tv.output + .extend(vec!["Type : Become Validator".to_string()]); tv.output.extend(vec![ format!("Address : {}", init_validator.address), format!("Consensus key : {}", init_validator.consensus_key), @@ -1075,6 +1037,9 @@ pub async fn to_ledger_vector( ), format!("Email : {}", init_validator.email), ]); + if let Some(name) = &init_validator.name { + tv.output.push(format!("Name : {}", name)); + } if let Some(description) = &init_validator.description { tv.output.push(format!("Description : {}", description)); } @@ -1085,6 +1050,9 @@ pub async fn to_ledger_vector( tv.output .push(format!("Discord handle : {}", discord_handle)); } + if let Some(avatar) = &init_validator.avatar { + tv.output.push(format!("Avatar : {}", avatar)); + } tv.output_expert.extend(vec![ format!("Address : {}", init_validator.address), @@ -1099,6 +1067,9 @@ pub async fn to_ledger_vector( ), format!("Email : {}", init_validator.email), ]); + if let Some(name) = &init_validator.name { + tv.output_expert.push(format!("Name : {}", name)); + } if let Some(description) = &init_validator.description { tv.output_expert .push(format!("Description : {}", description)); @@ -1110,6 +1081,9 @@ pub async fn to_ledger_vector( tv.output_expert .push(format!("Discord handle : {}", discord_handle)); } + if let Some(avatar) = &init_validator.avatar { + tv.output_expert.push(format!("Avatar : {}", avatar)); + } } else if code_sec.tag == Some(TX_INIT_PROPOSAL.to_string()) { let init_proposal_data = InitProposalData::try_from_slice( &tx.data(cmt) @@ -1341,7 +1315,6 @@ pub async fn to_ledger_vector( "Receiver : {}", transfer.message.packet_data.receiver ), - format!("Memo : {}", transfer.message.packet_data.memo), format!( "Timeout height : {}", transfer.message.timeout_height_on_b @@ -1368,7 +1341,14 @@ pub async fn to_ledger_vector( "Receiver : {}", transfer.message.packet_data.receiver ), - format!("Memo : {}", transfer.message.packet_data.memo), + ]); + if !transfer.message.packet_data.memo.to_string().is_empty() { + tv.output_expert.push(format!( + "Memo : {}", + transfer.message.packet_data.memo + )); + } + tv.output_expert.extend(vec![ format!( "Timeout height : {}", transfer.message.timeout_height_on_b @@ -1466,9 +1446,6 @@ pub async fn to_ledger_vector( transfer.message.packet_data.receiver ), ]); - if let Some(memo) = &transfer.message.packet_data.memo { - tv.output.push(format!("Memo: {}", memo)); - } tv.output.extend(vec![ format!( "Timeout height : {}", @@ -1538,7 +1515,9 @@ pub async fn to_ledger_vector( ), ]); if let Some(memo) = &transfer.message.packet_data.memo { - tv.output_expert.push(format!("Memo: {}", memo)); + if !memo.to_string().is_empty() { + tv.output_expert.push(format!("Memo: {}", memo)); + } } tv.output_expert.extend(vec![ format!( @@ -1732,6 +1711,9 @@ pub async fn to_ledger_vector( let mut other_items = vec![]; other_items .push(format!("Validator : {}", metadata_change.validator)); + if let Some(name) = metadata_change.name { + other_items.push(format!("Name : {}", name)); + } if let Some(email) = metadata_change.email { other_items.push(format!("Email : {}", email)); } diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index 48e1bd9c9a..ef0cc79080 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -307,9 +307,14 @@ pub async fn build_reveal_pk( args: &args::Tx, public_key: &common::PublicKey, ) -> Result<(Tx, SigningTxData)> { - let signing_data = - signing::aux_signing_data(context, args, None, Some(public_key.into())) - .await?; + let signing_data = signing::aux_signing_data( + context, + args, + None, + Some(public_key.into()), + vec![], + ) + .await?; let (fee_amount, _) = validate_transparent_fee(context, args, &signing_data.fee_payer) .await?; @@ -558,9 +563,11 @@ pub async fn build_change_consensus_key( consensus_key: consensus_key.clone(), }; - let signing_data = signing::init_validator_signing_data( + let signing_data = signing::aux_signing_data( context, tx_args, + None, + None, vec![consensus_key.clone()], ) .await?; @@ -598,6 +605,7 @@ pub async fn build_validator_commission_change( tx_args, Some(validator.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -739,6 +747,7 @@ pub async fn build_validator_metadata_change( tx_args, Some(validator.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -951,6 +960,7 @@ pub async fn build_update_steward_commission( tx_args, Some(steward.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -1018,6 +1028,7 @@ pub async fn build_resign_steward( tx_args, Some(steward.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -1065,6 +1076,7 @@ pub async fn build_unjail_validator( tx_args, Some(validator.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -1168,6 +1180,7 @@ pub async fn build_deactivate_validator( tx_args, Some(validator.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -1242,6 +1255,7 @@ pub async fn build_reactivate_validator( tx_args, Some(validator.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -1462,6 +1476,7 @@ pub async fn build_redelegation( tx_args, Some(default_address), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -1505,6 +1520,7 @@ pub async fn build_withdraw( tx_args, Some(default_address), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -1591,6 +1607,7 @@ pub async fn build_claim_rewards( tx_args, Some(default_address), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -1694,6 +1711,7 @@ pub async fn build_unbond( tx_args, Some(default_address), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -1928,6 +1946,7 @@ pub async fn build_bond( tx_args, Some(default_address.clone()), default_signer, + vec![], ) .await?; let (fee_amount, updated_balance) = @@ -1992,6 +2011,7 @@ pub async fn build_default_proposal( tx, Some(proposal.proposal.author.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _updated_balance) = @@ -2045,6 +2065,7 @@ pub async fn build_vote_proposal( tx, default_signer.clone(), default_signer.clone(), + vec![], ) .await?; let (fee_amount, _) = @@ -2070,7 +2091,8 @@ pub async fn build_vote_proposal( if !proposal.can_be_voted(current_epoch, is_validator) { edisplay_line!( context.io(), - "Proposal {} cannot be voted on anymore.", + "Proposal {} cannot be voted on, either the voting period ended \ + or the proposal is still pending.", proposal_id ); if is_validator { @@ -2346,7 +2368,8 @@ pub async fn build_become_validator( all_pks.push(protocol_key.clone().unwrap().clone()); let signing_data = - signing::init_validator_signing_data(context, tx_args, all_pks).await?; + signing::aux_signing_data(context, tx_args, None, None, all_pks) + .await?; let (fee_amount, _updated_balance) = validate_transparent_fee(context, tx_args, &signing_data.fee_payer) @@ -2383,6 +2406,7 @@ pub async fn build_pgf_funding_proposal( tx, Some(proposal.proposal.author.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _updated_balance) = @@ -2428,6 +2452,7 @@ pub async fn build_pgf_stewards_proposal( tx, Some(proposal.proposal.author.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _updated_balance) = @@ -2478,6 +2503,7 @@ pub async fn build_ibc_transfer( &args.tx, Some(source.clone()), Some(source.clone()), + vec![], ) .await?; let (fee_per_gas_unit, updated_balance) = @@ -2903,6 +2929,7 @@ pub async fn build_transparent_transfer( &args.tx, source.clone(), source, + vec![], ) .await?; @@ -2987,9 +3014,14 @@ pub async fn build_shielded_transfer( context: &N, args: &mut args::TxShieldedTransfer, ) -> Result<(Tx, SigningTxData)> { - let signing_data = - signing::aux_signing_data(context, &args.tx, Some(MASP), Some(MASP)) - .await?; + let signing_data = signing::aux_signing_data( + context, + &args.tx, + Some(MASP), + Some(MASP), + vec![], + ) + .await?; // Shielded fee payment let fee_per_gas_unit = validate_fee(context, &args.tx).await?; @@ -3134,9 +3166,14 @@ pub async fn build_shielding_transfer( // argument None }; - let signing_data = - signing::aux_signing_data(context, &args.tx, source.clone(), source) - .await?; + let signing_data = signing::aux_signing_data( + context, + &args.tx, + source.clone(), + source, + vec![], + ) + .await?; // Transparent fee payment let (fee_amount, updated_balance) = @@ -3254,9 +3291,14 @@ pub async fn build_unshielding_transfer( context: &N, args: &mut args::TxUnshieldingTransfer, ) -> Result<(Tx, SigningTxData)> { - let signing_data = - signing::aux_signing_data(context, &args.tx, Some(MASP), Some(MASP)) - .await?; + let signing_data = signing::aux_signing_data( + context, + &args.tx, + Some(MASP), + Some(MASP), + vec![], + ) + .await?; // Shielded fee payment let fee_per_gas_unit = validate_fee(context, &args.tx).await?; @@ -3442,7 +3484,7 @@ pub async fn build_init_account( }: &args::TxInitAccount, ) -> Result<(Tx, SigningTxData)> { let signing_data = - signing::aux_signing_data(context, tx_args, None, None).await?; + signing::aux_signing_data(context, tx_args, None, None, vec![]).await?; let (fee_amount, _) = validate_transparent_fee(context, tx_args, &signing_data.fee_payer) .await?; @@ -3528,6 +3570,7 @@ pub async fn build_update_account( tx_args, Some(addr.clone()), default_signer, + vec![], ) .await?; let (fee_amount, _) = @@ -3652,6 +3695,7 @@ pub async fn build_custom( tx_args, Some(owner.clone()), default_signer, + vec![], ) .await?; let fee_amount = validate_fee(context, tx_args).await?; diff --git a/crates/sdk/src/wallet/keys.rs b/crates/sdk/src/wallet/keys.rs index 7c94df49d6..17e0dc4077 100644 --- a/crates/sdk/src/wallet/keys.rs +++ b/crates/sdk/src/wallet/keys.rs @@ -7,6 +7,8 @@ use std::str::FromStr; use borsh::{BorshDeserialize, BorshSerialize}; use borsh_ext::BorshSerializeExt; use data_encoding::HEXLOWER; +use namada_core::masp::{ExtendedSpendingKey, ExtendedViewingKey}; +use namada_core::storage::BlockHeight; use orion::{aead, kdf}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -17,6 +19,11 @@ use crate::wallet::WalletIo; const ENCRYPTED_KEY_PREFIX: &str = "encrypted:"; const UNENCRYPTED_KEY_PREFIX: &str = "unencrypted:"; +/// Type alias for a viewing key with a birthday. +pub type DatedViewingKey = DatedKeypair; +/// Type alias for a spending key with a birthday. +pub type DatedSpendingKey = DatedKeypair; + /// A keypair stored in a wallet #[derive(Debug)] pub enum StoredKeypair @@ -113,6 +120,131 @@ pub enum DeserializeStoredKeypairError { MissingPrefix, } +#[allow(missing_docs)] +#[derive(Error, Debug)] +pub enum DeserializeDatedKeypairError { + #[error("The stored keypair is not valid: {0}")] + InvalidKeypairString(String), + #[error("The stored keypair contains an invalid birthday: {0}")] + InvalidBirthday(String), +} + +/// A keypair with a block height after which it was created +#[derive( + Debug, + Serialize, + Deserialize, + BorshSerialize, + BorshDeserialize, + Ord, + PartialOrd, + Eq, + PartialEq, +)] +pub struct DatedKeypair +where + T: BorshSerialize + BorshDeserialize, +{ + /// The keypair itself + pub key: T, + /// A blockheight that precedes the creation of the keypair + pub birthday: BlockHeight, +} + +impl Copy for DatedKeypair where + T: Copy + BorshSerialize + BorshDeserialize +{ +} + +impl Clone for DatedKeypair +where + T: Clone + BorshSerialize + BorshDeserialize, +{ + fn clone(&self) -> Self { + Self { + key: self.key.clone(), + birthday: self.birthday, + } + } +} + +impl DatedKeypair +where + T: BorshSerialize + BorshDeserialize, +{ + /// Create a new dated keypair. If no birthday is provided, + /// defaults to the first blockheight. + pub fn new(key: T, birthday: Option) -> Self { + Self { + key, + birthday: birthday.unwrap_or(BlockHeight(0)), + } + } + + /// Map the inner key type while maintaining the birthday. + pub fn map(self, func: F) -> DatedKeypair + where + F: Fn(T) -> U, + U: BorshSerialize + BorshDeserialize, + { + DatedKeypair { + key: func(self.key), + birthday: self.birthday, + } + } +} + +impl From for DatedKeypair +where + T: BorshSerialize + BorshDeserialize, +{ + fn from(key: T) -> Self { + Self::new(key, None) + } +} + +impl Display for DatedKeypair +where + T: BorshSerialize + BorshDeserialize + Display, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}<<{}", self.key, self.birthday,) + } +} + +impl FromStr for DatedKeypair +where + T: Serialize + BorshSerialize + BorshDeserialize + FromStr, + ::Err: Display, +{ + type Err = DeserializeDatedKeypairError; + + fn from_str(s: &str) -> Result { + let mut pieces = s.split("<<"); + let key_ser = pieces.next().ok_or( + DeserializeDatedKeypairError::InvalidKeypairString( + "Provided string was empty".to_string(), + ), + )?; + let birthday = pieces + .next() + .map(|b| { + BlockHeight::from_str(b).map_err(|_| { + DeserializeDatedKeypairError::InvalidBirthday(b.to_string()) + }) + }) + .transpose()?; + Ok(Self::new( + T::from_str(key_ser).map_err(|e| { + DeserializeDatedKeypairError::InvalidKeypairString( + e.to_string(), + ) + })?, + birthday, + )) + } +} + /// An encrypted keypair stored in a wallet #[derive(Debug)] pub struct EncryptedKeypair( diff --git a/crates/sdk/src/wallet/mod.rs b/crates/sdk/src/wallet/mod.rs index 3719b97663..a54930878e 100644 --- a/crates/sdk/src/wallet/mod.rs +++ b/crates/sdk/src/wallet/mod.rs @@ -21,6 +21,7 @@ use namada_core::key::*; use namada_core::masp::{ ExtendedSpendingKey, ExtendedViewingKey, PaymentAddress, }; +use namada_core::storage::BlockHeight; use namada_core::time::DateTimeUtc; use namada_ibc::trace::is_ibc_denom; pub use pre_genesis::gen_key_to_store; @@ -31,7 +32,10 @@ use thiserror::Error; use zeroize::Zeroizing; pub use self::derivation_path::{DerivationPath, DerivationPathError}; -pub use self::keys::{DecryptionError, StoredKeypair}; +pub use self::keys::{ + DatedKeypair, DatedSpendingKey, DatedViewingKey, DecryptionError, + StoredKeypair, +}; pub use self::store::{ConfirmationResponse, ValidatorData, ValidatorKeys}; use crate::wallet::store::{derive_hd_secret_key, derive_hd_spending_key}; @@ -257,7 +261,7 @@ pub struct Wallet { utils: U, store: Store, decrypted_key_cache: HashMap, - decrypted_spendkey_cache: HashMap, + decrypted_spendkey_cache: HashMap, } impl From> for Store { @@ -419,7 +423,7 @@ impl Wallet { pub fn find_viewing_key( &self, alias: impl AsRef, - ) -> Result<&ExtendedViewingKey, FindKeyError> { + ) -> Result<&DatedViewingKey, FindKeyError> { self.store.find_viewing_key(alias.as_ref()).ok_or_else(|| { FindKeyError::KeyNotFound(alias.as_ref().to_string()) }) @@ -484,7 +488,7 @@ impl Wallet { } /// Get all known viewing keys by their alias - pub fn get_viewing_keys(&self) -> HashMap { + pub fn get_viewing_keys(&self) -> HashMap { self.store .get_viewing_keys() .iter() @@ -495,7 +499,7 @@ impl Wallet { /// Get all known viewing keys by their alias pub fn get_spending_keys( &self, - ) -> HashMap> { + ) -> HashMap> { self.store .get_spending_keys() .iter() @@ -544,10 +548,12 @@ impl Wallet { /// provided, will prompt for password from stdin. /// Stores the key in decrypted key cache and returns the alias of the key /// and a reference-counting pointer to the key. + #[allow(clippy::too_many_arguments)] pub fn derive_store_spending_key_from_mnemonic_code( &mut self, alias: String, alias_force: bool, + birthday: Option, derivation_path: DerivationPath, mnemonic_passphrase: Option<(Mnemonic, Zeroizing)>, prompt_bip39_passphrase: bool, @@ -573,6 +579,7 @@ impl Wallet { alias, alias_force, spend_key, + birthday, password, Some(derivation_path), ) @@ -633,13 +640,21 @@ impl Wallet { pub fn gen_store_spending_key( &mut self, alias: String, + birthday: Option, password: Option>, force_alias: bool, csprng: &mut (impl CryptoRng + RngCore), ) -> Option<(String, ExtendedSpendingKey)> { let spend_key = gen_spending_key(csprng); - self.insert_spending_key(alias, force_alias, spend_key, password, None) - .map(|alias| (alias, spend_key)) + self.insert_spending_key( + alias, + force_alias, + spend_key, + birthday, + password, + None, + ) + .map(|alias| (alias, spend_key)) } /// Generate a new keypair, derive an implicit address from its public key @@ -736,14 +751,20 @@ impl Wallet { /// into the store with the provided alias, converted to lower case. If the /// alias already exists, optionally force overwrite the key for the /// alias. + /// + /// An optional birthday can be provided saying that this key was created + /// after this blockheight. + /// /// If no encryption password is provided, the key will be stored raw /// without encryption. + /// /// Stores the key in decrypted key cache and returns the alias of the key /// and the key itself. - pub fn derive_store_hd_spendind_key( + pub fn derive_store_hd_spending_key( &mut self, alias: String, force_alias: bool, + birthday: Option, seed: Seed, derivation_path: DerivationPath, password: Option>, @@ -754,6 +775,7 @@ impl Wallet { alias, force_alias, spend_key, + birthday, password, Some(derivation_path), ) @@ -886,7 +908,7 @@ impl Wallet { &mut self, alias: impl AsRef, password: Option>, - ) -> Result { + ) -> Result { // Try cache first if let Some(cached_key) = self .decrypted_spendkey_cache @@ -1082,10 +1104,16 @@ impl Wallet { &mut self, alias: String, view_key: ExtendedViewingKey, + birthday: Option, force_alias: bool, ) -> Option { self.store - .insert_viewing_key::(alias.into(), view_key, force_alias) + .insert_viewing_key::( + alias.into(), + view_key, + birthday, + force_alias, + ) .map(Into::into) } @@ -1095,6 +1123,7 @@ impl Wallet { alias: String, force_alias: bool, spend_key: ExtendedSpendingKey, + birthday: Option, password: Option>, path: Option, ) -> Option { @@ -1102,14 +1131,17 @@ impl Wallet { .insert_spending_key::( alias.into(), spend_key, + birthday, password, path, force_alias, ) .map(|alias| { // Cache the newly added key - self.decrypted_spendkey_cache - .insert(alias.clone(), spend_key); + self.decrypted_spendkey_cache.insert( + alias.clone(), + DatedKeypair::new(spend_key, birthday), + ); alias }) .map(Into::into) diff --git a/crates/sdk/src/wallet/store.rs b/crates/sdk/src/wallet/store.rs index c7c8edc01b..bf071b13df 100644 --- a/crates/sdk/src/wallet/store.rs +++ b/crates/sdk/src/wallet/store.rs @@ -15,12 +15,14 @@ use namada_core::key::*; use namada_core::masp::{ ExtendedSpendingKey, ExtendedViewingKey, PaymentAddress, }; +use namada_core::storage::BlockHeight; use serde::{Deserialize, Serialize}; use zeroize::Zeroizing; use super::alias::{self, Alias}; use super::derivation_path::DerivationPath; use super::pre_genesis; +use crate::wallet::keys::{DatedKeypair, DatedSpendingKey, DatedViewingKey}; use crate::wallet::{StoredKeypair, WalletIo}; /// Actions that can be taken when there is an alias conflict @@ -62,9 +64,9 @@ pub struct ValidatorData { #[derive(Serialize, Deserialize, Debug, Default)] pub struct Store { /// Known viewing keys - view_keys: BTreeMap, + view_keys: BTreeMap, /// Known spending keys - spend_keys: BTreeMap>, + spend_keys: BTreeMap>, /// Payment address book payment_addrs: BiBTreeMap, /// Cryptographic keypairs @@ -133,7 +135,7 @@ impl Store { pub fn find_spending_key( &self, alias: impl AsRef, - ) -> Option<&StoredKeypair> { + ) -> Option<&StoredKeypair> { self.spend_keys.get(&alias.into()) } @@ -141,7 +143,7 @@ impl Store { pub fn find_viewing_key( &self, alias: impl AsRef, - ) -> Option<&ExtendedViewingKey> { + ) -> Option<&DatedViewingKey> { self.view_keys.get(&alias.into()) } @@ -252,14 +254,14 @@ impl Store { } /// Get all known viewing keys by their alias. - pub fn get_viewing_keys(&self) -> &BTreeMap { + pub fn get_viewing_keys(&self) -> &BTreeMap { &self.view_keys } /// Get all known spending keys by their alias. pub fn get_spending_keys( &self, - ) -> &BTreeMap> { + ) -> &BTreeMap> { &self.spend_keys } @@ -368,6 +370,7 @@ impl Store { &mut self, alias: Alias, spendkey: ExtendedSpendingKey, + birthday: Option, password: Option>, path: Option, force: bool, @@ -388,19 +391,22 @@ impl Store { ConfirmationResponse::Replace => {} ConfirmationResponse::Reselect(new_alias) => { return self.insert_spending_key::( - new_alias, spendkey, password, path, false, + new_alias, spendkey, birthday, password, path, false, ); } ConfirmationResponse::Skip => return None, } } self.remove_alias(&alias); + let (spendkey_to_store, _raw_spendkey) = - StoredKeypair::new(spendkey, password); + StoredKeypair::new(DatedKeypair::new(spendkey, birthday), password); self.spend_keys.insert(alias.clone(), spendkey_to_store); // Simultaneously add the derived viewing key to ease balance viewing - let viewkey = - zip32::ExtendedFullViewingKey::from(&spendkey.into()).into(); + let viewkey = DatedKeypair::new( + zip32::ExtendedFullViewingKey::from(&spendkey.into()).into(), + birthday, + ); self.view_keys.insert(alias.clone(), viewkey); path.map(|p| self.derivation_paths.insert(alias.clone(), p)); Some(alias) @@ -411,6 +417,7 @@ impl Store { &mut self, alias: Alias, viewkey: ExtendedViewingKey, + birthday: Option, force: bool, ) -> Option { // abort if the alias is reserved @@ -427,14 +434,16 @@ impl Store { match U::show_overwrite_confirmation(&alias, "a viewing key") { ConfirmationResponse::Replace => {} ConfirmationResponse::Reselect(new_alias) => { - return self - .insert_viewing_key::(new_alias, viewkey, false); + return self.insert_viewing_key::( + new_alias, viewkey, birthday, false, + ); } ConfirmationResponse::Skip => return None, } } self.remove_alias(&alias); - self.view_keys.insert(alias.clone(), viewkey); + self.view_keys + .insert(alias.clone(), DatedKeypair::new(viewkey, birthday)); Some(alias) } diff --git a/crates/shielded_token/src/validation.rs b/crates/shielded_token/src/validation.rs index c52300b4d1..2fe6786b51 100644 --- a/crates/shielded_token/src/validation.rs +++ b/crates/shielded_token/src/validation.rs @@ -236,7 +236,6 @@ where consume_verify_gas(namada_gas::MASP_FIXED_SPEND_GAS)?; consume_verify_gas(checked!( namada_gas::MASP_VARIABLE_SPEND_GAS * remaining_notes as u64 - / namada_gas::MASP_PARALLEL_GAS_DIVIDER )?)?; } @@ -246,7 +245,6 @@ where consume_verify_gas(namada_gas::MASP_FIXED_CONVERT_GAS)?; consume_verify_gas(checked!( namada_gas::MASP_VARIABLE_CONVERT_GAS * remaining_notes as u64 - / namada_gas::MASP_PARALLEL_GAS_DIVIDER )?)?; } @@ -256,7 +254,6 @@ where consume_verify_gas(namada_gas::MASP_FIXED_OUTPUT_GAS)?; consume_verify_gas(checked!( namada_gas::MASP_VARIABLE_OUTPUT_GAS * remaining_notes as u64 - / namada_gas::MASP_PARALLEL_GAS_DIVIDER )?)?; } diff --git a/crates/shielded_token/src/vp.rs b/crates/shielded_token/src/vp.rs index 4f9861d79a..87be0be0ff 100644 --- a/crates/shielded_token/src/vp.rs +++ b/crates/shielded_token/src/vp.rs @@ -60,16 +60,16 @@ where pub _marker: PhantomData<(Params, Gov, Ibc, TransToken, Transfer)>, } -// The balances changed by the transaction, split between masp and non-masp -// balances. The masp collection carries the token addresses. The collection of -// the other balances maps the token address to the addresses of the -// senders/receivers, their balance diff and whether this is positive or -// negative diff +// Balances changed by a transaction #[derive(Default, Debug, Clone)] struct ChangedBalances { + // Maps asset types to their decodings tokens: BTreeMap, + // Map between MASP transparent address and Namada types decoder: BTreeMap, + // Balances before the tx pre: BTreeMap>, + // Balances after the tx post: BTreeMap>, } @@ -416,14 +416,14 @@ where tx } else { // Get the Transaction object from the actions - let masp_section_ref = namada_tx::action::get_masp_section_ref( - &actions, - ) - .ok_or_else(|| { - native_vp::Error::new_const( - "Missing MASP section reference in action", - ) - })?; + let masp_section_ref = + namada_tx::action::get_masp_section_ref(&actions) + .map_err(native_vp::Error::new_const)? + .ok_or_else(|| { + native_vp::Error::new_const( + "Missing MASP section reference in action", + ) + })?; batched_tx .tx .get_masp_section(&masp_section_ref) @@ -673,7 +673,7 @@ fn validate_transparent_input( .checked_sub(&ValueSum::from_pair(asset.token.clone(), amount)) .ok_or_else(|| { Error::NativeVpError(native_vp::Error::SimpleMessage( - "Overflow in bundle balance", + "Underflow in bundle balance", )) })?; } @@ -703,7 +703,7 @@ fn validate_transparent_input( .checked_sub(&ValueSum::from_pair(token.clone(), amount)) .ok_or_else(|| { Error::NativeVpError(native_vp::Error::SimpleMessage( - "Overflow in bundle balance", + "Underflow in bundle balance", )) })?; } @@ -751,7 +751,7 @@ fn validate_transparent_output( .checked_sub(&ValueSum::from_pair(asset.token.clone(), amount)) .ok_or_else(|| { Error::NativeVpError(native_vp::Error::SimpleMessage( - "Overflow in bundle balance", + "Underflow in bundle balance", )) })?; } @@ -766,7 +766,7 @@ fn validate_transparent_output( .checked_sub(&ValueSum::from_pair(token.clone(), amount)) .ok_or_else(|| { Error::NativeVpError(native_vp::Error::SimpleMessage( - "Overflow in bundle balance", + "Underflow in bundle balance", )) })?; } @@ -869,7 +869,7 @@ fn apply_balance_component( }) } -// Verify that the pre balance + the Sapling value balance = the post balance +// Verify that the pre balance - the Sapling value balance = the post balance // using the decodings in tokens and conversion_state for assistance. fn verify_sapling_balancing_value( pre: &ValueSum, @@ -945,18 +945,19 @@ where !is_masp_transfer_key(key) && !is_masp_token_map_key(key) }); + // Check that the transaction didn't write unallowed masp keys + if non_allowed_changes { + return Err(Error::NativeVpError(native_vp::Error::SimpleMessage( + "Found modifications to non-allowed masp keys", + ))); + } let masp_token_map_changed = masp_keys_changed .iter() .any(|key| is_masp_token_map_key(key)); let masp_transfer_changes = masp_keys_changed .iter() .any(|key| is_masp_transfer_key(key)); - // Check that the transaction didn't write unallowed masp keys - if non_allowed_changes { - Err(Error::NativeVpError(native_vp::Error::SimpleMessage( - "Found modifications to non-allowed masp keys", - ))) - } else if masp_token_map_changed && masp_transfer_changes { + if masp_token_map_changed && masp_transfer_changes { Err(Error::NativeVpError(native_vp::Error::SimpleMessage( "Cannot simultaneously do governance proposal and MASP \ transfer", diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index e414eba6f3..b063447d42 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -693,6 +693,7 @@ mod tests { use merkle_tree::NO_DIFF_KEY_PREFIX; use namada_core::address::InternalAddress; use namada_core::borsh::{BorshDeserialize, BorshSerializeExt}; + use namada_core::keccak::KeccakHash; use namada_core::parameters::{EpochDuration, Parameters}; use namada_core::storage::DbKeySeg; use namada_core::time::{self, DateTimeUtc, Duration}; @@ -1279,15 +1280,22 @@ mod tests { ) .prop_map(|kvs| { kvs.into_iter() - .filter_map(|(key, val)| { + .map(|(mut key, val)| { if let DbKeySeg::AddressSeg(Address::Internal( InternalAddress::EthBridgePool, )) = key.segments[0] { - None - } else { - Some((key, Level::Storage(val))) + // This is needed to be able to write this key to DB - + // the merkle tree's `BridgePoolTree::parse_key` + // requires a `KeccakHash` on the 2nd segment + key.segments.insert( + 1, + DbKeySeg::StringSeg( + KeccakHash::default().to_string(), + ), + ); } + (key, Level::Storage(val)) }) .collect::>() }); diff --git a/crates/state/src/wl_state.rs b/crates/state/src/wl_state.rs index 01c0bf3169..60ed93a0c4 100644 --- a/crates/state/src/wl_state.rs +++ b/crates/state/src/wl_state.rs @@ -694,7 +694,7 @@ where /// Commit the current transaction's write log and the entire batch to the /// block. Starts a new transaction and batch write log. pub fn commit_tx_batch(&mut self) { - self.write_log.commit_batch() + self.write_log.commit_batch_and_current_tx() } /// Drop the current transaction's write log when it's declined by any of diff --git a/crates/state/src/write_log.rs b/crates/state/src/write_log.rs index 1f1bb1bc06..61bbfc958f 100644 --- a/crates/state/src/write_log.rs +++ b/crates/state/src/write_log.rs @@ -618,9 +618,15 @@ impl WriteLog { } /// Commit the current tx and the entire batch to the block log. - pub fn commit_batch(&mut self) { + pub fn commit_batch_and_current_tx(&mut self) { self.commit_tx_to_batch(); + self.commit_batch_only(); + } + /// Commit the entire batch to the block log. Doesn't handle the tx write + /// log which might still contain some data and needs to be handled + /// separately. + pub fn commit_batch_only(&mut self) { for log in std::mem::take(&mut self.batch_write_log) { self.block_write_log.extend(log.write_log); self.block_address_gen = log.address_gen; @@ -922,7 +928,7 @@ mod tests { // initialize an account let vp1 = Hash::sha256("vp1".as_bytes()); let (addr1, _) = state.write_log.init_account(&address_gen, vp1, &[]); - state.write_log.commit_batch(); + state.write_log.commit_batch_and_current_tx(); // write values let val1 = "val1".as_bytes().to_vec(); @@ -930,7 +936,7 @@ mod tests { state.write_log.write(&key2, val1.clone()).unwrap(); state.write_log.write(&key3, val1.clone()).unwrap(); state.write_log.write_temp(&key4, val1.clone()).unwrap(); - state.write_log.commit_batch(); + state.write_log.commit_batch_and_current_tx(); // these values are not written due to drop_tx let val2 = "val2".as_bytes().to_vec(); @@ -943,7 +949,7 @@ mod tests { let val3 = "val3".as_bytes().to_vec(); state.write_log.delete(&key2).unwrap(); state.write_log.write(&key3, val3.clone()).unwrap(); - state.write_log.commit_batch(); + state.write_log.commit_batch_and_current_tx(); // commit a block state.commit_block().expect("commit failed"); diff --git a/crates/systems/src/ibc.rs b/crates/systems/src/ibc.rs index 549865104e..c84a4304a9 100644 --- a/crates/systems/src/ibc.rs +++ b/crates/systems/src/ibc.rs @@ -29,7 +29,7 @@ pub trait Read { /// Balances changed by a transaction #[derive(Default, Debug, Clone)] pub struct ChangedBalances { - /// Map between MASP transparent address and namada types + /// Map between MASP transparent address and Namada types pub decoder: BTreeMap, /// Balances before the tx pub pre: BTreeMap>, diff --git a/crates/test_utils/Cargo.toml b/crates/test_utils/Cargo.toml index 3dc882e09f..e308301ac6 100644 --- a/crates/test_utils/Cargo.toml +++ b/crates/test_utils/Cargo.toml @@ -14,5 +14,7 @@ version.workspace = true [dependencies] namada_core = { path = "../core" } +namada_state = { path = "../state" } borsh.workspace = true +prost.workspace = true strum = {version = "0.24", features = ["derive"]} diff --git a/crates/test_utils/src/ibc.rs b/crates/test_utils/src/ibc.rs new file mode 100644 index 0000000000..d9820ef2b1 --- /dev/null +++ b/crates/test_utils/src/ibc.rs @@ -0,0 +1,61 @@ +//! Helper functions for testing IBC client upgrade + +use core::time::Duration; + +use namada_core::ibc::clients::tendermint::client_state::ClientState as TmClientState; +use namada_core::ibc::clients::tendermint::consensus_state::ConsensusState as TmConsensusState; +use namada_core::ibc::clients::tendermint::types::{ + AllowUpdate, ClientState as TmClientStateType, + ConsensusState as TmConsensusStateType, TrustThreshold, +}; +use namada_core::ibc::core::client::types::Height; +use namada_core::ibc::primitives::proto::Any; +use namada_state::ics23_specs::ibc_proof_specs; +use namada_state::{Header, Sha256Hasher}; +use prost::Message; + +pub fn make_new_client_state_bytes(height: u64) -> Vec { + let trust_threshold = TrustThreshold::ONE_THIRD; + let trusting_period = Duration::from_secs(2400); + let unbonding_period = Duration::from_secs(3600); + let max_clock_drift = Duration::new(30, 0); + let height = Height::new(0, height).unwrap(); + + let client_state: TmClientState = TmClientStateType::new( + "upgraded-chain".parse().unwrap(), + trust_threshold, + trusting_period, + unbonding_period, + max_clock_drift, + height, + ibc_proof_specs::().try_into().unwrap(), + vec!["ibc".to_string()], + AllowUpdate { + after_expiry: true, + after_misbehaviour: true, + }, + ) + .unwrap() + .into(); + + Any::from(client_state).encode_to_vec() +} + +pub fn make_new_consensus_state_bytes(header: Header) -> Vec { + let consensus_state: TmConsensusState = TmConsensusStateType { + timestamp: header + .time + .to_rfc3339() + .parse() + .expect("invalid header time"), + root: header.hash.to_vec().into(), + next_validators_hash: header + .next_validators_hash + .to_vec() + .try_into() + .expect("invalid next_validators_hash"), + } + .into(); + + Any::from(consensus_state).encode_to_vec() +} diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 756a0aa5c3..8da61eeb9b 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs @@ -1,5 +1,6 @@ //! Utilities for use in tests. +pub mod ibc; pub mod tx_data; use std::env; @@ -26,6 +27,7 @@ pub enum TestWasms { TxProposalCode, TxProposalMaspRewards, TxProposalIbcTokenInflation, + TxProposalIbcClientUpgrade, TxReadStorageKey, TxWriteStorageKey, VpAlwaysFalse, @@ -53,6 +55,9 @@ impl TestWasms { TestWasms::TxProposalIbcTokenInflation => { "tx_proposal_ibc_token_inflation.wasm" } + TestWasms::TxProposalIbcClientUpgrade => { + "tx_proposal_ibc_client_upgrade.wasm" + } TestWasms::TxReadStorageKey => "tx_read_storage_key.wasm", TestWasms::TxWriteStorageKey => "tx_write.wasm", TestWasms::VpAlwaysFalse => "vp_always_false.wasm", diff --git a/crates/tests/src/e2e/helpers.rs b/crates/tests/src/e2e/helpers.rs index b495c7a4c0..e722dc3ba8 100644 --- a/crates/tests/src/e2e/helpers.rs +++ b/crates/tests/src/e2e/helpers.rs @@ -32,8 +32,8 @@ use namada_sdk::wallet::Wallet; use toml::Value; use super::setup::{ - self, run_gaia_cmd, sleep, NamadaBgCmd, NamadaCmd, Test, ENV_VAR_DEBUG, - ENV_VAR_USE_PREBUILT_BINARIES, + self, ensure_hot_key, run_gaia_cmd, sleep, NamadaBgCmd, NamadaCmd, Test, + ENV_VAR_DEBUG, ENV_VAR_USE_PREBUILT_BINARIES, }; use crate::e2e::setup::{constants, Bin, Who, APPS_PACKAGE}; use crate::strings::{LEDGER_STARTED, TX_APPLIED_SUCCESS}; @@ -219,9 +219,8 @@ pub fn get_pregenesis_pk>( alias: &str, base_dir_path: P, ) -> Option { - let mut wallet = get_pregenesis_wallet(base_dir_path); - let sk = wallet.find_secret_key(alias, None).ok()?; - Some(sk.ref_to()) + let wallet = get_pregenesis_wallet(base_dir_path); + wallet.find_public_key(alias).ok() } /// Get a pregenesis public key. @@ -610,7 +609,9 @@ fn make_hermes_chain_config(test: &Test) -> Value { chain.insert("account_prefix".to_owned(), Value::String("".to_owned())); chain.insert( "key_name".to_owned(), - Value::String(setup::constants::CHRISTEL_KEY.to_owned()), + Value::String( + ensure_hot_key(setup::constants::CHRISTEL_KEY).to_owned(), + ), ); chain.insert("store_prefix".to_owned(), Value::String("ibc".to_owned())); let mut table = toml::map::Map::new(); diff --git a/crates/tests/src/e2e/ibc_tests.rs b/crates/tests/src/e2e/ibc_tests.rs index 60bdd4970e..a4bde77ed9 100644 --- a/crates/tests/src/e2e/ibc_tests.rs +++ b/crates/tests/src/e2e/ibc_tests.rs @@ -66,11 +66,11 @@ use namada_sdk::ibc::core::connection::types::Counterparty as ConnCounterparty; use namada_sdk::ibc::core::host::types::identifiers::{ ChainId, ChannelId, ClientId, ConnectionId, PortId, }; -use namada_sdk::ibc::event as ibc_events; use namada_sdk::ibc::event::IbcEventType; use namada_sdk::ibc::primitives::proto::Any; use namada_sdk::ibc::primitives::{Signer, ToProto}; use namada_sdk::ibc::storage::*; +use namada_sdk::ibc::{event as ibc_events, COMMITMENT_PREFIX}; use namada_sdk::key::PublicKey; use namada_sdk::masp::fs::FsShieldedUtils; use namada_sdk::parameters::{storage as param_storage, EpochDuration}; @@ -94,8 +94,9 @@ use crate::e2e::helpers::{ }; use crate::e2e::ledger_tests::{prepare_proposal_data, write_json_file}; use crate::e2e::setup::{ - self, run_gaia_cmd, run_hermes_cmd, set_ethereum_bridge_mode, setup_gaia, - setup_hermes, sleep, Bin, NamadaCmd, Test, Who, + self, apply_use_device, ensure_hot_addr, ensure_hot_key, run_gaia_cmd, + run_hermes_cmd, set_ethereum_bridge_mode, setup_gaia, setup_hermes, sleep, + Bin, NamadaCmd, Test, Who, }; use crate::strings::{ LEDGER_STARTED, TX_APPLIED_SUCCESS, TX_FAILED, VALIDATOR_NODE, @@ -114,7 +115,7 @@ fn run_ledger_ibc() -> Result<()> { .parameters .ibc_params .default_per_epoch_throughput_limit = Amount::max_signed(); - setup::set_validators(1, genesis, base_dir, |_| 0) + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger_a, ledger_b, test_a, test_b) = run_two_nets(update_genesis)?; let _bg_ledger_a = ledger_a.background(); @@ -205,7 +206,7 @@ fn run_ledger_ibc_with_hermes() -> Result<()> { .parameters .ibc_params .default_per_epoch_throughput_limit = Amount::max_signed(); - setup::set_validators(1, genesis, base_dir, |_| 0) + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger_a, ledger_b, test_a, test_b) = run_two_nets(update_genesis)?; let _bg_ledger_a = ledger_a.background(); @@ -392,7 +393,7 @@ fn ibc_namada_gaia() -> Result<()> { .parameters .ibc_params .default_per_epoch_throughput_limit = Amount::max_signed(); - setup::set_validators(1, genesis, base_dir, |_| 0) + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger, mut ledger_b, test, _test_b) = run_two_nets(update_genesis)?; let _bg_ledger = ledger.background(); @@ -550,6 +551,31 @@ fn ibc_namada_gaia() -> Result<()> { check_balance(&test, AB_VIEWING_KEY, &ibc_denom, 40)?; check_gaia_balance(&test_gaia, GAIA_USER, GAIA_COIN, 810)?; + // Shielding transfer back from Gaia to Namada + let ibc_denom = format!("{port_id_gaia}/{channel_id_gaia}/{token_addr}"); + let memo_path = gen_ibc_shielding_data( + &test, + AA_PAYMENT_ADDRESS, + &ibc_denom, + 100, + &port_id_namada, + &channel_id_namada, + )?; + transfer_from_gaia( + &test_gaia, + GAIA_USER, + AA_PAYMENT_ADDRESS, + get_gaia_denom_hash(&ibc_denom), + 100000000, + &port_id_gaia, + &channel_id_gaia, + Some(memo_path), + )?; + wait_for_packet_relay(&port_id_gaia, &channel_id_gaia, &test)?; + + // Check the token on Namada + check_balance(&test, AA_VIEWING_KEY, APFEL, 100)?; + Ok(()) } @@ -574,7 +600,7 @@ fn pgf_over_ibc_with_hermes() -> Result<()> { .parameters .ibc_params .default_per_epoch_throughput_limit = Amount::max_signed(); - setup::set_validators(1, genesis, base_dir, |_| 0) + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger_a, ledger_b, test_a, test_b) = run_two_nets(update_genesis)?; let _bg_ledger_a = ledger_a.background(); @@ -651,7 +677,7 @@ fn proposal_ibc_token_inflation() -> Result<()> { .parameters .ibc_params .default_per_epoch_throughput_limit = Amount::max_signed(); - setup::set_validators(1, genesis, base_dir, |_| 0) + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger_a, ledger_b, test_a, test_b) = run_two_nets(update_genesis)?; let _bg_ledger_a = ledger_a.background(); @@ -729,6 +755,100 @@ fn proposal_ibc_token_inflation() -> Result<()> { Ok(()) } +#[test] +fn ibc_upgrade_client() -> Result<()> { + // To avoid the client expiration, stop updating the client near the + // first height of the grace epoch. It is set 340 because the grace epoch in + // this test will be Epoch 18 and the number of blocks per epoch is 20. + const MIN_UPGRADE_HEIGHT: u64 = 340; + const PIPELINE_LEN: u64 = 8; + + let update_genesis = + |mut genesis: templates::All, base_dir: &_| { + genesis.parameters.parameters.epochs_per_year = + epochs_per_year_from_min_duration(20); + // for the trusting period of IBC client + genesis.parameters.pos_params.pipeline_len = PIPELINE_LEN; + genesis.parameters.gov_params.min_proposal_grace_epochs = 3; + genesis.parameters.ibc_params.default_mint_limit = + Amount::max_signed(); + genesis + .parameters + .ibc_params + .default_per_epoch_throughput_limit = Amount::max_signed(); + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) + }; + let (ledger_a, ledger_b, test_a, test_b) = run_two_nets(update_genesis)?; + let _bg_ledger_a = ledger_a.background(); + let _bg_ledger_b = ledger_b.background(); + + // Proposal on Chain B + // Delegate some token + delegate_token(&test_b)?; + let rpc_b = get_actor_rpc(&test_b, Who::Validator(0)); + let mut epoch = get_epoch(&test_b, &rpc_b).unwrap(); + let delegated = epoch + PIPELINE_LEN; + while epoch <= delegated { + sleep(10); + epoch = get_epoch(&test_b, &rpc_b).unwrap_or_default(); + } + // Upgrade proposal on Chain B + // The transaction will store the upgraded client state and consensus state + // as if Chain B will be upgraded + let start_epoch = propose_upgrade_client(&test_b)?; + let mut epoch = get_epoch(&test_b, &rpc_b).unwrap(); + // Vote + while epoch < start_epoch { + sleep(10); + epoch = get_epoch(&test_b, &rpc_b).unwrap_or_default(); + } + submit_votes(&test_b)?; + + // creating IBC channel while waiting the grace epoch + setup_hermes(&test_a, &test_b)?; + create_channel_with_hermes(&test_a, &test_b)?; + // Start relaying to update clients + let hermes = run_hermes(&test_a)?; + let bg_hermes = hermes.background(); + + let mut height = query_height(&test_b)?; + while height.revision_height() < MIN_UPGRADE_HEIGHT { + sleep(10); + height = query_height(&test_b)?; + } + // Stop Hermes not to update a client after the upgrade height + let mut hermes = bg_hermes.foreground(); + hermes.interrupt()?; + + // wait for the grace epoch + let grace_epoch = start_epoch + 6u64; + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); + while epoch < grace_epoch { + sleep(10); + epoch = get_epoch(&test_b, &rpc_b).unwrap_or_default(); + } + + // Check the upgraded height + let upgraded_height = get_upgraded_height(&test_b, MIN_UPGRADE_HEIGHT)?; + // Upgrade the IBC client of Chain B on Chain A with Hermes + upgrade_client(&test_a, test_a.net.chain_id.to_string(), upgraded_height)?; + sleep(1); + + // Check the upgraded client + let current_height = query_height(&test_a)?; + let (upgraded_client_state, _, _) = get_client_states( + &test_a, + &"07-tendermint-0".parse().unwrap(), + current_height, + )?; + assert_eq!( + upgraded_client_state.inner().chain_id.as_str(), + "upgraded-chain" + ); + + Ok(()) +} + #[test] fn ibc_rate_limit() -> Result<()> { // Mint limit 2 transfer/channel-0/nam, per-epoch throughput limit 1 NAM @@ -743,7 +863,7 @@ fn ibc_rate_limit() -> Result<()> { .ibc_params .default_per_epoch_throughput_limit = Amount::from_u64(1_000_000); - setup::set_validators(1, genesis, base_dir, |_| 0) + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger_a, ledger_b, test_a, test_b) = run_two_nets(update_genesis)?; let _bg_ledger_a = ledger_a.background(); @@ -1090,6 +1210,55 @@ fn wait_for_packet_relay( Err(eyre!("Pending packet is still left")) } +fn get_upgraded_height(test: &Test, min_upgrade_height: u64) -> Result { + std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); + // Search the storage for the upgraded client state + let rpc = get_actor_rpc(test, Who::Validator(0)); + let max_height = min_upgrade_height + 100; + let mut height = min_upgrade_height; + while height < max_height { + height += 1; + let key = upgraded_client_state_key(Height::new(0, height).unwrap()); + let query_args = [ + "query-bytes", + "--storage-key", + &key.to_string(), + "--node", + &rpc, + ]; + let mut client = run!(test, Bin::Client, query_args, Some(10))?; + if client.exp_string("No data found").is_ok() { + sleep(1); + continue; + } else { + return Ok(height); + } + } + panic!("No upgraded client state on the chain"); +} + +fn upgrade_client( + test: &Test, + host_chain_id: impl AsRef, + upgrade_height: u64, +) -> Result<()> { + let args = [ + "upgrade", + "client", + "--host-chain", + host_chain_id.as_ref(), + "--client", + "07-tendermint-0", + "--upgrade-height", + &upgrade_height.to_string(), + ]; + let mut hermes = run_hermes_cmd(test, args, Some(120))?; + hermes.exp_string("upgraded-chain")?; + hermes.assert_success(); + + Ok(()) +} + fn wait_epochs(test: &Test, duration_epochs: u64) -> Result<()> { std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); let rpc = get_actor_rpc(test, Who::Validator(0)); @@ -1126,8 +1295,8 @@ fn create_client(test_a: &Test, test_b: &Test) -> Result<(ClientId, ClientId)> { let height_a = submit_ibc_tx( test_a, make_ibc_data(message.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1142,8 +1311,8 @@ fn create_client(test_a: &Test, test_b: &Test) -> Result<(ClientId, ClientId)> { let height_b = submit_ibc_tx( test_b, make_ibc_data(message.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1275,8 +1444,8 @@ fn update_client( submit_ibc_tx( target_test, make_ibc_data(message.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1321,8 +1490,8 @@ fn connection_handshake( let height = submit_ibc_tx( test_a, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; let events = get_events(test_a, height)?; @@ -1361,8 +1530,8 @@ fn connection_handshake( let height = submit_ibc_tx( test_b, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; let events = get_events(test_b, height)?; @@ -1394,8 +1563,8 @@ fn connection_handshake( submit_ibc_tx( test_a, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1414,8 +1583,8 @@ fn connection_handshake( submit_ibc_tx( test_b, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1458,8 +1627,8 @@ fn channel_handshake( let height = submit_ibc_tx( test_a, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; let events = get_events(test_a, height)?; @@ -1491,8 +1660,8 @@ fn channel_handshake( let height = submit_ibc_tx( test_b, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; let events = get_events(test_b, height)?; @@ -1518,8 +1687,8 @@ fn channel_handshake( submit_ibc_tx( test_a, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1540,8 +1709,8 @@ fn channel_handshake( submit_ibc_tx( test_b, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1640,8 +1809,8 @@ fn transfer_token( let height = submit_ibc_tx( test_b, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; let events = get_events(test_b, height)?; @@ -1665,8 +1834,8 @@ fn transfer_token( submit_ibc_tx( test_a, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1733,7 +1902,7 @@ fn transfer_on_chain( std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); let rpc = get_actor_rpc(test, Who::Validator(0)); let amount = amount.to_string(); - let tx_args = vec![ + let tx_args = apply_use_device(vec![ kind.as_ref(), "--source", sender.as_ref(), @@ -1747,7 +1916,7 @@ fn transfer_on_chain( signer.as_ref(), "--node", &rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(120))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -1801,8 +1970,8 @@ fn transfer_back( let height = submit_ibc_tx( test_a, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; let events = get_events(test_a, height)?; @@ -1825,8 +1994,8 @@ fn transfer_back( submit_ibc_tx( test_b, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1880,8 +2049,8 @@ fn transfer_timeout( submit_ibc_tx( test_a, make_ibc_data(msg.to_any()), - ALBERT, - ALBERT_KEY, + ensure_hot_addr(ALBERT), + ensure_hot_key(ALBERT_KEY), false, )?; @@ -1934,8 +2103,7 @@ fn get_receipt_absence_proof( } fn commitment_prefix() -> CommitmentPrefix { - CommitmentPrefix::try_from(b"ibc".to_vec()) - .expect("the prefix should be parsable") + CommitmentPrefix::from(COMMITMENT_PREFIX.as_bytes().to_vec()) } fn submit_ibc_tx( @@ -1954,7 +2122,7 @@ fn submit_ibc_tx( let mut client = run!( test, Bin::Client, - [ + apply_use_device(vec![ "tx", "--code-path", TX_IBC_WASM, @@ -1967,10 +2135,10 @@ fn submit_ibc_tx( "--gas-token", NAM, "--gas-limit", - "150000", + "200000", "--node", &rpc - ], + ]), Some(40) )?; client.exp_string(TX_APPLIED_SUCCESS)?; @@ -2001,7 +2169,7 @@ fn transfer( let channel_id = channel_id.to_string(); let port_id = port_id.to_string(); let amount = amount.to_string(); - let mut tx_args = vec![ + let mut tx_args = apply_use_device(vec![ "ibc-transfer", "--source", sender.as_ref(), @@ -2016,10 +2184,10 @@ fn transfer( "--port-id", &port_id, "--gas-limit", - "150000", + "200000", "--node", &rpc, - ]; + ]); if let Some(signer) = signer { tx_args.extend_from_slice(&["--signing-keys", signer]); @@ -2061,7 +2229,7 @@ fn transfer( fn delegate_token(test: &Test) -> Result<()> { std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); let rpc = get_actor_rpc(test, Who::Validator(0)); - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", "validator-0", @@ -2071,7 +2239,7 @@ fn delegate_token(test: &Test) -> Result<()> { "900", "--node", &rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -2115,14 +2283,14 @@ fn propose_funding( start_epoch, ); - let submit_proposal_args = vec![ + let submit_proposal_args = apply_use_device(vec![ "init-proposal", "--pgf-funding", "--data-path", proposal_json_path.to_str().unwrap(), "--node", &rpc_a, - ]; + ]); let mut client = run!(test_a, Bin::Client, submit_proposal_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -2159,16 +2327,60 @@ fn propose_inflation(test: &Test) -> Result { let proposal_json_path = test.test_dir.path().join("proposal.json"); write_json_file(proposal_json_path.as_path(), proposal_json); + let submit_proposal_args = apply_use_device(vec![ + "init-proposal", + "--data-path", + proposal_json_path.to_str().unwrap(), + "--gas-limit", + "4000000", + "--node", + &rpc, + ]); + let mut client = run!(test, Bin::Client, submit_proposal_args, Some(100))?; + client.exp_string(TX_APPLIED_SUCCESS)?; + client.assert_success(); + Ok(start_epoch.into()) +} + +fn propose_upgrade_client(test: &Test) -> Result { + std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); + let albert = find_address(test, ALBERT)?; + let rpc = get_actor_rpc(test, Who::Validator(0)); + let epoch = get_epoch(test, &rpc)?; + let start_epoch = (epoch.0 + 3) / 3 * 3; + let proposal_json = serde_json::json!({ + "proposal": { + "content": { + "title": "TheTitle", + "authors": "test@test.com", + "discussions-to": "www.github.com/anoma/aip/1", + "created": "2022-03-10T08:54:37Z", + "license": "MIT", + "abstract": "upgrade chain", + "motivation": "upgrade chain", + "details": "upgrade chain", + "requires": "2" + }, + "author": albert, + "voting_start_epoch": start_epoch, + "voting_end_epoch": start_epoch + 3_u64, + "activation_epoch": start_epoch + 6_u64, + }, + "data": TestWasms::TxProposalIbcClientUpgrade.read_bytes() + }); + let proposal_json_path = test.test_dir.path().join("proposal.json"); + write_json_file(proposal_json_path.as_path(), proposal_json); + let submit_proposal_args = vec![ "init-proposal", "--data-path", proposal_json_path.to_str().unwrap(), "--gas-limit", - "2000000", + "4000000", "--node", &rpc, ]; - let mut client = run!(test, Bin::Client, submit_proposal_args, Some(100))?; + let mut client = run!(test, Bin::Client, submit_proposal_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); Ok(start_epoch.into()) @@ -2200,7 +2412,7 @@ fn submit_votes(test: &Test) -> Result<()> { client.assert_success(); // Send different yay vote from delegator to check majority on 1/3 - let submit_proposal_vote_delagator = vec![ + let submit_proposal_vote_delagator = apply_use_device(vec![ "vote-proposal", "--proposal-id", "0", @@ -2210,7 +2422,7 @@ fn submit_votes(test: &Test) -> Result<()> { BERTHA, "--node", &rpc, - ]; + ]); let mut client = run!(test, Bin::Client, submit_proposal_vote_delagator, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; diff --git a/crates/tests/src/e2e/ledger_tests.rs b/crates/tests/src/e2e/ledger_tests.rs index 97413bb057..010d19ad4d 100644 --- a/crates/tests/src/e2e/ledger_tests.rs +++ b/crates/tests/src/e2e/ledger_tests.rs @@ -27,6 +27,7 @@ use namada_core::chain::ChainId; use namada_core::token::NATIVE_MAX_DECIMAL_PLACES; use namada_sdk::address::Address; use namada_sdk::storage::Epoch; +use namada_sdk::time::DateTimeUtc; use namada_sdk::token; use namada_test_utils::TestWasms; use serde::Serialize; @@ -44,13 +45,14 @@ use crate::e2e::helpers::{ is_debug_mode, parse_reached_epoch, }; use crate::e2e::setup::{ - self, allow_duplicate_ips, default_port_offset, sleep, Bin, Who, + self, allow_duplicate_ips, apply_use_device, default_port_offset, sleep, + Bin, Who, }; use crate::strings::{ LEDGER_SHUTDOWN, LEDGER_STARTED, NON_VALIDATOR_NODE, TX_APPLIED_SUCCESS, TX_REJECTED, VALIDATOR_NODE, }; -use crate::{run, run_as}; +use crate::{run, run_as, LastSignState}; const ENV_VAR_NAMADA_SEED_NODES: &str = "NAMADA_SEED_NODES"; @@ -129,7 +131,13 @@ fn test_node_connectivity_and_consensus() -> Result<()> { // Setup 2 genesis validator nodes let test = setup::network( |genesis, base_dir| { - setup::set_validators(2, genesis, base_dir, default_port_offset) + setup::set_validators( + 2, + genesis, + base_dir, + default_port_offset, + vec![], + ) }, None, )?; @@ -167,7 +175,7 @@ fn test_node_connectivity_and_consensus() -> Result<()> { let _ = epoch_sleep(&test, &validator_one_rpc, 720)?; // 3. Submit a valid token transfer tx - let tx_args = [ + let tx_args = apply_use_device(vec![ "transparent-transfer", "--source", BERTHA, @@ -183,7 +191,7 @@ fn test_node_connectivity_and_consensus() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -504,6 +512,7 @@ fn pos_bonds() -> Result<()> { genesis, base_dir, default_port_offset, + vec![], ); genesis.transactions.bond = Some({ let wallet = get_pregenesis_wallet(base_dir); @@ -557,7 +566,7 @@ fn pos_bonds() -> Result<()> { client.assert_success(); // 3. Submit a delegation to the first genesis validator - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", "validator-0", @@ -569,13 +578,13 @@ fn pos_bonds() -> Result<()> { BERTHA_KEY, "--node", &validator_0_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); // 4. Submit a re-delegation from the first to the second genesis validator - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "redelegate", "--source-validator", "validator-0", @@ -589,7 +598,7 @@ fn pos_bonds() -> Result<()> { BERTHA_KEY, "--node", &validator_0_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -613,7 +622,7 @@ fn pos_bonds() -> Result<()> { client.assert_success(); // 6. Submit an unbond of the delegation from the first validator - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "unbond", "--validator", "validator-0", @@ -625,14 +634,14 @@ fn pos_bonds() -> Result<()> { BERTHA_KEY, "--node", &validator_0_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; let expected = "Amount 1600.000000 withdrawable starting from epoch "; let _ = client.exp_regex(&format!("{expected}.*\n"))?; client.assert_success(); // 7. Submit an unbond of the re-delegation from the second validator - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "unbond", "--validator", "validator-1", @@ -644,7 +653,7 @@ fn pos_bonds() -> Result<()> { BERTHA_KEY, "--node", &validator_0_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; let expected = "Amount 1600.000000 withdrawable starting from epoch "; let (_unread, matched) = client.exp_regex(&format!("{expected}.*\n"))?; @@ -698,7 +707,7 @@ fn pos_bonds() -> Result<()> { client.assert_success(); // 10. Submit a withdrawal of the delegation - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "withdraw", "--validator", "validator-0", @@ -708,13 +717,13 @@ fn pos_bonds() -> Result<()> { BERTHA_KEY, "--node", &validator_0_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); // 11. Submit an withdrawal of the re-delegation - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "withdraw", "--validator", "validator-1", @@ -724,7 +733,7 @@ fn pos_bonds() -> Result<()> { BERTHA_KEY, "--node", &validator_0_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -756,6 +765,7 @@ fn pos_init_validator() -> Result<()> { genesis, base_dir, default_port_offset, + vec![], ); println!("{:?}", genesis.transactions.bond); let stake = genesis @@ -799,7 +809,7 @@ fn pos_init_validator() -> Result<()> { // 2. Initialize a new validator account with the non-validator node let new_validator = "new-validator"; let _new_validator_key = format!("{}-key", new_validator); - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "init-validator", "--alias", new_validator, @@ -818,7 +828,7 @@ fn pos_init_validator() -> Result<()> { "--node", &non_validator_rpc, "--unsafe-dont-encrypt", - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -853,7 +863,7 @@ fn pos_init_validator() -> Result<()> { // 3. Submit a delegation to the new validator First, transfer some tokens // to the validator's key for fees: - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "transparent-transfer", "--source", BERTHA, @@ -867,14 +877,14 @@ fn pos_init_validator() -> Result<()> { BERTHA_KEY, "--node", &non_validator_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); // Then self-bond the tokens: let delegation = 5_u64; let delegation_str = &delegation.to_string(); - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", new_validator, @@ -886,14 +896,14 @@ fn pos_init_validator() -> Result<()> { BERTHA_KEY, "--node", &non_validator_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); // 4. Transfer some NAM to the new validator let validator_stake_str = &validator_stake.to_string_native(); - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "transparent-transfer", "--source", BERTHA, @@ -907,13 +917,13 @@ fn pos_init_validator() -> Result<()> { BERTHA_KEY, "--node", &non_validator_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); // 5. Submit a self-bond for the new validator - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", new_validator, @@ -921,7 +931,7 @@ fn pos_init_validator() -> Result<()> { validator_stake_str, "--node", &non_validator_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -973,7 +983,7 @@ fn pos_init_validator() -> Result<()> { fn ledger_many_txs_in_a_block() -> Result<()> { let test = Arc::new(setup::network( |genesis, base_dir: &_| { - setup::set_validators(1, genesis, base_dir, |_| 0) + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }, // Set 10s consensus timeout to have more time to submit txs Some("10s"), @@ -995,7 +1005,7 @@ fn ledger_many_txs_in_a_block() -> Result<()> { let validator_one_rpc = Arc::new(get_actor_rpc(&test, Who::Validator(0))); // A token transfer tx args - let tx_args = Arc::new(vec![ + let tx_args = Arc::new(apply_use_device(vec![ "transparent-transfer", "--source", BERTHA, @@ -1007,30 +1017,42 @@ fn ledger_many_txs_in_a_block() -> Result<()> { "1.01", "--signing-keys", BERTHA_KEY, - "--node", - ]); - - // 2. Spawn threads each submitting token transfer tx - // We collect to run the threads in parallel. - #[allow(clippy::needless_collect)] - let tasks: Vec> = (0..4) - .map(|_| { - let test = Arc::clone(&test); - let validator_one_rpc = Arc::clone(&validator_one_rpc); - let tx_args = Arc::clone(&tx_args); - std::thread::spawn(move || { - let mut args = (*tx_args).clone(); - args.push(&*validator_one_rpc); - let mut client = run!(*test, Bin::Client, args, Some(80))?; - client.exp_string(TX_APPLIED_SUCCESS)?; - client.assert_success(); - let res: Result<()> = Ok(()); - res + ])); + + if tx_args.contains(&"--use-device") { + // Sequentialize transaction signing when hardware wallet is involved + for _ in 0..4 { + let mut args = (*tx_args).clone(); + args.push("--node"); + args.push(&*validator_one_rpc); + let mut client = run!(*test, Bin::Client, args, Some(80))?; + client.exp_string(TX_APPLIED_SUCCESS)?; + client.assert_success(); + } + } else { + // 2. Spawn threads each submitting token transfer tx + // We collect to run the threads in parallel. + #[allow(clippy::needless_collect)] + let tasks: Vec> = (0..4) + .map(|_| { + let test = Arc::clone(&test); + let validator_one_rpc = Arc::clone(&validator_one_rpc); + let tx_args = Arc::clone(&tx_args); + std::thread::spawn(move || { + let mut args = (*tx_args).clone(); + args.push("--node"); + args.push(&*validator_one_rpc); + let mut client = run!(*test, Bin::Client, args, Some(80))?; + client.exp_string(TX_APPLIED_SUCCESS)?; + client.assert_success(); + let res: Result<()> = Ok(()); + res + }) }) - }) - .collect(); - for task in tasks.into_iter() { - task.join().unwrap()?; + .collect(); + for task in tasks.into_iter() { + task.join().unwrap()?; + } } // Wait to commit a block let mut ledger = bg_ledger.foreground(); @@ -1056,13 +1078,13 @@ where /// In this test we intentionally make a validator node double sign blocks /// to test that slashing evidence is received and processed by the ledger /// correctly: -/// 1. Run 2 genesis validator ledger nodes -/// 2. Copy the first genesis validator base-dir -/// 3. Increment its ports and generate new node ID to avoid conflict -/// 4. Run it to get it to double vote and sign blocks -/// 5. Submit a valid token transfer tx to validator 0 -/// 6. Wait for double signing evidence -/// 7. Make sure the the first validator can proceed to the next epoch +/// 1. Copy the first genesis validator base-dir +/// 2. Increment its ports and generate new node ID to avoid conflict +/// 3. Run 2 genesis validator ledger nodes +/// 4. Run the copied validator to get it to double vote and sign blocks +/// 5. Wait for double signing evidence +/// 6. Wait for slash processing epoch +/// 7. Make sure the first validator can proceed to the next epoch #[test] fn double_signing_gets_slashed() -> Result<()> { use std::net::SocketAddr; @@ -1086,9 +1108,22 @@ fn double_signing_gets_slashed() -> Result<()> { ); // Make faster epochs to be more likely to discover boundary issues genesis.parameters.parameters.min_num_of_blocks = 2; - setup::set_validators(4, genesis, base_dir, default_port_offset) + setup::set_validators( + 2, + genesis, + base_dir, + default_port_offset, + vec![ + // The duplicate validator who will double sign and get + // slashed has less stake so that the 2nd validator has + // majority to continue producing blocks + token::Amount::native_whole(30_000), + token::Amount::native_whole(100_000), + ], + ) }, - None, + // Slow down the blocks to 5s + Some("5s"), )?; allow_duplicate_ips(&test, &test.net.chain_id, Who::Validator(0)); @@ -1110,27 +1145,7 @@ fn double_signing_gets_slashed() -> Result<()> { ); println!("pipeline_len: {}", pipeline_len); - // 1. Run 2 genesis validator ledger nodes - let _bg_validator_0 = - start_namada_ledger_node_wait_wasm(&test, Some(0), Some(40))? - .background(); - let bg_validator_1 = - start_namada_ledger_node_wait_wasm(&test, Some(1), Some(40))? - .background(); - - let mut validator_2 = - run_as!(test, Who::Validator(2), Bin::Node, &["ledger"], Some(40))?; - validator_2.exp_string(LEDGER_STARTED)?; - validator_2.exp_string(VALIDATOR_NODE)?; - let _bg_validator_2 = validator_2.background(); - - let mut validator_3 = - run_as!(test, Who::Validator(3), Bin::Node, &["ledger"], Some(40))?; - validator_3.exp_string(LEDGER_STARTED)?; - validator_3.exp_string(VALIDATOR_NODE)?; - let _bg_validator_3 = validator_3.background(); - - // 2. Copy the first genesis validator base-dir + // 1. Copy the first genesis validator base-dir let validator_0_base_dir = test.get_base_dir(Who::Validator(0)); let validator_0_base_dir_copy = test .test_dir @@ -1149,7 +1164,7 @@ fn double_signing_gets_slashed() -> Result<()> { ) .unwrap(); - // 3. Increment its ports and generate new node ID to avoid conflict + // 2. Increment its ports and generate new node ID to avoid conflict // Same as in `genesis/e2e-tests-single-node.toml` for `validator-0` let net_address_0 = SocketAddr::from_str("127.0.0.1:27656").unwrap(); @@ -1206,8 +1221,17 @@ fn double_signing_gets_slashed() -> Result<()> { let _node_pk = client::utils::write_tendermint_node_key(&tm_home_dir, node_sk); - // 4. Run it to get it to double vote and sign block + // 3. Run 2 genesis validator ledger nodes + let _bg_validator_0 = + start_namada_ledger_node_wait_wasm(&test, Some(0), Some(40))? + .background(); + let bg_validator_1 = + start_namada_ledger_node_wait_wasm(&test, Some(1), Some(100))? + .background(); + + // 4. Run the copied validator to get it to double vote and sign blocks let loc = format!("{}:{}", std::file!(), std::line!()); + // This node will only connect to `validator_1`, so that nodes // `validator_0` and `validator_0_copy` should start double signing let mut validator_0_copy = setup::run_cmd( @@ -1215,42 +1239,92 @@ fn double_signing_gets_slashed() -> Result<()> { ["ledger"], Some(40), &test.working_dir, - validator_0_base_dir_copy, + &validator_0_base_dir_copy, loc, )?; validator_0_copy.exp_string(LEDGER_STARTED)?; validator_0_copy.exp_string(VALIDATOR_NODE)?; - let _bg_validator_0_copy = validator_0_copy.background(); + let mut bg_validator_0_copy = validator_0_copy.background(); - // 5. Submit a valid token transfer tx to validator 0 - let validator_one_rpc = get_actor_rpc(&test, Who::Validator(0)); - let tx_args = [ - "transparent-transfer", - "--source", - BERTHA, - "--target", - ALBERT, - "--token", - NAM, - "--amount", - "10.1", - "--node", - &validator_one_rpc, - ]; - let _client = run!(test, Bin::Client, tx_args, Some(100))?; - // We don't wait for tx result - sometimes the node may crash before while - // it's being applied, because the slashed validator will stop voting and - // rewards calculation then fails with `InsufficientVotes`. - - // 6. Wait for double signing evidence + // 5. Wait for double signing evidence let mut validator_1 = bg_validator_1.foreground(); - validator_1.exp_string("Processing evidence")?; + const RETRIES: usize = 5; + for i in 0..=RETRIES { + if let Err(e) = validator_1.exp_string("Processing evidence") { + #[allow(clippy::disallowed_methods)] + let now = DateTimeUtc::now().to_rfc3339(); + println!("Failed to get evidence on {}. try at {now}", i + 1); + + // Often, the `validator_0_copy` detects the duplicate votes and + // doesn't report them. It then stores the sig in + // `priv_validator_state.json` which prevents it from attempting to + // double sign again. + // To get around it, we try to stop the `validator_1` that owns the + // consensus so that it stops producing blocks while we're clearing + // out the signature and restarting the duplicate validator node. + validator_1.interrupt()?; + validator_1.exp_string(LEDGER_SHUTDOWN)?; + validator_1.assert_success(); + drop(validator_1); + let mut validator_0_copy = bg_validator_0_copy.foreground(); + validator_0_copy.interrupt()?; + validator_0_copy.exp_string(LEDGER_SHUTDOWN)?; + validator_0_copy.assert_success(); + drop(validator_0_copy); + + // Clear out last sig + let chain_dir = + validator_0_base_dir_copy.join(test.net.chain_id.to_string()); + let validator_state_path = + chain_dir.join("cometbft/data/priv_validator_state.json"); + if validator_state_path.exists() { + let bytes = std::fs::read(&validator_state_path).unwrap(); + let mut state: LastSignState = + serde_json::from_slice(&bytes).unwrap(); + state.signature = None; + state.signbytes = None; + std::fs::write( + &validator_state_path, + serde_json::to_vec(&state).unwrap(), + ) + .unwrap() + } + + if i == RETRIES { + return Err(e); + } + + // Restart the nodes + let loc = format!("{}:{}", std::file!(), std::line!()); + bg_validator_0_copy = setup::run_cmd( + Bin::Node, + ["ledger"], + Some(40), + &test.working_dir, + &validator_0_base_dir_copy, + loc, + )? + .background(); + validator_1 = start_namada_ledger_node(&test, Some(1), Some(100))?; + } else { + break; + } + } + #[allow(clippy::disallowed_methods)] + let now = DateTimeUtc::now().to_rfc3339(); + println!("Got evidence at {now}"); println!("\nPARSING SLASH MESSAGE\n"); let (_, res) = validator_1 .exp_regex(r"Slashing [a-z0-9]+ for Duplicate vote in epoch [0-9]+") .unwrap(); println!("\n{res}\n"); + + // Stop the duplicate validator to avoid getting any more slashes + let mut validator_0_copy = bg_validator_0_copy.foreground(); + validator_0_copy.interrupt()?; + validator_0_copy.assert_success(); + // Wait to commit a block validator_1.exp_regex(r"Committed block hash.*, height: [0-9]+")?; let bg_validator_1 = validator_1.background(); @@ -1262,10 +1336,11 @@ fn double_signing_gets_slashed() -> Result<()> { + 1u64; // Query slashes + let validator_1_rpc = get_actor_rpc(&test, Who::Validator(1)); let mut client = run!( test, Bin::Client, - &["slashes", "--node", &validator_one_rpc], + &["slashes", "--node", &validator_1_rpc], Some(40) )?; client.exp_string("No processed slashes found")?; @@ -1280,9 +1355,9 @@ fn double_signing_gets_slashed() -> Result<()> { println!("\n{processing_epoch}\n"); - // 6. Wait for processing epoch + // 6. Wait for slash processing epoch loop { - let epoch = epoch_sleep(&test, &validator_one_rpc, 240)?; + let epoch = epoch_sleep(&test, &validator_1_rpc, 240)?; println!("\nCurrent epoch: {}", epoch); if epoch > processing_epoch { break; @@ -1297,7 +1372,7 @@ fn double_signing_gets_slashed() -> Result<()> { "--validator", "validator-0", "--node", - &validator_one_rpc + &validator_1_rpc ], Some(40) )?; @@ -1306,7 +1381,7 @@ fn double_signing_gets_slashed() -> Result<()> { let mut client = run!( test, Bin::Client, - &["slashes", "--node", &validator_one_rpc], + &["slashes", "--node", &validator_1_rpc], Some(40) )?; client.exp_string("Processed slashes:")?; @@ -1317,7 +1392,7 @@ fn double_signing_gets_slashed() -> Result<()> { "--validator", "validator-0-validator", "--node", - &validator_one_rpc, + &validator_1_rpc, ]; let mut client = run_as!(test, Who::Validator(0), Bin::Client, tx_args, Some(40))?; @@ -1325,9 +1400,9 @@ fn double_signing_gets_slashed() -> Result<()> { client.assert_success(); // Wait until pipeline epoch to see if the validator is back in consensus - let cur_epoch = epoch_sleep(&test, &validator_one_rpc, 240)?; + let cur_epoch = epoch_sleep(&test, &validator_1_rpc, 240)?; loop { - let epoch = epoch_sleep(&test, &validator_one_rpc, 240)?; + let epoch = epoch_sleep(&test, &validator_1_rpc, 240)?; println!("\nCurrent epoch: {}", epoch); if epoch > cur_epoch + pipeline_len + 1u64 { break; @@ -1341,7 +1416,7 @@ fn double_signing_gets_slashed() -> Result<()> { "--validator", "validator-0", "--node", - &validator_one_rpc + &validator_1_rpc ], Some(40) )?; @@ -1349,8 +1424,8 @@ fn double_signing_gets_slashed() -> Result<()> { .exp_regex(r"Validator [a-z0-9]+ is in the .* set") .unwrap(); - // 7. Make sure the the first validator can proceed to the next epoch - epoch_sleep(&test, &validator_one_rpc, 120)?; + // 7. Make sure the first validator can proceed to the next epoch + epoch_sleep(&test, &validator_1_rpc, 120)?; // Make sure there are no errors let mut validator_1 = bg_validator_1.foreground(); @@ -1371,7 +1446,7 @@ fn test_epoch_sleep() -> Result<()> { genesis.parameters.parameters.epochs_per_year = epochs_per_year_from_min_duration(30); genesis.parameters.parameters.min_num_of_blocks = 1; - setup::set_validators(1, genesis, base_dir, |_| 0) + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }, None, )?; @@ -1454,6 +1529,7 @@ fn deactivate_and_reactivate_validator() -> Result<()> { genesis, base_dir, default_port_offset, + vec![], ); genesis.transactions.bond = Some({ let wallet = get_pregenesis_wallet(base_dir); @@ -1627,6 +1703,7 @@ fn test_invalid_validator_txs() -> Result<()> { genesis, base_dir, default_port_offset, + vec![], ); genesis.transactions.bond = Some({ let wallet = get_pregenesis_wallet(base_dir); @@ -1799,7 +1876,13 @@ fn change_consensus_key() -> Result<()> { genesis.parameters.parameters.epochs_per_year = 31_536_000; genesis.parameters.pos_params.pipeline_len = pipeline_len; genesis.parameters.pos_params.unbonding_len = 4; - setup::set_validators(2, genesis, base_dir, default_port_offset) + setup::set_validators( + 2, + genesis, + base_dir, + default_port_offset, + vec![], + ) }, None, )?; @@ -1908,7 +1991,7 @@ fn proposal_change_shielded_reward() -> Result<()> { let test = setup::network( |mut genesis, base_dir: &_| { genesis.parameters.gov_params.max_proposal_code_size = 600000; - setup::set_validators(1, genesis, base_dir, |_| 0u16) + setup::set_validators(1, genesis, base_dir, |_| 0u16, vec![]) }, None, )?; @@ -1929,7 +2012,7 @@ fn proposal_change_shielded_reward() -> Result<()> { let validator_0_rpc = get_actor_rpc(&test, Who::Validator(0)); // 1.1 Delegate some token - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", "validator-0", @@ -1939,7 +2022,7 @@ fn proposal_change_shielded_reward() -> Result<()> { "900", "--node", &validator_0_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, tx_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -1954,15 +2037,15 @@ fn proposal_change_shielded_reward() -> Result<()> { ); let validator_one_rpc = get_actor_rpc(&test, Who::Validator(0)); - let submit_proposal_args = vec![ + let submit_proposal_args = apply_use_device(vec![ "init-proposal", "--data-path", valid_proposal_json_path.to_str().unwrap(), "--gas-limit", - "2000000", + "4000000", "--node", &validator_one_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, submit_proposal_args, Some(40))?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -2014,7 +2097,7 @@ fn proposal_change_shielded_reward() -> Result<()> { client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); - let submit_proposal_vote_delagator = vec![ + let submit_proposal_vote_delagator = apply_use_device(vec![ "vote-proposal", "--proposal-id", "0", @@ -2024,7 +2107,7 @@ fn proposal_change_shielded_reward() -> Result<()> { BERTHA, "--node", &validator_one_rpc, - ]; + ]); let mut client = run!(test, Bin::Client, submit_proposal_vote_delagator, Some(40))?; @@ -2130,13 +2213,7 @@ fn test_sync_chain() -> Result<()> { // Setup the chain let mut join_network = setup::run_cmd( Bin::Client, - [ - "utils", - "join-network", - "--chain-id", - chain_id_raw.as_str(), - "--dont-prefetch-wasm", - ], + ["utils", "join-network", "--chain-id", chain_id_raw.as_str()], Some(60), &test.working_dir, base_dir, @@ -2233,7 +2310,13 @@ where fn rollback() -> Result<()> { let test = setup::network( |genesis, base_dir| { - setup::set_validators(1, genesis, base_dir, default_port_offset) + setup::set_validators( + 1, + genesis, + base_dir, + default_port_offset, + vec![], + ) }, // slow block production rate Some("5s"), @@ -2258,7 +2341,7 @@ fn rollback() -> Result<()> { let ledger = ledger.background(); // send a few transactions - let txs_args = vec![vec![ + let txs_args = vec![apply_use_device(vec![ "transparent-transfer", "--source", BERTHA, @@ -2272,7 +2355,7 @@ fn rollback() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ]]; + ])]; for tx_args in &txs_args { let mut client = run!(test, Bin::Client, tx_args, Some(40))?; @@ -2338,7 +2421,13 @@ fn masp_txs_and_queries() -> Result<()> { genesis.parameters.parameters.epochs_per_year = epochs_per_year_from_min_duration(3600); genesis.parameters.parameters.min_num_of_blocks = 1; - setup::set_validators(1, genesis, base_dir, default_port_offset) + setup::set_validators( + 1, + genesis, + base_dir, + default_port_offset, + vec![], + ) }, None, )?; @@ -2358,7 +2447,7 @@ fn masp_txs_and_queries() -> Result<()> { .background(); let rpc_address = get_actor_rpc(&test, who); - let _ep1 = epoch_sleep(&test, &rpc_address, 720)?; + wait_for_block_height(&test, &rpc_address, 1, 30)?; // add necessary viewing keys to shielded context let mut sync = run_as!( diff --git a/crates/tests/src/e2e/setup.rs b/crates/tests/src/e2e/setup.rs index ba61380b9b..e3fa45c778 100644 --- a/crates/tests/src/e2e/setup.rs +++ b/crates/tests/src/e2e/setup.rs @@ -23,10 +23,9 @@ use namada_apps_lib::client::utils::{ self, validator_pre_genesis_dir, validator_pre_genesis_txs_file, }; use namada_apps_lib::config::genesis::utils::read_toml; -use namada_apps_lib::config::genesis::{ - templates, transactions, GenesisAddress, -}; +use namada_apps_lib::config::genesis::{templates, transactions}; use namada_apps_lib::config::{ethereum_bridge, genesis, Config}; +use namada_apps_lib::wallet::defaults::{derive_template_dir, is_use_device}; use namada_apps_lib::{config, wallet}; use namada_core::address::Address; use namada_core::collections::HashMap; @@ -66,12 +65,6 @@ const ENV_VAR_TEMP_PATH: &str = "NAMADA_E2E_TEMP_PATH"; pub const ENV_VAR_USE_PREBUILT_BINARIES: &str = "NAMADA_E2E_USE_PREBUILT_BINARIES"; -/// The E2E tests genesis config source. -/// This file must contain a single validator with alias "validator-0". -/// To add more validators, use the [`set_validators`] function in the call to -/// setup the [`network`]. -#[allow(dead_code)] -pub const SINGLE_NODE_NET_GENESIS: &str = "genesis/localnet"; /// An E2E test network. #[derive(Debug, Clone)] pub struct Network { @@ -81,6 +74,35 @@ pub struct Network { /// Offset the ports used in the network configuration to avoid shared resources pub const ANOTHER_CHAIN_PORT_OFFSET: u16 = 1000; +/// Apply the --use-device flag depending on the environment variables +pub fn apply_use_device(mut tx_args: Vec<&str>) -> Vec<&str> { + if is_use_device() { + tx_args.push("--use-device"); + } + tx_args +} + +/// Replace the given key with a key that is stored unencrypted in the wallet. +/// This is useful for IBC tests where a keypair needs to be added to the Hermes +/// keyring or where IBC messages unsupported by the hardware wallet need to be +/// signed +pub fn ensure_hot_key(key: &str) -> &str { + if is_use_device() { + constants::FRANK_KEY + } else { + key + } +} + +/// Same as ensure_hot_key but for addressees +pub fn ensure_hot_addr(key: &str) -> &str { + if is_use_device() { + constants::FRANK + } else { + key + } +} + /// Default functions for offsetting ports when /// adding multiple validators to a network pub fn default_port_offset(ix: u8) -> u16 { @@ -133,12 +155,16 @@ pub fn set_ethereum_bridge_mode( /// the [`network`]'s first argument's closure, e.g. `set_validators(2, _)` will /// configure a network with 2 validators. /// +/// Default self-bond amount for each validator is 100 000, which can be +/// overridden via the `bonds` argument indexed by the validator number. +/// /// INVARIANT: Do not call this function more than once on the same config. pub fn set_validators( num: u8, mut genesis: templates::All, base_dir: &Path, port_offset: F, + bonds: Vec, ) -> templates::All where F: Fn(u8) -> u16, @@ -227,7 +253,7 @@ where .get_mut(&Alias::from_str("nam").expect("Infallible")) .expect("NAM balances should exist in pre-genesis wallet already"); nam_balances.0.insert( - GenesisAddress::PublicKey(StringEncoded::new(sk.ref_to())), + (&sk.ref_to()).into(), token::DenominatedAmount::new( token::Amount::from_uint(1000000, NATIVE_MAX_DECIMAL_PLACES) .unwrap(), @@ -235,7 +261,7 @@ where ), ); nam_balances.0.insert( - GenesisAddress::EstablishedAddress(validator_address.clone()), + Address::Established(validator_address.clone()), token::DenominatedAmount::new( token::Amount::from_uint(2000000, NATIVE_MAX_DECIMAL_PLACES) .unwrap(), @@ -246,6 +272,11 @@ where // account to a validator account let net_addr = format!("127.0.0.1:{}", 27656 + port_offset(val)); let validator_address_str = validator_address.to_string(); + let bond_amount = bonds + .get(usize::from(val)) + .copied() + .unwrap_or(token::Amount::native_whole(100_000)) + .to_string_native(); let args = vec![ "utils", "init-genesis-validator", @@ -264,7 +295,7 @@ where "--email", "null@null.net", "--self-bond-amount", - "100000", + &bond_amount, "--unsafe-dont-encrypt", ]; let mut init_genesis_validator = run_cmd( @@ -292,7 +323,7 @@ where let mut sign_pre_genesis_txs = run_cmd( Bin::Client, args, - Some(15), + Some(30), &working_dir(), base_dir, format!("{}:{}", std::file!(), std::line!()), @@ -326,7 +357,9 @@ where /// Setup a network with a single genesis validator node. pub fn single_node_net() -> Result { network( - |genesis, base_dir: &_| set_validators(1, genesis, base_dir, |_| 0u16), + |genesis, base_dir: &_| { + set_validators(1, genesis, base_dir, |_| 0u16, vec![]) + }, None, ) } @@ -348,7 +381,7 @@ pub fn network( let test_dir = TestDir::new(); // Open the source genesis file templates - let templates_dir = working_dir.join("genesis").join("localnet"); + let templates_dir = derive_template_dir(&working_dir); println!( "{} {}.", "Loading genesis templates from".yellow(), @@ -434,7 +467,7 @@ pub fn network( let mut init_network = run_cmd( Bin::Client, args, - Some(15), + Some(30), &working_dir, &genesis_dir, format!("{}:{}", std::file!(), std::line!()), @@ -506,7 +539,6 @@ pub fn network( net.chain_id.as_str(), "--genesis-validator", &alias, - "--dont-prefetch-wasm", ], Some(5), &working_dir, @@ -537,7 +569,6 @@ pub fn network( "--add-persistent-peers", "--chain-id", net.chain_id.as_str(), - "--dont-prefetch-wasm", ], Some(5), &working_dir, @@ -1412,6 +1443,9 @@ pub mod constants { pub const DAEWON_KEY: &str = "Daewon-key"; pub const ESTER: &str = "Ester"; pub const MATCHMAKER_KEY: &str = "matchmaker-key"; + // Special user that must be stored unencrypted for IBC tests + pub const FRANK: &str = "Frank"; + pub const FRANK_KEY: &str = "Frank-key"; // Shielded spending and viewing keys and payment addresses pub const A_SPENDING_KEY: &str = "zsknam1qdrk9kd8qqqqpqy3pxzxu2kexydl7ug22s3808htl604emmz9qlde9cl9mx6euhvh3cpl9w7guustfzjxsyaeqtefhden6q8776t9cr9vkqztj7u0mgs5k9nz945sypev9ppptn5d85as3ccsnu3q6g3acqp2gpsrwe6naqg3stqp43uk9x2cj79gcxuum8a7jayjqlv4ptcfnunqkqzsj6m2r3sn8ft0tyqqpv28nghe4ag68eccaqx7v5f65he95g5uwq2wr4yuqc06jgc7"; diff --git a/crates/tests/src/integration/ledger_tests.rs b/crates/tests/src/integration/ledger_tests.rs index def29d1a0a..dcd163acfd 100644 --- a/crates/tests/src/integration/ledger_tests.rs +++ b/crates/tests/src/integration/ledger_tests.rs @@ -6,7 +6,9 @@ use borsh::BorshDeserialize; use borsh_ext::BorshSerializeExt; use color_eyre::eyre::Result; use data_encoding::HEXLOWER; -use namada_apps_lib::wallet::defaults::{self, albert_keypair}; +use namada_apps_lib::wallet::defaults::{ + self, get_unencrypted_keypair, is_use_device, +}; use namada_core::dec::Dec; use namada_core::hash::Hash; use namada_core::storage::{DbColFam, Epoch, Key}; @@ -28,6 +30,7 @@ use crate::e2e::setup::constants::{ ALBERT, ALBERT_KEY, APFEL, BERTHA, BERTHA_KEY, BTC, CHRISTEL, CHRISTEL_KEY, DAEWON, DOT, ESTER, ETH, GOVERNANCE_ADDRESS, KARTOFFEL, NAM, SCHNITZEL, }; +use crate::e2e::setup::{apply_use_device, ensure_hot_key}; use crate::integration::helpers::{ find_address, prepare_steward_commission_update_data, }; @@ -80,7 +83,7 @@ fn ledger_txs_and_queries() -> Result<()> { let txs_args = vec![ // 2. Submit a token transfer tx (from an established account) - vec![ + apply_use_device(vec![ "transparent-transfer", "--source", BERTHA, @@ -94,9 +97,9 @@ fn ledger_txs_and_queries() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ], + ]), // Submit a token transfer tx (from an ed25519 implicit account) - vec![ + apply_use_device(vec![ "transparent-transfer", "--source", DAEWON, @@ -110,9 +113,9 @@ fn ledger_txs_and_queries() -> Result<()> { DAEWON, "--node", &validator_one_rpc, - ], + ]), // Submit a token transfer tx (from a secp256k1 implicit account) - vec![ + apply_use_device(vec![ "transparent-transfer", "--source", ESTER, @@ -124,10 +127,10 @@ fn ledger_txs_and_queries() -> Result<()> { "10.1", "--node", &validator_one_rpc, - ], + ]), // 3. Submit a transaction to update an account's validity // predicate - vec![ + apply_use_device(vec![ "update-account", "--address", BERTHA, @@ -137,9 +140,9 @@ fn ledger_txs_and_queries() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ], + ]), // 4. Submit a custom tx - vec![ + apply_use_device(vec![ "tx", "--code-path", TX_TRANSFER_WASM, @@ -151,9 +154,9 @@ fn ledger_txs_and_queries() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ], + ]), // 5. Submit a tx to initialize a new account - vec![ + apply_use_device(vec![ "init-account", "--public-keys", // Value obtained from `namada_sdk::key::ed25519::tests::gen_keypair` @@ -168,9 +171,9 @@ fn ledger_txs_and_queries() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ], + ]), // 5. Submit a tx to initialize a new multisig account - vec![ + apply_use_device(vec![ "init-account", "--public-keys", &multisig_account, @@ -184,12 +187,13 @@ fn ledger_txs_and_queries() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ], + ]), ]; for tx_args in &txs_args { for &dry_run in &[true, false] { - let tx_args = if dry_run && tx_args[0] == "tx" { + let tx_args = if dry_run && (tx_args[0] == "tx" || is_use_device()) + { continue; } else if dry_run { [tx_args.clone(), vec!["--dry-run"]].concat() @@ -358,7 +362,7 @@ fn invalid_transactions() -> Result<()> { // 2. Submit an invalid transaction (trying to transfer tokens should fail // in the user's VP due to the wrong signer) - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "transparent-transfer", "--source", BERTHA, @@ -373,7 +377,7 @@ fn invalid_transactions() -> Result<()> { "--node", &validator_one_rpc, "--force", - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); assert_matches!(captured.result, Ok(_)); @@ -387,7 +391,7 @@ fn invalid_transactions() -> Result<()> { } let daewon_lower = DAEWON.to_lowercase(); - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "transparent-transfer", "--source", DAEWON, @@ -404,7 +408,7 @@ fn invalid_transactions() -> Result<()> { "--force", "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); assert!(captured.contains(TX_INSUFFICIENT_BALANCE)); @@ -496,7 +500,7 @@ fn pos_rewards() -> Result<()> { .unwrap(); // Claim rewards - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "claim-rewards", "--validator", "validator-0-validator", @@ -504,7 +508,7 @@ fn pos_rewards() -> Result<()> { "validator-0-account-key", "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); println!("{:?}", captured.result); assert_matches!(captured.result, Ok(_)); @@ -553,7 +557,7 @@ fn test_bond_queries() -> Result<()> { let validator_alias = "validator-0-validator"; // 2. Submit a delegation to the genesis validator - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", validator_alias, @@ -561,13 +565,13 @@ fn test_bond_queries() -> Result<()> { "100", "--ledger-address", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); assert_matches!(captured.result, Ok(_)); assert!(captured.contains(TX_APPLIED_SUCCESS)); // 3. Submit a delegation to the genesis validator - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", "validator-0-validator", @@ -579,7 +583,7 @@ fn test_bond_queries() -> Result<()> { BERTHA_KEY, "--ledger-address", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); assert_matches!(captured.result, Ok(_)); @@ -591,7 +595,7 @@ fn test_bond_queries() -> Result<()> { } // 4. Submit another delegation to the genesis validator - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", validator_alias, @@ -603,13 +607,13 @@ fn test_bond_queries() -> Result<()> { BERTHA_KEY, "--ledger-address", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); assert_matches!(captured.result, Ok(_)); assert!(captured.contains(TX_APPLIED_SUCCESS)); // 5. Submit an unbond of the delegation - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "unbond", "--validator", validator_alias, @@ -621,7 +625,7 @@ fn test_bond_queries() -> Result<()> { BERTHA_KEY, "--ledger-address", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); assert_matches!(captured.result, Ok(_)); @@ -685,7 +689,7 @@ fn proposal_submission() -> Result<()> { let (mut node, _services) = setup::setup()?; // 1.1 Delegate some token - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", "validator-0-validator", @@ -695,7 +699,7 @@ fn proposal_submission() -> Result<()> { "900", "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); assert_matches!(captured.result, Ok(_)); assert!(captured.contains(TX_APPLIED_SUCCESS)); @@ -709,15 +713,15 @@ fn proposal_submission() -> Result<()> { 12, ); - let submit_proposal_args = vec![ + let submit_proposal_args = apply_use_device(vec![ "init-proposal", "--data-path", valid_proposal_json_path.to_str().unwrap(), "--gas-limit", - "2000000", + "5000000", "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, submit_proposal_args)); assert_matches!(captured.result, Ok(_)); @@ -767,66 +771,12 @@ fn proposal_submission() -> Result<()> { assert_matches!(captured.result, Ok(_)); assert!(captured.contains("nam: 500")); - // 6. Submit an invalid proposal - // proposal is invalid due to voting_end_epoch - voting_start_epoch < 3 - let invalid_proposal_json = prepare_proposal_data( - node.test_dir.path(), - albert, - TestWasms::TxProposalCode.read_bytes(), - 1, - ); - - let submit_proposal_args = vec![ - "init-proposal", - "--data-path", - invalid_proposal_json.to_str().unwrap(), - "--node", - &validator_one_rpc, - ]; - - let captured = - CapturedOutput::of(|| run(&node, Bin::Client, submit_proposal_args)); - assert!(captured.result.is_err()); - println!("{:?}", captured.result); - assert!(captured.err_contains( - "Proposal data are invalid: Invalid proposal start epoch: 1 must be \ - greater than current epoch .* and a multiple of 3" - )); - - // 7. Check invalid proposal was not submitted - let proposal_query_args = vec![ - "query-proposal", - "--proposal-id", - "1", - "--node", - &validator_one_rpc, - ]; - let captured = - CapturedOutput::of(|| run(&node, Bin::Client, proposal_query_args)); - assert_matches!(captured.result, Ok(_)); - assert!(captured.contains("No proposal found with id: 1")); - - // 8. Query token balance (funds shall not be submitted) - let query_balance_args = vec![ - "balance", - "--owner", - ALBERT, - "--token", - NAM, - "--node", - &validator_one_rpc, - ]; - let captured = - CapturedOutput::of(|| run(&node, Bin::Client, query_balance_args)); - assert_matches!(captured.result, Ok(_)); - assert!(captured.contains("nam: 1979500")); - // 9.1. Send a yay vote from a validator while node.current_epoch().0 <= 13 { node.next_epoch(); } - let submit_proposal_vote = vec![ + let submit_proposal_vote = apply_use_device(vec![ "vote-proposal", "--proposal-id", "0", @@ -836,7 +786,7 @@ fn proposal_submission() -> Result<()> { "validator-0-validator", "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, submit_proposal_vote)); @@ -844,7 +794,7 @@ fn proposal_submission() -> Result<()> { assert!(captured.contains(TX_APPLIED_SUCCESS)); // 9.2. Send a valid yay vote from a delegator with bonds - let submit_proposal_vote_delegator = vec![ + let submit_proposal_vote_delegator = apply_use_device(vec![ "vote-proposal", "--proposal-id", "0", @@ -854,7 +804,7 @@ fn proposal_submission() -> Result<()> { BERTHA, "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| { run(&node, Bin::Client, submit_proposal_vote_delegator) @@ -863,7 +813,7 @@ fn proposal_submission() -> Result<()> { assert!(captured.contains(TX_APPLIED_SUCCESS)); // 10. Send a yay vote from a non-validator/non-delegator user - let submit_proposal_vote = vec![ + let submit_proposal_vote = apply_use_device(vec![ "vote-proposal", "--proposal-id", "0", @@ -873,7 +823,7 @@ fn proposal_submission() -> Result<()> { CHRISTEL, "--node", &validator_one_rpc, - ]; + ]); // Expect a client failure here let captured = @@ -949,7 +899,7 @@ fn proposal_submission() -> Result<()> { assert!(captured.contains(".*Min. proposal grace epochs: 9.*")); // 15. Try to initialize a new account with the no more allowlisted vp - let init_account = vec![ + let init_account = apply_use_device(vec![ "init-account", "--public-keys", // Value obtained from @@ -965,7 +915,7 @@ fn proposal_submission() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, init_account)); assert_matches!(captured.result, Ok(_)); assert!( @@ -975,7 +925,7 @@ fn proposal_submission() -> Result<()> { // 16. Submit a tx touching a previous account with the no more allowlisted // vp and verify that the transaction succeeds, i.e. the non allowlisted // vp can still run - let transfer = vec![ + let transfer = apply_use_device(vec![ "transparent-transfer", "--source", BERTHA, @@ -989,7 +939,7 @@ fn proposal_submission() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, transfer)); assert_matches!(captured.result, Ok(_)); assert!(captured.contains(TX_APPLIED_SUCCESS)); @@ -1018,7 +968,7 @@ fn pgf_governance_proposal() -> Result<()> { // 1. start the ledger node let (mut node, _services) = setup::setup()?; - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "bond", "--validator", "validator-0-validator", @@ -1028,7 +978,7 @@ fn pgf_governance_proposal() -> Result<()> { "900", "--ledger-address", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); assert_matches!(captured.result, Ok(_)); assert!(captured.contains(TX_APPLIED_SUCCESS)); @@ -1042,14 +992,14 @@ fn pgf_governance_proposal() -> Result<()> { let valid_proposal_json_path = prepare_proposal_data(node.test_dir.path(), albert, pgf_stewards, 12); - let submit_proposal_args = vec![ + let submit_proposal_args = apply_use_device(vec![ "init-proposal", "--pgf-stewards", "--data-path", valid_proposal_json_path.to_str().unwrap(), "--ledger-address", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, submit_proposal_args)); assert_matches!(captured.result, Ok(_)); @@ -1103,7 +1053,7 @@ fn pgf_governance_proposal() -> Result<()> { node.next_epoch(); } - let submit_proposal_vote = vec![ + let submit_proposal_vote = apply_use_device(vec![ "vote-proposal", "--proposal-id", "0", @@ -1113,14 +1063,14 @@ fn pgf_governance_proposal() -> Result<()> { "validator-0-validator", "--ledger-address", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, submit_proposal_vote)); assert_matches!(captured.result, Ok(_)); assert!(captured.contains(TX_APPLIED_SUCCESS)); // Send different yay vote from delegator to check majority on 1/3 - let submit_proposal_vote_delegator = vec![ + let submit_proposal_vote_delegator = apply_use_device(vec![ "vote-proposal", "--proposal-id", "0", @@ -1130,7 +1080,7 @@ fn pgf_governance_proposal() -> Result<()> { BERTHA, "--ledger-address", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| { run(&node, Bin::Client, submit_proposal_vote_delegator) }); @@ -1218,14 +1168,14 @@ fn pgf_governance_proposal() -> Result<()> { let valid_proposal_json_path = prepare_proposal_data(node.test_dir.path(), albert, pgf_funding, 36); - let submit_proposal_args = vec![ + let submit_proposal_args = apply_use_device(vec![ "init-proposal", "--pgf-funding", "--data-path", valid_proposal_json_path.to_str().unwrap(), "--ledger-address", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, submit_proposal_args)); assert_matches!(captured.result, Ok(_)); @@ -1301,7 +1251,7 @@ fn pgf_steward_change_commission() -> Result<()> { commission, ); // Update steward commissions - let tx_args = vec![ + let tx_args = apply_use_device(vec![ "update-steward-rewards", "--steward", ALBERT, @@ -1309,7 +1259,7 @@ fn pgf_steward_change_commission() -> Result<()> { commission_path.to_str().unwrap(), "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, tx_args)); assert_matches!(captured.result, Ok(_)); assert!(captured.contains(TX_APPLIED_SUCCESS)); @@ -1437,7 +1387,7 @@ fn implicit_account_reveal_pk() -> Result<()> { // Apply the key_alias once the key is generated to obtain tx args let tx_args = tx_args(&key_alias); // 2b. Send some funds to the implicit account. - let credit_args = vec![ + let credit_args = apply_use_device(vec![ "transparent-transfer", "--source", BERTHA, @@ -1451,7 +1401,7 @@ fn implicit_account_reveal_pk() -> Result<()> { BERTHA_KEY, "--node", &validator_one_rpc, - ]; + ]); run(&node, Bin::Client, credit_args)?; node.assert_success(); @@ -1511,7 +1461,7 @@ fn change_validator_metadata() -> Result<()> { assert!(captured.contains("max change per epoch:")); // 3. Add some metadata to the validator - let metadata_change_args = vec![ + let metadata_change_args = apply_use_device(vec![ "change-metadata", "--validator", "validator-0-validator", @@ -1525,7 +1475,7 @@ fn change_validator_metadata() -> Result<()> { "theokayestvalidator.com", "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, metadata_change_args)); @@ -1548,7 +1498,7 @@ fn change_validator_metadata() -> Result<()> { assert!(captured.contains("max change per epoch:")); // 5. Remove the validator website - let metadata_change_args = vec![ + let metadata_change_args = apply_use_device(vec![ "change-metadata", "--validator", "validator-0-validator", @@ -1556,7 +1506,7 @@ fn change_validator_metadata() -> Result<()> { "", "--node", &validator_one_rpc, - ]; + ]); let captured = CapturedOutput::of(|| run(&node, Bin::Client, metadata_change_args)); assert_matches!(captured.result, Ok(_)); @@ -1599,7 +1549,7 @@ fn enforce_fee_payment() -> Result<()> { vec![ "balance", "--owner", - ALBERT_KEY, + ensure_hot_key(ALBERT_KEY), "--token", NAM, "--node", @@ -1613,10 +1563,10 @@ fn enforce_fee_payment() -> Result<()> { run( &node, Bin::Client, - vec![ + apply_use_device(vec![ "transparent-transfer", "--source", - ALBERT_KEY, + ensure_hot_key(ALBERT_KEY), "--target", BERTHA, "--token", @@ -1632,7 +1582,7 @@ fn enforce_fee_payment() -> Result<()> { "--dump-tx", "--ledger-address", validator_one_rpc, - ], + ]), )?; node.assert_success(); let file_path = tempdir @@ -1649,10 +1599,10 @@ fn enforce_fee_payment() -> Result<()> { run( &node, Bin::Client, - vec![ + apply_use_device(vec![ "transparent-transfer", "--source", - ALBERT_KEY, + ensure_hot_key(ALBERT_KEY), "--target", CHRISTEL, "--token", @@ -1660,13 +1610,13 @@ fn enforce_fee_payment() -> Result<()> { "--amount", "50", "--gas-payer", - ALBERT_KEY, + ensure_hot_key(ALBERT_KEY), "--output-folder-path", tempdir.path().to_str().unwrap(), "--dump-tx", "--ledger-address", validator_one_rpc, - ], + ]), )?; node.assert_success(); let file_path = tempdir @@ -1680,7 +1630,9 @@ fn enforce_fee_payment() -> Result<()> { txs_bytes.push(std::fs::read(&file_path).unwrap()); std::fs::remove_file(&file_path).unwrap(); - let sk = albert_keypair(); + let sk = get_unencrypted_keypair( + &ensure_hot_key("albert-key").to_ascii_lowercase(), + ); let pk = sk.to_public(); let native_token = node @@ -1740,7 +1692,7 @@ fn enforce_fee_payment() -> Result<()> { vec![ "balance", "--owner", - ALBERT_KEY, + ensure_hot_key(ALBERT_KEY), "--token", NAM, "--node", diff --git a/crates/tests/src/integration/masp.rs b/crates/tests/src/integration/masp.rs index e719c58c1c..b9f6854647 100644 --- a/crates/tests/src/integration/masp.rs +++ b/crates/tests/src/integration/masp.rs @@ -685,6 +685,8 @@ fn masp_incentives() -> Result<()> { CHRISTEL, "--token", NAM, + "--gas-limit", + "200000", "--amount", "1.451732", "--signing-keys", diff --git a/crates/tests/src/integration/setup.rs b/crates/tests/src/integration/setup.rs index 6b062169a3..4d557d747a 100644 --- a/crates/tests/src/integration/setup.rs +++ b/crates/tests/src/integration/setup.rs @@ -14,6 +14,7 @@ use namada_apps_lib::config::genesis::templates::load_and_validate; use namada_apps_lib::config::TendermintMode; use namada_apps_lib::facade::tendermint::Timeout; use namada_apps_lib::facade::tendermint_proto::google::protobuf::Timestamp; +use namada_apps_lib::wallet::defaults::derive_template_dir; use namada_apps_lib::wallet::pre_genesis; use namada_core::chain::ChainIdPrefix; use namada_core::collections::HashMap; @@ -27,7 +28,7 @@ use namada_sdk::dec::Dec; use namada_sdk::token; use namada_sdk::wallet::alias::Alias; -use crate::e2e::setup::{copy_wasm_to_chain_dir, SINGLE_NODE_NET_GENESIS}; +use crate::e2e::setup::copy_wasm_to_chain_dir; /// Env. var for keeping temporary files created by the integration tests const ENV_VAR_KEEP_TEMP: &str = "NAMADA_INT_KEEP_TEMP"; @@ -49,7 +50,7 @@ pub fn initialize_genesis( _ => false, }; let test_dir = TestDir::new(); - let template_dir = working_dir.join(SINGLE_NODE_NET_GENESIS); + let template_dir = derive_template_dir(&working_dir); // Copy genesis files to test directory. let mut templates = templates::All::read_toml_files(&template_dir) diff --git a/crates/tests/src/lib.rs b/crates/tests/src/lib.rs index e4717b8c12..e76a81a430 100644 --- a/crates/tests/src/lib.rs +++ b/crates/tests/src/lib.rs @@ -26,3 +26,34 @@ pub mod log { } pub use namada_sdk::*; + +/// A type corresponding to cometbft `FilePVLastSignState` in `privval/file.go` +/// stored in `cometbft/data/priv_validator_state.json` +#[derive(Debug, serde::Serialize, serde::Deserialize)] +struct LastSignState { + // i64 encoded as a string + pub height: String, + pub round: i32, + pub step: i8, + #[serde(skip_serializing_if = "Option::is_none")] + pub signature: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub signbytes: Option, +} + +#[test] +fn test_last_sign_state_encoding() { + // An example taken from `cometbft/data/priv_validate_state.json` + let example_state = serde_json::json!({ + "height": "36", + "round": 0, + "step": 3, + "signature": "pBNefaWQtXBKXGCmiwdz3SVifEoytgoRD/Ui0JiA7giZYTwInKcLITyZLVHnZ/nbKq8CULoMrLhasAHPsS6HAw==", + "signbytes": "8301080211240000000000000022480A202B35C46A53F9E93AC38BDF7CAC71CAEBEC3889308BBB6012D848A67FE1756923122408011220530C5626D32F9D0D95E8494396BD510560357439BBC7B2F2F689E1246281A9C72A0C08DCE5EDB50610D2AAABCC03321E6532652D746573742E336636616131326538323736346261613631376637" + }); + + let state: LastSignState = serde_json::from_value(example_state).unwrap(); + assert_eq!(&state.height, "36"); + assert_eq!(state.round, 0); + assert_eq!(state.step, 3); +} diff --git a/crates/tests/src/vm_host_env/ibc.rs b/crates/tests/src/vm_host_env/ibc.rs index 654442dbe2..35a186a58c 100644 --- a/crates/tests/src/vm_host_env/ibc.rs +++ b/crates/tests/src/vm_host_env/ibc.rs @@ -59,7 +59,7 @@ pub use namada_sdk::ibc::storage::{ connection_counter_key, connection_key, consensus_state_key, port_key, }; pub use namada_sdk::ibc::trace::ibc_token; -use namada_sdk::ibc::MsgTransfer; +use namada_sdk::ibc::{MsgTransfer, COMMITMENT_PREFIX}; use namada_sdk::parameters::storage::get_epoch_duration_storage_key; use namada_sdk::parameters::EpochDuration; use namada_sdk::proof_of_stake::test_utils::get_dummy_genesis_validator; @@ -83,7 +83,6 @@ use crate::tx::*; const ADDRESS: Address = Address::Internal(InternalAddress::Ibc); pub const ANY_DENOMINATION: u8 = token::NATIVE_MAX_DECIMAL_PLACES; -const COMMITMENT_PREFIX: &[u8] = b"ibc"; pub struct TestIbcVp<'a> { pub ibc: IbcVp<'a, TestState, WasmCacheRwAccess>, @@ -428,7 +427,7 @@ pub fn msg_connection_open_init(client_id: ClientId) -> MsgConnectionOpenInit { let counterparty_client_id = ClientId::new(&client_type().to_string(), 42).unwrap(); let commitment_prefix = - CommitmentPrefix::try_from(COMMITMENT_PREFIX.to_vec()).unwrap(); + CommitmentPrefix::from(COMMITMENT_PREFIX.as_bytes().to_vec()); let counterparty = ConnCounterparty::new(counterparty_client_id, None, commitment_prefix); @@ -509,8 +508,7 @@ fn dummy_connection_counterparty() -> ConnCounterparty { .expect("invalid client ID"); let conn_id = ConnectionId::new(12); let commitment_prefix = - CommitmentPrefix::try_from(COMMITMENT_PREFIX.to_vec()) - .expect("the prefix should be parsable"); + CommitmentPrefix::from(COMMITMENT_PREFIX.as_bytes().to_vec()); ConnCounterparty::new(client_id, Some(conn_id), commitment_prefix) } diff --git a/crates/tx/src/action.rs b/crates/tx/src/action.rs index 323de1754c..a25049623b 100644 --- a/crates/tx/src/action.rs +++ b/crates/tx/src/action.rs @@ -122,18 +122,28 @@ fn storage_key() -> storage::Key { } /// Helper function to get the optional masp section reference from the -/// [`Actions`]. If more than one [`MaspAction`] has been found we return the -/// first one -pub fn get_masp_section_ref(actions: &Actions) -> Option { - actions.iter().find_map(|action| { - if let Action::Masp(MaspAction::MaspSectionRef(masp_section_ref)) = - action - { - Some(masp_section_ref.to_owned()) - } else { - None - } - }) +/// [`Actions`]. If more than one [`MaspAction`] is found we return an error +pub fn get_masp_section_ref( + actions: &Actions, +) -> Result, &'static str> { + let masp_sections: Vec<_> = actions + .iter() + .filter_map(|action| { + if let Action::Masp(MaspAction::MaspSectionRef(masp_section_ref)) = + action + { + Some(masp_section_ref.to_owned()) + } else { + None + } + }) + .collect(); + + if masp_sections.len() > 1 { + Err("The transaction pushed multiple MASP Actions") + } else { + Ok(masp_sections.first().cloned()) + } } /// Helper function to check if the action is IBC shielding transfer diff --git a/crates/tx/src/data/mod.rs b/crates/tx/src/data/mod.rs index 11386c0d02..ea73b8ed70 100644 --- a/crates/tx/src/data/mod.rs +++ b/crates/tx/src/data/mod.rs @@ -26,7 +26,7 @@ use namada_core::ibc::IbcTxDataRefs; use namada_core::masp::MaspTxRefs; use namada_core::storage; use namada_events::Event; -use namada_gas::{VpsGas, WholeGas}; +use namada_gas::WholeGas; use namada_macros::BorshDeserializer; #[cfg(feature = "migrations")] use namada_migrations::*; @@ -481,8 +481,6 @@ pub struct VpsResult { pub accepted_vps: BTreeSet
, /// The addresses whose VPs rejected the transaction pub rejected_vps: BTreeSet
, - /// The total gas used by all the VPs - pub gas_used: VpsGas, /// Errors occurred in any of the VPs, if any pub errors: Vec<(Address, String)>, /// Validity predicate status flags, containing info diff --git a/crates/tx/src/data/pgf.rs b/crates/tx/src/data/pgf.rs index 8b2c9f3944..2da23db625 100644 --- a/crates/tx/src/data/pgf.rs +++ b/crates/tx/src/data/pgf.rs @@ -47,7 +47,7 @@ pub mod tests { /// Generate an arbitraary steward commission update pub fn arb_update_steward_commission()( steward in arb_non_internal_address(), - commission in collection::hash_map(arb_non_internal_address(), arb_dec(), 0..10), + commission in collection::btree_map(arb_non_internal_address(), arb_dec(), 0..10), ) -> UpdateStewardCommission { UpdateStewardCommission { steward, diff --git a/crates/tx/src/types.rs b/crates/tx/src/types.rs index c0eeb34935..51830063d5 100644 --- a/crates/tx/src/types.rs +++ b/crates/tx/src/types.rs @@ -1770,6 +1770,17 @@ pub struct IndexedTx { pub index: TxIndex, } +impl IndexedTx { + /// Create an [`IndexedTx`] that upper bounds the entire range of + /// txs in a block with some height `height`. + pub const fn entire_block(height: BlockHeight) -> Self { + Self { + height, + index: TxIndex(u32::MAX), + } + } +} + impl Default for IndexedTx { fn default() -> Self { Self { diff --git a/crates/tx_prelude/src/ibc.rs b/crates/tx_prelude/src/ibc.rs index d82cedc461..bede0056ad 100644 --- a/crates/tx_prelude/src/ibc.rs +++ b/crates/tx_prelude/src/ibc.rs @@ -8,7 +8,9 @@ use namada_core::address::Address; use namada_core::token::Amount; pub use namada_ibc::event::{IbcEvent, IbcEventType}; pub use namada_ibc::storage::{ - burn_tokens, is_ibc_key, mint_limit_key, mint_tokens, throughput_limit_key, + burn_tokens, client_state_key, is_ibc_key, mint_limit_key, mint_tokens, + throughput_limit_key, upgraded_client_state_key, + upgraded_consensus_state_key, }; pub use namada_ibc::trace::ibc_token; pub use namada_ibc::{ diff --git a/crates/vm/src/wasm/compilation_cache/common.rs b/crates/vm/src/wasm/compilation_cache/common.rs index 43a2cd35c1..0f3aaaa242 100644 --- a/crates/vm/src/wasm/compilation_cache/common.rs +++ b/crates/vm/src/wasm/compilation_cache/common.rs @@ -116,7 +116,7 @@ impl Cache { /// Get a WASM module from LRU cache, from a file or compile it and cache /// it. If the cache access is set to [`crate::WasmCacheRwAccess`], it /// updates the position in the LRU cache. Otherwise, the compiled - /// module will not be be cached, if it's not already. + /// module will not be cached, if it's not already. pub fn fetch( &mut self, code_hash: &Hash, diff --git a/crates/vm/src/wasm/run.rs b/crates/vm/src/wasm/run.rs index dd58a51548..d22e7b84c8 100644 --- a/crates/vm/src/wasm/run.rs +++ b/crates/vm/src/wasm/run.rs @@ -763,6 +763,9 @@ where .borrow_mut() .add_wasm_validation_gas(tx_len) .map_err(|e| Error::GasError(e.to_string()))?; + // Validation is only needed for governance proposals. The other + // transactions are subject to the allowlist and are guaranteed to + // not contain invalid opcodes. validate_untrusted_wasm(code).map_err(Error::ValidationError)?; gas_meter @@ -790,53 +793,59 @@ impl wasm_instrument::gas_metering::Rules for GasRules { // NOTE: these costs are taken from the benchmarks crate. None of them // should be zero let gas = match instruction { - Unreachable => 129_358, - // Just a flag, aribitrary cost of 1 + // NOTE: the real cost of this operation is 57_330 but because of + // the behavior of the instrumentaiton tools which doesn't account + // for traps in called functions we need to reduce it to 1 otherwise + // the gas costs explode + Unreachable => 1, + // Just a label, aribitrary cost of 1 End => 1, - // Just a flag, aribitrary cost of 1 + // Just a label, aribitrary cost of 1 Else => 1, Nop => 1, + // Just a label, cost of 1 Block(_) => 1, + // Just a label, cost of 1 Loop(_) => 1, - If(_) => 4, - Br(_) => 27, - BrIf(_) => 36, - BrTable(_) => 70, - Return => 7, - Call(_) => 43, - CallIndirect(_, _) => 140, + If(_) => 5, + Br(_) => 14, + BrIf(_) => 14, + BrTable(_) => 56, + Return => 4, + Call(_) => 16, + CallIndirect(_, _) => 28, Drop => 1, - Select => 37, - GetLocal(_) => 2, + Select => 11, + GetLocal(_) => 1, SetLocal(_) => 2, TeeLocal(_) => 2, - GetGlobal(_) => 3, - SetGlobal(_) => 4, - I32Load(_, _) => 5, - I64Load(_, _) => 5, - F32Load(_, _) => 6, - F64Load(_, _) => 6, - I32Load8S(_, _) => 5, - I32Load8U(_, _) => 5, - I32Load16S(_, _) => 5, - I32Load16U(_, _) => 5, - I64Load8S(_, _) => 5, - I64Load8U(_, _) => 5, - I64Load16S(_, _) => 5, - I64Load16U(_, _) => 5, - I64Load32S(_, _) => 5, - I64Load32U(_, _) => 5, - I32Store(_, _) => 5, - I64Store(_, _) => 7, - F32Store(_, _) => 5, - F64Store(_, _) => 6, - I32Store8(_, _) => 5, - I32Store16(_, _) => 15, - I64Store8(_, _) => 5, - I64Store16(_, _) => 15, - I64Store32(_, _) => 6, - CurrentMemory(_) => 108, - GrowMemory(_) => 394, + GetGlobal(_) => 4, + SetGlobal(_) => 5, + I32Load(_, _) => 8, + I64Load(_, _) => 8, + F32Load(_, _) => 9, + F64Load(_, _) => 9, + I32Load8S(_, _) => 8, + I32Load8U(_, _) => 8, + I32Load16S(_, _) => 8, + I32Load16U(_, _) => 8, + I64Load8S(_, _) => 8, + I64Load8U(_, _) => 8, + I64Load16S(_, _) => 8, + I64Load16U(_, _) => 8, + I64Load32S(_, _) => 7, + I64Load32U(_, _) => 7, + I32Store(_, _) => 8, + I64Store(_, _) => 9, + F32Store(_, _) => 8, + F64Store(_, _) => 9, + I32Store8(_, _) => 7, + I32Store16(_, _) => 13, + I64Store8(_, _) => 7, + I64Store16(_, _) => 12, + I64Store32(_, _) => 8, + CurrentMemory(_) => 110, + GrowMemory(_) => 194, I32Const(_) => 1, I64Const(_) => 1, F32Const(_) => 1, @@ -852,118 +861,118 @@ impl wasm_instrument::gas_metering::Rules for GasRules { I32LeU => 6, I32GeS => 6, I32GeU => 6, - I64Eqz => 7, - I64Eq => 7, - I64Ne => 7, - I64LtS => 7, - I64LtU => 7, - I64GtS => 7, - I64GtU => 7, - I64LeS => 7, - I64LeU => 7, - I64GeS => 7, - I64GeU => 7, - F32Eq => 8, - F32Ne => 8, - F32Lt => 8, - F32Gt => 8, - F32Le => 8, - F32Ge => 8, - F64Eq => 10, - F64Ne => 10, - F64Lt => 9, - F64Gt => 9, - F64Le => 9, - F64Ge => 9, - I32Clz => 35, - I32Ctz => 34, + I64Eqz => 8, + I64Eq => 8, + I64Ne => 8, + I64LtS => 8, + I64LtU => 8, + I64GtS => 8, + I64GtU => 8, + I64LeS => 8, + I64LeU => 8, + I64GeS => 8, + I64GeU => 8, + F32Eq => 10, + F32Ne => 10, + F32Lt => 10, + F32Gt => 9, + F32Le => 10, + F32Ge => 10, + F64Eq => 11, + F64Ne => 11, + F64Lt => 11, + F64Gt => 12, + F64Le => 11, + F64Ge => 11, + I32Clz => 3, + I32Ctz => 3, I32Popcnt => 3, - I32Add => 3, - I32Sub => 3, - I32Mul => 5, - I32DivS => 17, - I32DivU => 17, - I32RemS => 41, - I32RemU => 17, - I32And => 3, - I32Or => 3, - I32Xor => 3, - I32Shl => 3, - I32ShrS => 3, - I32ShrU => 3, - I32Rotl => 3, - I32Rotr => 3, - I64Clz => 35, - I64Ctz => 34, - I64Popcnt => 3, - I64Add => 5, - I64Sub => 5, - I64Mul => 6, - I64DivS => 28, - I64DivU => 28, - I64RemS => 46, - I64RemU => 28, - I64And => 5, - I64Or => 5, - I64Xor => 5, - I64Shl => 4, - I64ShrS => 4, - I64ShrU => 4, - I64Rotl => 4, - I64Rotr => 4, - F32Abs => 4, - F32Neg => 3, - F32Ceil => 6, - F32Floor => 6, - F32Trunc => 6, - F32Nearest => 6, - F32Sqrt => 9, - F32Add => 6, - F32Sub => 6, - F32Mul => 6, - F32Div => 9, - F32Min => 50, - F32Max => 47, - F32Copysign => 6, - F64Abs => 6, - F64Neg => 4, - F64Ceil => 7, - F64Floor => 7, - F64Trunc => 7, - F64Nearest => 7, - F64Sqrt => 17, - F64Add => 7, - F64Sub => 7, - F64Mul => 7, + I32Add => 4, + I32Sub => 4, + I32Mul => 6, + I32DivS => 18, + I32DivU => 18, + I32RemS => 18, + I32RemU => 18, + I32And => 4, + I32Or => 4, + I32Xor => 4, + I32Shl => 4, + I32ShrS => 4, + I32ShrU => 4, + I32Rotl => 4, + I32Rotr => 4, + I64Clz => 4, + I64Ctz => 4, + I64Popcnt => 4, + I64Add => 7, + I64Sub => 7, + I64Mul => 8, + I64DivS => 30, + I64DivU => 30, + I64RemS => 31, + I64RemU => 30, + I64And => 7, + I64Or => 7, + I64Xor => 7, + I64Shl => 6, + I64ShrS => 6, + I64ShrU => 6, + I64Rotl => 6, + I64Rotr => 6, + F32Abs => 5, + F32Neg => 4, + F32Ceil => 7, + F32Floor => 7, + F32Trunc => 7, + F32Nearest => 7, + F32Sqrt => 10, + F32Add => 7, + F32Sub => 7, + F32Mul => 7, + F32Div => 10, + F32Min => 21, + F32Max => 19, + F32Copysign => 9, + F64Abs => 7, + F64Neg => 5, + F64Ceil => 9, + F64Floor => 9, + F64Trunc => 9, + F64Nearest => 9, + F64Sqrt => 19, + F64Add => 9, + F64Sub => 9, + F64Mul => 9, F64Div => 12, - F64Min => 52, - F64Max => 49, - F64Copysign => 11, + F64Min => 24, + F64Max => 31, + F64Copysign => 13, I32WrapI64 => 2, - I32TruncSF32 => 54, - I32TruncUF32 => 54, - I32TruncSF64 => 57, - I32TruncUF64 => 57, - I64ExtendSI32 => 2, + I32TruncSF32 => 24, + I32TruncUF32 => 25, + I32TruncSF64 => 28, + I32TruncUF64 => 27, + I64ExtendSI32 => 3, I64ExtendUI32 => 2, - I64TruncSF32 => 73, - I64TruncUF32 => 70, - I64TruncSF64 => 89, - I64TruncUF64 => 70, + I64TruncSF32 => 24, + I64TruncUF32 => 39, + I64TruncSF64 => 27, + I64TruncUF64 => 46, F32ConvertSI32 => 12, F32ConvertUI32 => 6, F32ConvertSI64 => 6, - F32ConvertUI64 => 39, + F32ConvertUI64 => 12, F32DemoteF64 => 9, F64ConvertSI32 => 12, F64ConvertUI32 => 12, F64ConvertSI64 => 12, - F64ConvertUI64 => 39, + F64ConvertUI64 => 12, F64PromoteF32 => 9, I32ReinterpretF32 => 2, - I64ReinterpretF64 => 2, + I64ReinterpretF64 => 3, F32ReinterpretI32 => 3, - F64ReinterpretI64 => 3, + F64ReinterpretI64 => 4, SignExt(SignExtInstruction::I32Extend8S) => 1, SignExt(SignExtInstruction::I32Extend16S) => 1, SignExt(SignExtInstruction::I64Extend8S) => 1, @@ -986,7 +995,7 @@ impl wasm_instrument::gas_metering::Rules for GasRules { } fn call_per_local_cost(&self) -> u32 { - 1 + 0 } } diff --git a/examples/generate_txs.rs b/examples/generate_txs.rs index daa91961f2..51727d6361 100644 --- a/examples/generate_txs.rs +++ b/examples/generate_txs.rs @@ -10,7 +10,7 @@ use proptest::test_runner::{Reason, TestRunner}; #[tokio::main] async fn main() -> Result<(), Reason> { - let mut runner = TestRunner::default(); + let mut runner = TestRunner::deterministic(); let wallet = FsWalletUtils::new(PathBuf::from("wallet.toml")); let mut debug_vectors = vec![]; let mut test_vectors = vec![]; diff --git a/genesis/hardware/README.md b/genesis/hardware/README.md new file mode 100644 index 0000000000..7abc5d42db --- /dev/null +++ b/genesis/hardware/README.md @@ -0,0 +1,148 @@ +# Localnet genesis templates using hardware wallet keys + +This directory contains genesis templates for a local network with a single validator. The `src` directory contains generated pre-genesis wallet pre-loaded with public keys, derivation paths, and a single validator `validator-0` wallet that are being used in the templates. Most of the keys for this network are derived from a hardware wallet configured with a specific seed phrase. + +If you're modifying any of the files here, you can run this to ensure that the changes are valid: + +```shell +cargo watch -x "test test_validate_hardware_genesis_templates" +``` + +## Reproducibility + +To ensure that the key generated by the hardware wallet for a given derivation path is always the same, the hardware wallet must be configured to use a known test mnemonic. Specifically, these genesis templates were generated using the following test mnemonic: `equip will roof matter pink blind book anxiety banner elbow sun young`. Instructions on how to configure the hardware wallet with this mnemonic can be found in the `Set a test mnemonic` section of . +## E2E and Integration Tests +The E2E and integration tests can be made to use these hardware wallet based genesis templates by setting the environment variable `NAMADA_E2E_USE_DEVICE` to `true` when running `make test ...`. In order to ensure the success of these tests, please ensure that the following requirements are met: +* The hardware wallet is connected and the Ledger app is open for the duration of the E2E tests +* Transactions are promptly manually approved on the hardware wallet before the E2E test timeouts ellapse +* The hardware wallet is configured with the same test mnemonic used to generate these genesis templates. See [reproducibility](#reproducibility). + +### Using Ledger emulator Speculos + +1. Build an elf file of the Namada ledger app +2. Build the emulator following the instructions from +3. Start the emulator with: + ```sh + ./speculos.py ../ledger-namada/app/output/app_s2.elf --seed "equip will roof matter pink blind book anxiety banner elbow sun young" + ``` +4. Set env var `export NAMADA_DEVICE_TRANSPORT=tcp` to connect to the emulator. The default ip/port is `127.0.0.1:9999`. To use a different ip/port set `LEDGER_PROXY_ADDRESS` and/or `LEDGER_PROXY_PORT`, respectively. + +## pre-genesis/wallet.toml + +The pre-genesis balances wallet is located at [pre-genesis/wallet.toml](pre-genesis/wallet.toml) and can be re-generated from the repo's root dir with: + +```shell +cargo run --bin namadaw -- --base-dir "genesis/hardware/src" derive \ + --alias albert-key --pre-genesis --use-device --hd-path "m/44'/877'/0'/0'/0'" +cargo run --bin namadaw -- --base-dir "genesis/hardware/src" derive \ + --alias bertha-key --pre-genesis --use-device --hd-path "m/44'/877'/0'/0'/1'" +cargo run --bin namadaw -- --base-dir "genesis/hardware/src" derive \ + --alias christel --pre-genesis --use-device --hd-path "m/44'/877'/0'/0'/2'" +cargo run --bin namadaw -- --base-dir "genesis/hardware/src" derive \ + --alias daewon --pre-genesis --use-device --hd-path "m/44'/877'/0'/0'/3'" +cargo run --bin namadaw -- --base-dir "genesis/hardware/src" derive \ + --alias validator-0-account-key --pre-genesis --use-device --hd-path "m/44'/877'/0'/0'/5'" +cargo run --bin namadaw -- --base-dir "genesis/hardware/src" gen \ + --alias faucet-key --unsafe-dont-encrypt --pre-genesis +``` + +Some keys are used to setup established accounts and some are directly assigned balances in the [balances.toml](#balancestoml) file to implicit addresses derived from these keys. + +## transactions.toml + +### Transaction to initialize an established account + +For example, Albert's account is created with: + +```shell +cargo run --bin namadac -- --base-dir "genesis/localnet/src" utils \ + init-genesis-established-account \ + --path "genesis/localnet/src/pre-genesis/established/established-account-tx-albert.toml" \ + --aliases "albert-key" +``` + +Note that the command will print out your `Derived established account address`. + +### Validator transactions + +To create a validator's account, first initialize an established account: + +```shell +cargo run --bin namadac -- --base-dir "genesis/localnet/src" utils \ + init-genesis-established-account \ + --path "genesis/localnet/src/pre-genesis/validator-0/unsigned-transactions.toml" \ + --aliases "validator-0-account-key" +``` + +The `Derived established account address` and the transaction added to the TOML file from this command is used in the following command. + +The pre-genesis validator wallet used to generate [validator transactions for transactions.toml](src/pre-genesis/validator-0/transactions.toml) is located at [src/pre-genesis/validator-0/validator-wallet.toml](src/pre-genesis/validator-0/validator-wallet.toml) and can be re-generated: + +```shell +cargo run --bin namadac -- --base-dir "genesis/localnet/src" utils \ + init-genesis-validator \ + --alias validator-0 \ + --address tnam1q9vhfdur7gadtwx4r223agpal0fvlqhywylf2mzx \ + --path "genesis/localnet/src/pre-genesis/validator-0/unsigned-transactions.toml" \ + --net-address "127.0.0.1:27656" \ + --commission-rate 0.05 \ + --max-commission-rate-change 0.01 \ + --email "null@null.net" \ + --self-bond-amount 100000 \ + --unsafe-dont-encrypt +``` + +### Delegations + +A delegation with e.g. 20 000 NAM tokens to a validator account whose address has to be known beforehand (here the validator-0 created above) is created with: + +```shell +cargo run --bin namadac -- --base-dir "genesis/localnet/src" utils \ + genesis-bond \ + --validator tnam1q9vhfdur7gadtwx4r223agpal0fvlqhywylf2mzx \ + --amount 20000 \ + --path "genesis/localnet/src/pre-genesis/bond/bond-tx-albert.toml" +``` + +### Signing + +The non-validator transactions are manually appended together in [src/pre-genesis/unsigned-transactions.toml](src/pre-genesis/unsigned-transactions.toml) and then signed to produce [src/pre-genesis/signed-transactions.toml](src/pre-genesis/signed-transactions.toml) using: + +```shell +cargo run --bin namadac -- --base-dir "genesis/localnet/src" utils \ + sign-genesis-txs --use-device \ + --path "genesis/localnet/src/pre-genesis/unsigned-transactions.toml" \ + --output "genesis/localnet/src/pre-genesis/signed-transactions.toml" +``` + +The validator transactions are signed using (note the extra `--alias` argument needed to find the validator pre-genesis wallet): + +```shell +cargo run --bin namadac -- --base-dir "genesis/localnet/src" utils \ + sign-genesis-txs --use-device \ + --path "genesis/localnet/src/pre-genesis/validator-0/unsigned-transactions.toml" \ + --output "genesis/localnet/src/pre-genesis/validator-0/signed-transactions.toml" \ + --alias validator-0 +``` + +This non-validator [src/pre-genesis/signed-transactions.toml](src/pre-genesis/signed-transactions.toml) are joined together with [src/validator-0/signed-transactions.toml](src/validator-0/signed-transactions.toml) in [transactions.toml](transactions.toml). + +## balances.toml + +The [balances.toml file](balances.toml) contains token balances associated with public keys or established addresses which can be derived from genesis transactions. The public keys from the wallet can be found with: + +```shell +cargo run --bin namadaw -- --base-dir "genesis/localnet/src" key list +``` + +If you didn't note the address from your transactions, you can deterministically derive an established address from the TOML file again, run with the `--path` set to a transaction TOML file: + +```shell +cargo run --bin namadac -- --base-dir "genesis/localnet/src" utils \ + derive-genesis-addresses \ + --path "genesis/localnet/src/pre-genesis/established/established-account-tx-validator-0.toml" +``` + +## Validation + +A unit test `test_validate_hardware_genesis_templates` is setup to check validity of the localnet setup. diff --git a/genesis/hardware/balances.toml b/genesis/hardware/balances.toml new file mode 100644 index 0000000000..4e8dfbd076 --- /dev/null +++ b/genesis/hardware/balances.toml @@ -0,0 +1,135 @@ +# Genesis balances. +# +# This files contains the genesis balances of any tokens present at genesis +# associated with implicit addresses (in the form of public keys) or established +# addresses. +# +# For example: +# ``` +# [token.NAM] +# some_pk_bech32m_encoding = 10 # genesis tokens, the amount can have up to 6 decimal places +# ``` +# +# The public keys present in here are taken from `pre-genesis/wallet.toml`. +# As for the established addresses, these are derived from their respective +# genesis tx toml files. + +[token.NAM] +# albert +tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e = "2000000" +tnam1qq6qyugak0gd4up6lma8z8wr88w3pq9lgvfhw6yu = "2000000" +# bertha +tnam1qyvmxf6r5e9gjtq2pwsndgq77hmx4vw2rghnmt8v = "2000000" +tnam1qp7z909dsdv4qw5jcasywzm9p7xa3qeqqghcjqxe = "2000000" +# christel +tnam1q8wemh6ws8vctdyg3dh9339qusttefzp0qw0qhvm = "2000000" +tnam1qq8kszasdp30f2j2pkhz40zpfvztdakwqvkm0xy4 = "2000000" +# daewon +tnam1qqnxq04amahj5yuwux7pdsjp3dyu07at3u3f742p = "100000000" +# ester +tnam1qr2y927swt2ax66m9fgc9ejs40m7m77rry53cvkv = "1000000" +# validator-0 +tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss = "200000" +tnam1qrdrgx6d3rzl2f5yn6nde6wg20sl6kmtug3ecg7z = "200000" +# validator-0-account-key +tnam1qr56gfuh4flztuqlpk50e5dknjx8vcnhz59t5u3w = "1000000" +# frank +tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "2000000" +tnam1qz0nvec686e9pks8ynhm5ddq8ke7j2eey50uagtr = "2000000" + +[token.BTC] +# albert +tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e = "1000000" +# bertha +tnam1qyvmxf6r5e9gjtq2pwsndgq77hmx4vw2rghnmt8v = "1000000" +# christel +tnam1q8wemh6ws8vctdyg3dh9339qusttefzp0qw0qhvm = "1000000" +# daewon-key +tnam1qqnxq04amahj5yuwux7pdsjp3dyu07at3u3f742p = "1000000" +# ester-key +tnam1qr2y927swt2ax66m9fgc9ejs40m7m77rry53cvkv = "1000000" +# validator-0 +tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss = "1000000" +# frank +tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" + +[token.ETH] +# albert +tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e = "1000000" +# bertha +tnam1qyvmxf6r5e9gjtq2pwsndgq77hmx4vw2rghnmt8v = "1000000" +# christel +tnam1q8wemh6ws8vctdyg3dh9339qusttefzp0qw0qhvm = "1000000" +# daewon-key +tnam1qqnxq04amahj5yuwux7pdsjp3dyu07at3u3f742p = "1000000" +# ester-key +tnam1qr2y927swt2ax66m9fgc9ejs40m7m77rry53cvkv = "1000000" +# validator-0 +tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss = "1000000" +# frank +tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" + + +[token.DOT] +# albert +tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e = "1000000" +# bertha +tnam1qyvmxf6r5e9gjtq2pwsndgq77hmx4vw2rghnmt8v = "1000000" +# christel +tnam1q8wemh6ws8vctdyg3dh9339qusttefzp0qw0qhvm = "1000000" +# daewon-key +tnam1qqnxq04amahj5yuwux7pdsjp3dyu07at3u3f742p = "1000000" +# ester-key +tnam1qr2y927swt2ax66m9fgc9ejs40m7m77rry53cvkv = "1000000" +# validator-0 +tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss = "1000000" +# frank +tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" + +[token.Schnitzel] +# albert +tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e = "1000000" +# bertha +tnam1qyvmxf6r5e9gjtq2pwsndgq77hmx4vw2rghnmt8v = "1000000" +# christel +tnam1q8wemh6ws8vctdyg3dh9339qusttefzp0qw0qhvm = "1000000" +# daewon-key +tnam1qqnxq04amahj5yuwux7pdsjp3dyu07at3u3f742p = "1000000" +# ester-key +tnam1qr2y927swt2ax66m9fgc9ejs40m7m77rry53cvkv = "1000000" +# validator-0 +tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss = "1000000" +# frank +tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" + +[token.Apfel] +# albert +tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e = "1000000" +# bertha +tnam1qyvmxf6r5e9gjtq2pwsndgq77hmx4vw2rghnmt8v = "1000000" +# christel +tnam1q8wemh6ws8vctdyg3dh9339qusttefzp0qw0qhvm = "1000000" +# daewon-key +tnam1qqnxq04amahj5yuwux7pdsjp3dyu07at3u3f742p = "1000000" +# ester-key +tnam1qr2y927swt2ax66m9fgc9ejs40m7m77rry53cvkv = "1000000" +# validator-0 +tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss = "1000000" +# frank +tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" + +[token.Kartoffel] +# albert +tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e = "1000000" +# bertha +tnam1qyvmxf6r5e9gjtq2pwsndgq77hmx4vw2rghnmt8v = "1000000" +# christel +tnam1q8wemh6ws8vctdyg3dh9339qusttefzp0qw0qhvm = "1000000" +# daewon-key +tnam1qqnxq04amahj5yuwux7pdsjp3dyu07at3u3f742p = "1000000" +# ester-key +tnam1qr2y927swt2ax66m9fgc9ejs40m7m77rry53cvkv = "1000000" +# validator-0 +tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss = "1000000" +# frank +tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" diff --git a/genesis/hardware/parameters.toml b/genesis/hardware/parameters.toml new file mode 100644 index 0000000000..f3b48ffece --- /dev/null +++ b/genesis/hardware/parameters.toml @@ -0,0 +1,113 @@ +# General protocol parameters. +[parameters] +native_token = "NAM" +is_native_token_transferable = true +# Minimum number of blocks in an epoch. +min_num_of_blocks = 4 +# Max payload size, in bytes, for a tx. +max_tx_bytes = 1048576 +# Max payload size, in bytes, for a block proposal. +max_proposal_bytes = 6291456 +# vp allowlist +vp_allowlist = [] +# tx allowlist +tx_allowlist = [] +# Implicit VP WASM name +implicit_vp = "vp_implicit" +# Expected number of epochs per year (also sets the min duration of an epoch in seconds) +epochs_per_year = 31_536_000 +# The multiplier for masp epochs +masp_epoch_multiplier = 2 +# Max gas for block +max_block_gas = 20000000 +# Masp fee payment gas limit +masp_fee_payment_gas_limit = 150_000 +# Gas scale +gas_scale = 10_000_000 + +# Map of the cost per gas unit for every token allowed for fee payment +[parameters.minimum_gas_price] +nam = "0.000001" + +# Proof of stake parameters. +[pos_params] +# Maximum number of active validators. +max_validator_slots = 128 +# Pipeline length (in epochs). Any change in the validator set made in +# epoch 'n' will become active in epoch 'n + pipeline_len'. +pipeline_len = 2 +# Unbonding length (in epochs). Validators may have their stake slashed +# for a fault in epoch 'n' up through epoch 'n + unbonding_len'. +unbonding_len = 3 +# Votes per fundamental staking token (namnam) +tm_votes_per_token = "1" +# Reward for proposing a block. +block_proposer_reward = "0.125" +# Reward for voting on a block. +block_vote_reward = "0.1" +# Maximum inflation rate per annum (10%) +max_inflation_rate = "0.1" +# Targeted ratio of staked tokens to total tokens in the supply +target_staked_ratio = "0.6667" +# Portion of a validator's stake that should be slashed on a duplicate +# vote. +duplicate_vote_min_slash_rate = "0.001" +# Portion of a validator's stake that should be slashed on a light +# client attack. +light_client_attack_min_slash_rate = "0.001" +# Number of epochs above and below (separately) the current epoch to +# consider when doing cubic slashing +cubic_slashing_window_length = 1 +# The minimum amount of bonded tokens that a validator needs to be in +# either the `consensus` or `below_capacity` validator sets +validator_stake_threshold = "1000000" +# The length, in blocks, of the sliding window for consensus validators +# inactivity verification +liveness_window_check = 100 +# The minimum required activity of consensus validators, in percentage, over +# the `liveness_window_check` +liveness_threshold = "0.9" +# The P gain factor in the Proof of Stake rewards controller +rewards_gain_p = "0.25" +# The D gain factor in the Proof of Stake rewards controller +rewards_gain_d = "0.25" + +# Governance parameters. +[gov_params] +# minimum amount of nam token to lock +min_proposal_fund = 500 +# proposal code size in bytes +max_proposal_code_size = 600000 +# min proposal period length in epochs +min_proposal_voting_period = 3 +# max proposal period length in epochs +max_proposal_period = 27 +# maximum number of characters in the proposal content +max_proposal_content_size = 10000 +# minimum epochs between end and activation epoch +min_proposal_grace_epochs = 6 +# maximum number of epochs between current epoch and start epoch +max_proposal_latency = 30 + +# Public goods funding parameters +[pgf_params] +# Initial set of stewards +stewards = [ + # bertha + "tnam1qyvmxf6r5e9gjtq2pwsndgq77hmx4vw2rghnmt8v", + # validator-0 + "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +] +# The pgf funding inflation rate +pgf_inflation_rate = "0.1" +# The pgf stewards inflation rate +stewards_inflation_rate = "0.01" +# The maximum number of pgf stewards +maximum_number_of_stewards = 5 + +# IBC parameters +[ibc_params] +# default mint limit of each token +default_mint_limit = "0" +# default per-epoch throughput limit of each token +default_per_epoch_throughput_limit = "0" diff --git a/genesis/hardware/src/pre-genesis/bond/bond-tx-albert.toml b/genesis/hardware/src/pre-genesis/bond/bond-tx-albert.toml new file mode 100644 index 0000000000..f1aaf70aef --- /dev/null +++ b/genesis/hardware/src/pre-genesis/bond/bond-tx-albert.toml @@ -0,0 +1,4 @@ +[[bond]] +source = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +validator = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +amount = "20000" diff --git a/genesis/hardware/src/pre-genesis/established/established-account-tx-albert.toml b/genesis/hardware/src/pre-genesis/established/established-account-tx-albert.toml new file mode 100644 index 0000000000..3d7ed59c05 --- /dev/null +++ b/genesis/hardware/src/pre-genesis/established/established-account-tx-albert.toml @@ -0,0 +1,4 @@ +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qquurf975axryz4sf0jmyxpknkxp4cs7g8e8ahhpw089u6j3q9dy6qssdhz"] diff --git a/genesis/hardware/src/pre-genesis/established/established-account-tx-bertha.toml b/genesis/hardware/src/pre-genesis/established/established-account-tx-bertha.toml new file mode 100644 index 0000000000..bc544c9c80 --- /dev/null +++ b/genesis/hardware/src/pre-genesis/established/established-account-tx-bertha.toml @@ -0,0 +1,4 @@ +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qrg6qx72e0vqhg8plg20hv97g3p3q092gl88jlngkly0hpmca2h2we44uzw"] diff --git a/genesis/hardware/src/pre-genesis/established/established-account-tx-christel.toml b/genesis/hardware/src/pre-genesis/established/established-account-tx-christel.toml new file mode 100644 index 0000000000..9d539dc979 --- /dev/null +++ b/genesis/hardware/src/pre-genesis/established/established-account-tx-christel.toml @@ -0,0 +1,4 @@ +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qp7r3et2usz538fxzkm69h3awr7t0kgk7h6528za7pk4g2jldk5dz0qjkhx"] diff --git a/genesis/hardware/src/pre-genesis/established/established-account-tx-frank.toml b/genesis/hardware/src/pre-genesis/established/established-account-tx-frank.toml new file mode 100644 index 0000000000..cdb56e0666 --- /dev/null +++ b/genesis/hardware/src/pre-genesis/established/established-account-tx-frank.toml @@ -0,0 +1,4 @@ +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qqwfpuvn8x7yqtquejhppef4vddv9ghusec2rkaxav38amamxaxpgj9cs79"] diff --git a/genesis/hardware/src/pre-genesis/signed-transactions.toml b/genesis/hardware/src/pre-genesis/signed-transactions.toml new file mode 100644 index 0000000000..d08893c91c --- /dev/null +++ b/genesis/hardware/src/pre-genesis/signed-transactions.toml @@ -0,0 +1,27 @@ +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qqwfpuvn8x7yqtquejhppef4vddv9ghusec2rkaxav38amamxaxpgj9cs79"] + +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qquurf975axryz4sf0jmyxpknkxp4cs7g8e8ahhpw089u6j3q9dy6qssdhz"] + +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qp7r3et2usz538fxzkm69h3awr7t0kgk7h6528za7pk4g2jldk5dz0qjkhx"] + +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qrg6qx72e0vqhg8plg20hv97g3p3q092gl88jlngkly0hpmca2h2we44uzw"] + +[[bond]] +source = "tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e" +validator = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +amount = "20000" + +[bond.signatures] +tpknam1qquurf975axryz4sf0jmyxpknkxp4cs7g8e8ahhpw089u6j3q9dy6qssdhz = "signam1qzgqntx4tqsrlwn2g2lwwhkcvwkjpd768fup0yr9ctunrc6yj89h57uxgv74vn3y5unz55slmlkyj0td5nu8wjvf52el3azn95uk3xcfjmzcpl" diff --git a/genesis/hardware/src/pre-genesis/unsigned-transactions.toml b/genesis/hardware/src/pre-genesis/unsigned-transactions.toml new file mode 100644 index 0000000000..b906c6d7de --- /dev/null +++ b/genesis/hardware/src/pre-genesis/unsigned-transactions.toml @@ -0,0 +1,43 @@ +# This file contains hand-written unsigned transactions for localnet with: +# +# - 3 established accounts for "Albert", "Bertha" and "Christel" +# - a bond from "Albert"'s established account to validator-0 +# +# Note that 1 localnet user account "Daewon" is left as +# implicit account, so their tokens are kept in the accounts derived from their +# keys used in `balances.toml`. +# +# This file is used to produce `signed-transactions.toml` with +# the `sign-genesis-txs` command. + +# Albert +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qquurf975axryz4sf0jmyxpknkxp4cs7g8e8ahhpw089u6j3q9dy6qssdhz"] + +# Bertha +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qrg6qx72e0vqhg8plg20hv97g3p3q092gl88jlngkly0hpmca2h2we44uzw"] + +# Christel +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qp7r3et2usz538fxzkm69h3awr7t0kgk7h6528za7pk4g2jldk5dz0qjkhx"] + +# Frank +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qqwfpuvn8x7yqtquejhppef4vddv9ghusec2rkaxav38amamxaxpgj9cs79"] + +########################################################################################## + +# Albert bonds to `validator-0` +[[bond]] +source = "tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e" +validator = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +amount = "20000" diff --git a/genesis/hardware/src/pre-genesis/validator-0/signed-transactions.toml b/genesis/hardware/src/pre-genesis/validator-0/signed-transactions.toml new file mode 100644 index 0000000000..f1fa75a707 --- /dev/null +++ b/genesis/hardware/src/pre-genesis/validator-0/signed-transactions.toml @@ -0,0 +1,45 @@ +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qrulnacf6l6lt2vlpc8y2yudlgzs9hzrfa9p66fv4p7vk8utf6m4554t3ak"] + +[[validator_account]] +address = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +vp = "vp_user" +commission_rate = "0.05" +max_commission_rate_change = "0.01" +net_address = "127.0.0.1:27656" + +[validator_account.consensus_key] +pk = "tpknam1qr9u5py97pdmcvnrxhzuuv79ydv5rw7r9z402sucwt6h0lvmmmwqy2wrweg" +authorization = "signam1qqc8l8rvl5kx36sgnrqfzsyc5p6047c3xp5hqnhz8w7qmqzw5umqtglaejn6ekajm2jt98qhwlje38wdackknk4qrj9jycutmw2eevgvlv0uq6" + +[validator_account.protocol_key] +pk = "tpknam1qrenhfdphzpszlr7fzand6qgmppge430g3a2lquqzhz64fkve5mq2hdfjaa" +authorization = "signam1qrgem8wds2eupup8a5wl8he9ftvx6a4elyt97322q483vh8j3fm0x330h0pfcpumpm2tqgz2chmw567mhxtqdlncggz8uc8u66svnsqw26ra2v" + +[validator_account.tendermint_node_key] +pk = "tpknam1qpgcgptcjl22hl2te2uqnp33aqjmvfaud3a3f3sgtxezg7uu5rsv6d2flr3" +authorization = "signam1qq05nmg0v5w9377235dpuk7k5k7kkjx5zyewqr4ecd0yyawz3ll2r7jxq9ss9wpnl69c9s0t9aqyuf7y6e7avh8m6d6nvyt5qnmaz5qyay596t" + +[validator_account.eth_hot_key] +pk = "tpknam1qypnh98mexms8edj8rcwu0cayx0459p39dwzsffxrr394mf4cse707qcctyrx" +authorization = "signam1q86yxmjctxx7h59cl3tz8sf6j9r6wlxplv282fkm8yxyc8wvjkz4q8lhcavq8xa9jk3clnuxfpdg9hnp4t589ld3v2lv9tla3phucle7qysufnv4" + +[validator_account.eth_cold_key] +pk = "tpknam1qypz8zr0w8lsz3s98vh4p974xuxeedpecj9s2l3326r3kdz4tc0snrcpnc8yv" +authorization = "signam1qxxc4ulf7qlc0vdz477sgg3hms07vn3apkluxrq0erhchtw90yw9z2m6kmjcrgc8zks0fvwsmr88q0dxd3cs9zy7pz94wuum5urwu868qyzvqmr5" + +[validator_account.metadata] +email = "null@null.net" + +[validator_account.signatures] +tpknam1qrulnacf6l6lt2vlpc8y2yudlgzs9hzrfa9p66fv4p7vk8utf6m4554t3ak = "signam1qzg4cjyctnrnl8vpgp95tvjgwpcye3xfwchxq66de6wqn5ujwk6m69qd4n4mzx40ch48xtzhdhnq9m605pwm2v0gy422ehula4xt89cz39ngg0" + +[[bond]] +source = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +validator = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +amount = "100000" + +[bond.signatures] +tpknam1qrulnacf6l6lt2vlpc8y2yudlgzs9hzrfa9p66fv4p7vk8utf6m4554t3ak = "signam1qzwn66j9dx49eyg72fd7s2cw5l2va3p9dj07te0egf93p6qatf95hk447ty6s6cds55ggtz8dcr65xqqz00a0wclqrhqcknk504a2ps9jqe6f7" diff --git a/genesis/hardware/src/pre-genesis/validator-0/unsigned-transactions.toml b/genesis/hardware/src/pre-genesis/validator-0/unsigned-transactions.toml new file mode 100644 index 0000000000..80e15d14b5 --- /dev/null +++ b/genesis/hardware/src/pre-genesis/validator-0/unsigned-transactions.toml @@ -0,0 +1,24 @@ +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qrulnacf6l6lt2vlpc8y2yudlgzs9hzrfa9p66fv4p7vk8utf6m4554t3ak"] + +[[validator_account]] +address = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +vp = "vp_user" +commission_rate = "0.05" +max_commission_rate_change = "0.01" +net_address = "127.0.0.1:27656" +consensus_key = "tpknam1qr9u5py97pdmcvnrxhzuuv79ydv5rw7r9z402sucwt6h0lvmmmwqy2wrweg" +protocol_key = "tpknam1qrenhfdphzpszlr7fzand6qgmppge430g3a2lquqzhz64fkve5mq2hdfjaa" +tendermint_node_key = "tpknam1qpgcgptcjl22hl2te2uqnp33aqjmvfaud3a3f3sgtxezg7uu5rsv6d2flr3" +eth_hot_key = "tpknam1qypnh98mexms8edj8rcwu0cayx0459p39dwzsffxrr394mf4cse707qcctyrx" +eth_cold_key = "tpknam1qypz8zr0w8lsz3s98vh4p974xuxeedpecj9s2l3326r3kdz4tc0snrcpnc8yv" + +[validator_account.metadata] +email = "null@null.net" + +[[bond]] +source = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +validator = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +amount = "100000" diff --git a/genesis/hardware/src/pre-genesis/validator-0/validator-wallet.toml b/genesis/hardware/src/pre-genesis/validator-0/validator-wallet.toml new file mode 100644 index 0000000000..d7ceb76fb9 --- /dev/null +++ b/genesis/hardware/src/pre-genesis/validator-0/validator-wallet.toml @@ -0,0 +1,7 @@ +consensus_key = "unencrypted:0037a44681b64d42497e2229516479f83e5344a7a30e8316bde45881a1ec745359" +eth_cold_key = "unencrypted:010d34fcb42383f0babe7c86203f07bf4134f0756a630eb07923f21c90cc068602" +tendermint_node_key = "unencrypted:002f2e94bb5834e18433343345baf47b2b5d4e1ef4d46ba0f876d3d2c89d831419" + +[validator_keys] +protocol_keypair = "ED25519_SK_PREFIX00610677d4c52ab8ca5e8abe7dfb40246a271a03069fded6099763cbc41e04df02" +eth_bridge_keypair = "SECP256K1_SK_PREFIX01a81af251a711382d6b649a44b36ac5d4f41106f356e1f2fb33c001e91ffaa169" diff --git a/genesis/hardware/src/pre-genesis/wallet.toml b/genesis/hardware/src/pre-genesis/wallet.toml new file mode 100644 index 0000000000..1f36ffe432 --- /dev/null +++ b/genesis/hardware/src/pre-genesis/wallet.toml @@ -0,0 +1,53 @@ +[view_keys] + +[spend_keys] + +[payment_addrs] + +[secret_keys] +faucet-key = "unencrypted:00548aa8393422b88dce5f4be8ee0320638061c3e0649ada1b0dacbec4c0c75bb2" +frank-key = "unencrypted:00a08de8d33b9798328d2e4476fade49f515dc82754451fc6ef7060ea0bd1e8f1a" + +[public_keys] +albert-key = "ED25519_PK_PREFIXtpknam1qquurf975axryz4sf0jmyxpknkxp4cs7g8e8ahhpw089u6j3q9dy6qssdhz" +bertha-key = "ED25519_PK_PREFIXtpknam1qrg6qx72e0vqhg8plg20hv97g3p3q092gl88jlngkly0hpmca2h2we44uzw" +christel-key = "ED25519_PK_PREFIXtpknam1qp7r3et2usz538fxzkm69h3awr7t0kgk7h6528za7pk4g2jldk5dz0qjkhx" +daewon = "ED25519_PK_PREFIXtpknam1qzdgg0q7c2szvx67q84r859axuwmyvsku0t9w97kwdvz7ff89xy4xrqxfmv" +ester = "ED25519_PK_PREFIXtpknam1qplr7n6ej99zyvzvjy0w726p0809m6a279a02rn5zw0c52k8wdw8q5gfc8y" +faucet-key = "ED25519_PK_PREFIXtpknam1qzh2d8vk9wvj2j63fa3cvjru9uldpdjctjjxpafl5r8vwwf56pdgyq0vra4" +validator-0-account-key = "ED25519_PK_PREFIXtpknam1qrulnacf6l6lt2vlpc8y2yudlgzs9hzrfa9p66fv4p7vk8utf6m4554t3ak" +frank-key = "ED25519_PK_PREFIXtpknam1qqwfpuvn8x7yqtquejhppef4vddv9ghusec2rkaxav38amamxaxpgj9cs79" + +[derivation_paths] +albert-key = "m/44'/877'/0'/0'/0'" +bertha-key = "m/44'/877'/0'/0'/1'" +christel-key = "m/44'/877'/0'/0'/2'" +daewon = "m/44'/877'/0'/0'/3'" +ester = "m/44'/877'/0'/0'/4'" +validator-0-account-key = "m/44'/877'/0'/0'/5'" + +[addresses] +albert = "tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e" +bertha = "tnam1qyvmxf6r5e9gjtq2pwsndgq77hmx4vw2rghnmt8v" +christel = "tnam1q8wemh6ws8vctdyg3dh9339qusttefzp0qw0qhvm" +albert-key = "tnam1qq6qyugak0gd4up6lma8z8wr88w3pq9lgvfhw6yu" +bertha-key = "tnam1qp7z909dsdv4qw5jcasywzm9p7xa3qeqqghcjqxe" +christel-key = "tnam1qq8kszasdp30f2j2pkhz40zpfvztdakwqvkm0xy4" +daewon = "tnam1qqnxq04amahj5yuwux7pdsjp3dyu07at3u3f742p" +ester = "tnam1qr2y927swt2ax66m9fgc9ejs40m7m77rry53cvkv" +faucet-key = "tnam1qzgcl2znamndmku7ujw6e79dmvd4v7rfd5c89dfz" +validator-0 = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +frank = "tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf" +frank-key = "tnam1qz0nvec686e9pks8ynhm5ddq8ke7j2eey50uagtr" + +[pkhs] +7C22BCAD8359503A92C760470B650F8DD8832002 = "bertha-key" +3402711DB3D0DAF03AFEFA711DC339DD1080BF43 = "albert-key" +26603EBDDF6F2A138EE1BC16C2418B49C7FBAB8F = "daewon" +918FA853EEE6DDDB9EE49DACF8ADDB1B5678696D = "faucet-key" +0F680BB06862F4AA4A0DAE2ABC414B04B6F6CE03 = "christel-key" +D442ABD072D5D36B5B2A5182E650ABF7EDFBC319 = "ester" +E9A42797AA7E25F01F0DA8FCD1B69C8C76627715 = "validator-0-account-key" +9F36671A3EB250DA0724EFBA35A03DB3E92B3925 = "frank-key" + +[address_vp_types] diff --git a/genesis/hardware/tokens.toml b/genesis/hardware/tokens.toml new file mode 100644 index 0000000000..3a851f7102 --- /dev/null +++ b/genesis/hardware/tokens.toml @@ -0,0 +1,64 @@ +# Token accounts with their validity predicates + +[token.NAM] +denom = 6 + +[token.NAM.masp_params] +max_reward_rate = "0.01" +kd_gain_nom = "0.25" +kp_gain_nom = "0.25" +locked_amount_target = 10000 + +[token.BTC] +denom = 8 + +[token.BTC.masp_params] +max_reward_rate = "0.01" +kd_gain_nom = "0.25" +kp_gain_nom = "0.25" +locked_amount_target = 10000 + +[token.ETH] +denom = 18 + +[token.ETH.masp_params] +max_reward_rate = "0.01" +kd_gain_nom = "0.25" +kp_gain_nom = "0.25" +locked_amount_target = 10000 + +[token.DOT] +denom = 10 + +[token.DOT.masp_params] +max_reward_rate = "0.01" +kd_gain_nom = "0.25" +kp_gain_nom = "0.25" +locked_amount_target = 10000 + +[token.Schnitzel] +denom = 6 + +[token.Schnitzel.masp_params] +max_reward_rate = "0.01" +kd_gain_nom = "0.25" +kp_gain_nom = "0.25" +locked_amount_target = 10000 + +[token.Apfel] +denom = 6 + +[token.Apfel.masp_params] +max_reward_rate = "0.01" +kd_gain_nom = "0.25" +kp_gain_nom = "0.25" +locked_amount_target = 10000 + +[token.Kartoffel] +denom = 6 + +[token.Kartoffel.masp_params] +max_reward_rate = "0.01" +kd_gain_nom = "0.25" +kp_gain_nom = "0.25" +locked_amount_target = 10000 diff --git a/genesis/hardware/transactions.toml b/genesis/hardware/transactions.toml new file mode 100644 index 0000000000..fbf8e5b1e9 --- /dev/null +++ b/genesis/hardware/transactions.toml @@ -0,0 +1,82 @@ +# Transactions pasted from: +# +# 1. `src/pre-genesis/validator-0/signed-transactions.toml` +# 2. `src/pre-genesis/signed-transactions.toml` + +# 1. + +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qrulnacf6l6lt2vlpc8y2yudlgzs9hzrfa9p66fv4p7vk8utf6m4554t3ak"] + +[[validator_account]] +address = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +vp = "vp_user" +commission_rate = "0.05" +max_commission_rate_change = "0.01" +net_address = "127.0.0.1:27656" + +[validator_account.consensus_key] +pk = "tpknam1qr9u5py97pdmcvnrxhzuuv79ydv5rw7r9z402sucwt6h0lvmmmwqy2wrweg" +authorization = "signam1qqc8l8rvl5kx36sgnrqfzsyc5p6047c3xp5hqnhz8w7qmqzw5umqtglaejn6ekajm2jt98qhwlje38wdackknk4qrj9jycutmw2eevgvlv0uq6" + +[validator_account.protocol_key] +pk = "tpknam1qrenhfdphzpszlr7fzand6qgmppge430g3a2lquqzhz64fkve5mq2hdfjaa" +authorization = "signam1qrgem8wds2eupup8a5wl8he9ftvx6a4elyt97322q483vh8j3fm0x330h0pfcpumpm2tqgz2chmw567mhxtqdlncggz8uc8u66svnsqw26ra2v" + +[validator_account.tendermint_node_key] +pk = "tpknam1qpgcgptcjl22hl2te2uqnp33aqjmvfaud3a3f3sgtxezg7uu5rsv6d2flr3" +authorization = "signam1qq05nmg0v5w9377235dpuk7k5k7kkjx5zyewqr4ecd0yyawz3ll2r7jxq9ss9wpnl69c9s0t9aqyuf7y6e7avh8m6d6nvyt5qnmaz5qyay596t" + +[validator_account.eth_hot_key] +pk = "tpknam1qypnh98mexms8edj8rcwu0cayx0459p39dwzsffxrr394mf4cse707qcctyrx" +authorization = "signam1q86yxmjctxx7h59cl3tz8sf6j9r6wlxplv282fkm8yxyc8wvjkz4q8lhcavq8xa9jk3clnuxfpdg9hnp4t589ld3v2lv9tla3phucle7qysufnv4" + +[validator_account.eth_cold_key] +pk = "tpknam1qypz8zr0w8lsz3s98vh4p974xuxeedpecj9s2l3326r3kdz4tc0snrcpnc8yv" +authorization = "signam1qxxc4ulf7qlc0vdz477sgg3hms07vn3apkluxrq0erhchtw90yw9z2m6kmjcrgc8zks0fvwsmr88q0dxd3cs9zy7pz94wuum5urwu868qyzvqmr5" + +[validator_account.metadata] +email = "null@null.net" + +[validator_account.signatures] +tpknam1qrulnacf6l6lt2vlpc8y2yudlgzs9hzrfa9p66fv4p7vk8utf6m4554t3ak = "signam1qzg4cjyctnrnl8vpgp95tvjgwpcye3xfwchxq66de6wqn5ujwk6m69qd4n4mzx40ch48xtzhdhnq9m605pwm2v0gy422ehula4xt89cz39ngg0" + +[[bond]] +source = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +validator = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +amount = "100000" + +[bond.signatures] +tpknam1qrulnacf6l6lt2vlpc8y2yudlgzs9hzrfa9p66fv4p7vk8utf6m4554t3ak = "signam1qzwn66j9dx49eyg72fd7s2cw5l2va3p9dj07te0egf93p6qatf95hk447ty6s6cds55ggtz8dcr65xqqz00a0wclqrhqcknk504a2ps9jqe6f7" + +# 2. + +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qqwfpuvn8x7yqtquejhppef4vddv9ghusec2rkaxav38amamxaxpgj9cs79"] + +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qquurf975axryz4sf0jmyxpknkxp4cs7g8e8ahhpw089u6j3q9dy6qssdhz"] + +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qp7r3et2usz538fxzkm69h3awr7t0kgk7h6528za7pk4g2jldk5dz0qjkhx"] + +[[established_account]] +vp = "vp_user" +threshold = 1 +public_keys = ["tpknam1qrg6qx72e0vqhg8plg20hv97g3p3q092gl88jlngkly0hpmca2h2we44uzw"] + +[[bond]] +source = "tnam1qye83lg3ncsen8wjedgz27rxjktn0gcrc574p78e" +validator = "tnam1q9q3lph40w88cs5000k48thkw3f7s0m6mqrtfgss" +amount = "20000" + +[bond.signatures] +tpknam1qquurf975axryz4sf0jmyxpknkxp4cs7g8e8ahhpw089u6j3q9dy6qssdhz = "signam1qzgqntx4tqsrlwn2g2lwwhkcvwkjpd768fup0yr9ctunrc6yj89h57uxgv74vn3y5unz55slmlkyj0td5nu8wjvf52el3azn95uk3xcfjmzcpl" diff --git a/genesis/hardware/validity-predicates.toml b/genesis/hardware/validity-predicates.toml new file mode 100644 index 0000000000..0216abe982 --- /dev/null +++ b/genesis/hardware/validity-predicates.toml @@ -0,0 +1,10 @@ +# WASM Validity predicate that can be used for genesis accounts + +# Implicit VP +[wasm.vp_implicit] +filename = "vp_implicit.wasm" + +# Default user VP in established accounts +[wasm.vp_user] +filename = "vp_user.wasm" + diff --git a/genesis/localnet/balances.toml b/genesis/localnet/balances.toml index 1a41f87dad..e4db4e5c85 100644 --- a/genesis/localnet/balances.toml +++ b/genesis/localnet/balances.toml @@ -17,22 +17,22 @@ [token.NAM] # albert tnam1qxfj3sf6a0meahdu9t6znp05g8zx4dkjtgyn9gfu = "2000000" -tpknam1qrnw8mxyqlj60mykgevnldcj5mg2fya7fs5a8xqdkd2gwtxhef0zy8a2wha = "2000000" +tnam1qrr8r00nrf6490ff9zgfz52xrnfhdja7rqvldl46 = "2000000" # bertha tnam1q9rhgyv3ydq0zu3whnftvllqnvhvhm270qxay5tn = "2000000" -tpknam1qq52dx5e290wyh7ngdt6wudtyd502lg6ln49yvg3vz97e8j2ruux5e3yewq = "2000000" +tnam1qqc2ge6tg7s03nlshjr5d79dqyjr33aa8g2mxyzm = "2000000" # christel tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "2000000" -tpknam1qqwfpuvn8x7yqtquejhppef4vddv9ghusec2rkaxav38amamxaxpgj9cs79 = "2000000" +tnam1qz0nvec686e9pks8ynhm5ddq8ke7j2eey50uagtr = "2000000" # daewon -tpknam1qzz4x4fammhdcfa0g8xw4udkq8s4n6kjhzlxh00ul3da05wuu9wkykqqvjm = "100000000" +tnam1qpca48f45pdtpcz06rue7k4kfdcjrvrux5cr3pwn = "100000000" # ester -tpknam1qypvqpzu74nafjahlwyq272dj76qq9rz30dulyc94883tmj893mquqs74gxv4 = "1000000" +tnam1qpm3dpsv76ttu382vfggtr7m8n00na3sfyzm2g2q = "1000000" # validator-0 tnam1q9vhfdur7gadtwx4r223agpal0fvlqhywylf2mzx = "200000" -tpknam1qpzrttnzfyt6xfu2vy092eruasll3z52rjfexwapdw0rdww5uktlk3j73dw = "200000" +tnam1qrdrgx6d3rzl2f5yn6nde6wg20sl6kmtug3ecg7z = "200000" # validator-0-account-key -tpknam1qpg2tsrplvhu3fd7z7tq5ztc2ne3s7e2ahjl2a2cddufrzdyr752g666ytj = "1000000" +tnam1qzwnw8rdyg8c5nrdwrcd87pgdxygr2eyguzy9c44 = "1000000" [token.BTC] # albert @@ -42,9 +42,9 @@ tnam1q9rhgyv3ydq0zu3whnftvllqnvhvhm270qxay5tn = "1000000" # christel tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" # daewon-key -tpknam1qzz4x4fammhdcfa0g8xw4udkq8s4n6kjhzlxh00ul3da05wuu9wkykqqvjm = "1000000" +tnam1qpca48f45pdtpcz06rue7k4kfdcjrvrux5cr3pwn = "1000000" # ester-key -tpknam1qypvqpzu74nafjahlwyq272dj76qq9rz30dulyc94883tmj893mquqs74gxv4 = "1000000" +tnam1qpm3dpsv76ttu382vfggtr7m8n00na3sfyzm2g2q = "1000000" # validator-0 tnam1q9vhfdur7gadtwx4r223agpal0fvlqhywylf2mzx = "1000000" @@ -56,9 +56,9 @@ tnam1q9rhgyv3ydq0zu3whnftvllqnvhvhm270qxay5tn = "1000000" # christel tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" # daewon-key -tpknam1qzz4x4fammhdcfa0g8xw4udkq8s4n6kjhzlxh00ul3da05wuu9wkykqqvjm = "1000000" +tnam1qpca48f45pdtpcz06rue7k4kfdcjrvrux5cr3pwn = "1000000" # ester-key -tpknam1qypvqpzu74nafjahlwyq272dj76qq9rz30dulyc94883tmj893mquqs74gxv4 = "1000000" +tnam1qpm3dpsv76ttu382vfggtr7m8n00na3sfyzm2g2q = "1000000" # validator-0 tnam1q9vhfdur7gadtwx4r223agpal0fvlqhywylf2mzx = "1000000" @@ -71,9 +71,9 @@ tnam1q9rhgyv3ydq0zu3whnftvllqnvhvhm270qxay5tn = "1000000" # christel tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" # daewon-key -tpknam1qzz4x4fammhdcfa0g8xw4udkq8s4n6kjhzlxh00ul3da05wuu9wkykqqvjm = "1000000" +tnam1qpca48f45pdtpcz06rue7k4kfdcjrvrux5cr3pwn = "1000000" # ester-key -tpknam1qypvqpzu74nafjahlwyq272dj76qq9rz30dulyc94883tmj893mquqs74gxv4 = "1000000" +tnam1qpm3dpsv76ttu382vfggtr7m8n00na3sfyzm2g2q = "1000000" # validator-0 tnam1q9vhfdur7gadtwx4r223agpal0fvlqhywylf2mzx = "1000000" @@ -85,9 +85,9 @@ tnam1q9rhgyv3ydq0zu3whnftvllqnvhvhm270qxay5tn = "1000000" # christel tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" # daewon-key -tpknam1qzz4x4fammhdcfa0g8xw4udkq8s4n6kjhzlxh00ul3da05wuu9wkykqqvjm = "1000000" +tnam1qpca48f45pdtpcz06rue7k4kfdcjrvrux5cr3pwn = "1000000" # ester-key -tpknam1qypvqpzu74nafjahlwyq272dj76qq9rz30dulyc94883tmj893mquqs74gxv4 = "1000000" +tnam1qpm3dpsv76ttu382vfggtr7m8n00na3sfyzm2g2q = "1000000" # validator-0 tnam1q9vhfdur7gadtwx4r223agpal0fvlqhywylf2mzx = "1000000" @@ -99,9 +99,9 @@ tnam1q9rhgyv3ydq0zu3whnftvllqnvhvhm270qxay5tn = "1000000" # christel tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" # daewon-key -tpknam1qzz4x4fammhdcfa0g8xw4udkq8s4n6kjhzlxh00ul3da05wuu9wkykqqvjm = "1000000" +tnam1qpca48f45pdtpcz06rue7k4kfdcjrvrux5cr3pwn = "1000000" # ester-key -tpknam1qypvqpzu74nafjahlwyq272dj76qq9rz30dulyc94883tmj893mquqs74gxv4 = "1000000" +tnam1qpm3dpsv76ttu382vfggtr7m8n00na3sfyzm2g2q = "1000000" # validator-0 tnam1q9vhfdur7gadtwx4r223agpal0fvlqhywylf2mzx = "1000000" @@ -113,8 +113,8 @@ tnam1q9rhgyv3ydq0zu3whnftvllqnvhvhm270qxay5tn = "1000000" # christel tnam1q9sx4ekzqaq3xdxtruxkm764nhl00cvcsc7df5jf = "1000000" # daewon-key -tpknam1qzz4x4fammhdcfa0g8xw4udkq8s4n6kjhzlxh00ul3da05wuu9wkykqqvjm = "1000000" +tnam1qpca48f45pdtpcz06rue7k4kfdcjrvrux5cr3pwn = "1000000" # ester-key -tpknam1qypvqpzu74nafjahlwyq272dj76qq9rz30dulyc94883tmj893mquqs74gxv4 = "1000000" +tnam1qpm3dpsv76ttu382vfggtr7m8n00na3sfyzm2g2q = "1000000" # validator-0 tnam1q9vhfdur7gadtwx4r223agpal0fvlqhywylf2mzx = "1000000" diff --git a/genesis/localnet/parameters.toml b/genesis/localnet/parameters.toml index ef76cfb4c3..66cbefe091 100644 --- a/genesis/localnet/parameters.toml +++ b/genesis/localnet/parameters.toml @@ -19,11 +19,11 @@ epochs_per_year = 31_536_000 # The multiplier for masp epochs masp_epoch_multiplier = 2 # Max gas for block -max_block_gas = 20000000 +max_block_gas = 15_000_000 # Masp fee payment gas limit -masp_fee_payment_gas_limit = 150_000 +masp_fee_payment_gas_limit = 200_000 # Gas scale -gas_scale = 10_000_000 +gas_scale = 10_000 # Map of the cost per gas unit for every token allowed for fee payment [parameters.minimum_gas_price] diff --git a/genesis/starter/parameters.toml b/genesis/starter/parameters.toml index 2b4f5ea052..143c68fd5d 100644 --- a/genesis/starter/parameters.toml +++ b/genesis/starter/parameters.toml @@ -19,11 +19,11 @@ epochs_per_year = 31_536_000 # The multiplier for masp epochs masp_epoch_multiplier = 2 # Max gas for block -max_block_gas = 20000000 +max_block_gas = 15_000_000 # Masp fee payment gas limit -masp_fee_payment_gas_limit = 150_000 +masp_fee_payment_gas_limit = 200_000 # Gas scale -gas_scale = 10_000_000 +gas_scale = 10_000 # Map of the cost per gas unit for every token allowed for fee payment [parameters.minimum_gas_price] diff --git a/scripts/gen_localnet.py b/scripts/gen_localnet.py index 3cfe1facac..e9323bec64 100755 --- a/scripts/gen_localnet.py +++ b/scripts/gen_localnet.py @@ -160,7 +160,6 @@ def join_network( genesis_validator, "--pre-genesis-path", genesis_validator_path, - "--dont-prefetch-wasm", ) info(f"Validator {genesis_validator} joined {chain_id}") diff --git a/scripts/get_hermes.sh b/scripts/get_hermes.sh index 8c74b20bde..0923f26101 100755 --- a/scripts/get_hermes.sh +++ b/scripts/get_hermes.sh @@ -2,9 +2,9 @@ set -Eo pipefail -HERMES_MAJORMINOR="1.9" +HERMES_MAJORMINOR="1.10" HERMES_PATCH="0" -HERMES_SUFFIX="-namada-beta14-rc" +HERMES_SUFFIX="-namada-beta15-rc2" HERMES_REPO="https://github.com/heliaxdev/hermes" diff --git a/scripts/release.sh b/scripts/release.sh index ece65a0e0f..b3050aeabc 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -37,18 +37,9 @@ cd $REPO_ROOT/wasm_for_tests cargo update -w git add Cargo.lock git commit --fixup=$HASH_AFTER -cargo release --execute $VERSION -make all -git add ../*.wasm -git commit --fixup=$HASH_AFTER - -# build the wasm checksums (1 fixup) -cd $REPO_ROOT -make build-wasm-scripts-docker -git add wasm/checksums.json -git commit --fixup=$HASH_AFTER # update the changelog (1 fixup) +cd $REPO_ROOT unclog release $TAG_NAME unclog build > CHANGELOG.md git add .changelog CHANGELOG.md diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index f6ff22b622..d1afa43ba1 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -2443,7 +2443,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-apps", "ibc-clients", @@ -2456,7 +2456,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", @@ -2466,7 +2466,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "base64 0.22.1", "borsh", @@ -2487,7 +2487,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -2497,7 +2497,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2515,7 +2515,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", @@ -2524,7 +2524,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -2541,7 +2541,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -2558,7 +2558,7 @@ dependencies = [ [[package]] name = "ibc-client-wasm-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "base64 0.22.1", "displaydoc", @@ -2572,7 +2572,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -2581,7 +2581,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2597,7 +2597,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -2612,7 +2612,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2635,7 +2635,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -2648,7 +2648,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -2664,7 +2664,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2684,11 +2684,12 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", "displaydoc", + "ibc-core-host-types", "ibc-primitives", "ibc-proto", "ics23", @@ -2702,7 +2703,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-client-wasm-types", "ibc-core-client", @@ -2716,7 +2717,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2737,7 +2738,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2752,7 +2753,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2776,7 +2777,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -2794,7 +2795,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -2817,7 +2818,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2832,7 +2833,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -2846,7 +2847,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2865,7 +2866,7 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.7.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "proc-macro2", "quote", @@ -2875,7 +2876,7 @@ dependencies = [ [[package]] name = "ibc-primitives" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2915,7 +2916,7 @@ dependencies = [ [[package]] name = "ibc-query" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "displaydoc", "ibc", @@ -2926,7 +2927,7 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "basecoin-store", "derive_more", @@ -2938,7 +2939,7 @@ dependencies = [ "subtle-encoding", "tendermint 0.37.0", "tendermint-testgen", - "typed-builder 0.18.2", + "typed-builder", ] [[package]] @@ -3508,7 +3509,7 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "namada_account" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -3520,7 +3521,7 @@ dependencies = [ [[package]] name = "namada_controller" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "smooth-operator", @@ -3529,7 +3530,7 @@ dependencies = [ [[package]] name = "namada_core" -version = "0.41.0" +version = "0.42.0" dependencies = [ "bech32 0.8.1", "borsh", @@ -3579,7 +3580,7 @@ dependencies = [ [[package]] name = "namada_ethereum_bridge" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "ethers", @@ -3608,7 +3609,7 @@ dependencies = [ [[package]] name = "namada_events" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -3621,7 +3622,7 @@ dependencies = [ [[package]] name = "namada_gas" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -3633,7 +3634,7 @@ dependencies = [ [[package]] name = "namada_governance" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "itertools 0.12.1", @@ -3656,7 +3657,7 @@ dependencies = [ [[package]] name = "namada_ibc" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "data-encoding", @@ -3688,7 +3689,7 @@ dependencies = [ [[package]] name = "namada_macros" -version = "0.41.0" +version = "0.42.0" dependencies = [ "data-encoding", "proc-macro2", @@ -3699,7 +3700,7 @@ dependencies = [ [[package]] name = "namada_merkle_tree" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "eyre", @@ -3713,7 +3714,7 @@ dependencies = [ [[package]] name = "namada_parameters" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_macros", @@ -3728,7 +3729,7 @@ dependencies = [ [[package]] name = "namada_proof_of_stake" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "itertools 0.12.1", @@ -3753,14 +3754,14 @@ dependencies = [ [[package]] name = "namada_replay_protection" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", ] [[package]] name = "namada_sdk" -version = "0.41.0" +version = "0.42.0" dependencies = [ "async-trait", "bimap", @@ -3828,14 +3829,14 @@ dependencies = [ "tokio", "toml 0.5.11", "tracing", - "typed-builder 0.19.1", + "typed-builder", "xorf", "zeroize", ] [[package]] name = "namada_shielded_token" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "lazy_static", @@ -3862,7 +3863,7 @@ dependencies = [ [[package]] name = "namada_state" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "clru", @@ -3885,7 +3886,7 @@ dependencies = [ [[package]] name = "namada_storage" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "itertools 0.12.1", @@ -3902,7 +3903,7 @@ dependencies = [ [[package]] name = "namada_systems" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_storage", @@ -3910,16 +3911,18 @@ dependencies = [ [[package]] name = "namada_test_utils" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", + "namada_state", + "prost", "strum 0.24.1", ] [[package]] name = "namada_tests" -version = "0.41.0" +version = "0.42.0" dependencies = [ "concat-idents", "derivative", @@ -3949,7 +3952,7 @@ dependencies = [ [[package]] name = "namada_token" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -3965,7 +3968,7 @@ dependencies = [ [[package]] name = "namada_trans_token" -version = "0.41.0" +version = "0.42.0" dependencies = [ "konst", "namada_core", @@ -3981,7 +3984,7 @@ dependencies = [ [[package]] name = "namada_tx" -version = "0.41.0" +version = "0.42.0" dependencies = [ "ark-bls12-381", "bitflags 2.5.0", @@ -4009,7 +4012,7 @@ dependencies = [ [[package]] name = "namada_tx_env" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_events", @@ -4018,7 +4021,7 @@ dependencies = [ [[package]] name = "namada_tx_prelude" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "masp_primitives", @@ -4040,7 +4043,7 @@ dependencies = [ [[package]] name = "namada_vm" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "clru", @@ -4068,7 +4071,7 @@ dependencies = [ [[package]] name = "namada_vm_env" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "masp_primitives", @@ -4077,7 +4080,7 @@ dependencies = [ [[package]] name = "namada_vote_ext" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -4088,7 +4091,7 @@ dependencies = [ [[package]] name = "namada_vp" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_events", @@ -4103,7 +4106,7 @@ dependencies = [ [[package]] name = "namada_vp_env" -version = "0.41.0" +version = "0.42.0" dependencies = [ "derivative", "masp_primitives", @@ -4116,7 +4119,7 @@ dependencies = [ [[package]] name = "namada_vp_prelude" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_account", @@ -6704,7 +6707,7 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tx_become_validator" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6713,7 +6716,7 @@ dependencies = [ [[package]] name = "tx_bond" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_test_utils", @@ -6729,7 +6732,7 @@ dependencies = [ [[package]] name = "tx_bridge_pool" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6738,7 +6741,7 @@ dependencies = [ [[package]] name = "tx_change_consensus_key" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6747,7 +6750,7 @@ dependencies = [ [[package]] name = "tx_change_validator_commission" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_test_utils", @@ -6763,7 +6766,7 @@ dependencies = [ [[package]] name = "tx_change_validator_metadata" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6772,7 +6775,7 @@ dependencies = [ [[package]] name = "tx_claim_rewards" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6781,7 +6784,7 @@ dependencies = [ [[package]] name = "tx_deactivate_validator" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6790,7 +6793,7 @@ dependencies = [ [[package]] name = "tx_ibc" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6799,7 +6802,7 @@ dependencies = [ [[package]] name = "tx_init_account" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6808,7 +6811,7 @@ dependencies = [ [[package]] name = "tx_init_proposal" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6817,7 +6820,7 @@ dependencies = [ [[package]] name = "tx_reactivate_validator" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6826,7 +6829,7 @@ dependencies = [ [[package]] name = "tx_redelegate" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_test_utils", @@ -6842,7 +6845,7 @@ dependencies = [ [[package]] name = "tx_resign_steward" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6851,7 +6854,7 @@ dependencies = [ [[package]] name = "tx_reveal_pk" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6860,7 +6863,7 @@ dependencies = [ [[package]] name = "tx_transfer" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6869,7 +6872,7 @@ dependencies = [ [[package]] name = "tx_unbond" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_test_utils", @@ -6885,7 +6888,7 @@ dependencies = [ [[package]] name = "tx_unjail_validator" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6894,7 +6897,7 @@ dependencies = [ [[package]] name = "tx_update_account" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6903,7 +6906,7 @@ dependencies = [ [[package]] name = "tx_update_steward_commission" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6912,7 +6915,7 @@ dependencies = [ [[package]] name = "tx_vote_proposal" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_tx_prelude", @@ -6921,7 +6924,7 @@ dependencies = [ [[package]] name = "tx_withdraw" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_test_utils", @@ -6935,33 +6938,13 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "typed-builder" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" -dependencies = [ - "typed-builder-macro 0.18.2", -] - [[package]] name = "typed-builder" version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06fbd5b8de54c5f7c91f6fe4cebb949be2125d7758e630bb58b1d831dbce600" dependencies = [ - "typed-builder-macro 0.19.1", -] - -[[package]] -name = "typed-builder-macro" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", + "typed-builder-macro", ] [[package]] @@ -7123,7 +7106,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vp_implicit" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_test_utils", @@ -7139,7 +7122,7 @@ dependencies = [ [[package]] name = "vp_user" -version = "0.41.0" +version = "0.42.0" dependencies = [ "getrandom 0.2.15", "namada_test_utils", diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index bbaddfac31..3f1ffb98d5 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -32,7 +32,7 @@ members = [ authors = ["Heliax AG "] edition = "2021" license = "GPL-3.0" -version = "0.41.0" +version = "0.42.0" [workspace.dependencies] namada_tx_prelude = { path = "../crates/tx_prelude" } diff --git a/wasm/checksums.json b/wasm/checksums.json deleted file mode 100644 index 214edb98fb..0000000000 --- a/wasm/checksums.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "tx_become_validator.wasm": "tx_become_validator.7e050a410cd63c3dbcd909670ec94ce8c85d902446614e107bfaaf2cd8884f21.wasm", - "tx_bond.wasm": "tx_bond.76f633853c23ae641cfb391e55b2497b0f8e415b099d497a69aa4a5a8da3aefa.wasm", - "tx_bridge_pool.wasm": "tx_bridge_pool.094cc9f7b26e3f80d4c27ad80ea9f044b5276272d088bcfb00346381c4513fd4.wasm", - "tx_change_consensus_key.wasm": "tx_change_consensus_key.017e40783051971094da8416e2c7f470f1d3074276f78639a679682255d3e454.wasm", - "tx_change_validator_commission.wasm": "tx_change_validator_commission.ed8f2a4f3bde50a2554f0dc46dd002611d30de0ea1f42dd501242a0fcbb6834f.wasm", - "tx_change_validator_metadata.wasm": "tx_change_validator_metadata.9d5c62746062862fee478955e9f466b2cf382b4e1749a9841dad6a616588d909.wasm", - "tx_claim_rewards.wasm": "tx_claim_rewards.6935d856662d0dead13ce8cadc540582755aa84a95b0e0842548e0d122da84ff.wasm", - "tx_deactivate_validator.wasm": "tx_deactivate_validator.fb24ce20403ea01b6c05ab8ebc08824862dec3b1b411de806b057ded949216f3.wasm", - "tx_ibc.wasm": "tx_ibc.74015ec20700282700775f5df576db36b6b7f65c4819da21a900a9a4e817ba33.wasm", - "tx_init_account.wasm": "tx_init_account.b09f6d1b3ec4275e1bfcdfea9a4d6811f21cd831192c2eb591b9058d9e8fabcf.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.ade6cdaf5ca51afd31a878ae2d03be4cdfbd4b9b0f293cc5b2f7d44baf7b01f0.wasm", - "tx_reactivate_validator.wasm": "tx_reactivate_validator.5128cf4ee042c77e778489dfd3930974725077d0bfa638f7f8104ce5f9f98c3d.wasm", - "tx_redelegate.wasm": "tx_redelegate.65fd98f1b94f07c1469b76a72c4175fad1caaa72a7ef9d9b55df33d10a33f52e.wasm", - "tx_resign_steward.wasm": "tx_resign_steward.709185532cd801be422cf129a7657c43619cff0b4d441ad0ba40166f333b358c.wasm", - "tx_reveal_pk.wasm": "tx_reveal_pk.0aa78ff0e901c2c4d9d407dd9769b5e6a48ce12c29332d3113f1b10e9bf32673.wasm", - "tx_transfer.wasm": "tx_transfer.362c30269da7f4497eb1a7c094c75e0aa7c578d9f0eaf3979aeaaffda105ef1e.wasm", - "tx_unbond.wasm": "tx_unbond.1805394203f416f59f9ac958bcd2ee92196234bfe4580e71fa8f751fd0ab32a1.wasm", - "tx_unjail_validator.wasm": "tx_unjail_validator.65ad976d32046edc3d84d3b2bcb336062a753eee1427eda9db46d6641f2392bb.wasm", - "tx_update_account.wasm": "tx_update_account.9b4925aedf019da5e437aa5112730071c2e22e583a9473341ade8c44e19c15ff.wasm", - "tx_update_steward_commission.wasm": "tx_update_steward_commission.01c368cec0ec50e4b4a082bbf6b95e1be6059583b299c5536e01c9f709cf6ba5.wasm", - "tx_vote_proposal.wasm": "tx_vote_proposal.ae5ddd5a72fb24381dd41a70495ade61f0ab1967fdd73c98ab42bfd56e7a1e46.wasm", - "tx_withdraw.wasm": "tx_withdraw.420e1925aa35e7aadbaeff056179b82f57da1507fe65892ac621ba687d08d1ce.wasm", - "vp_implicit.wasm": "vp_implicit.1bd524107d97584f7304e41648bd4c6ba3e2404606b32e9e40784323ff34230f.wasm", - "vp_user.wasm": "vp_user.45e467b2f23f65a1ce3b658e15667f4e792f7433eb26e288aa6548031061106e.wasm" -} \ No newline at end of file diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index ce7efa14d9..5194c4dc82 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -2443,7 +2443,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-apps", "ibc-clients", @@ -2456,7 +2456,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", @@ -2466,7 +2466,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "base64 0.22.1", "borsh", @@ -2487,7 +2487,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -2497,7 +2497,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2515,7 +2515,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", @@ -2524,7 +2524,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -2541,7 +2541,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -2558,7 +2558,7 @@ dependencies = [ [[package]] name = "ibc-client-wasm-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "base64 0.22.1", "displaydoc", @@ -2572,7 +2572,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -2581,7 +2581,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2597,7 +2597,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -2612,7 +2612,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2635,7 +2635,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -2648,7 +2648,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -2664,7 +2664,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2684,11 +2684,12 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", "displaydoc", + "ibc-core-host-types", "ibc-primitives", "ibc-proto", "ics23", @@ -2702,7 +2703,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-client-wasm-types", "ibc-core-client", @@ -2716,7 +2717,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2737,7 +2738,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2752,7 +2753,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2776,7 +2777,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -2794,7 +2795,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -2817,7 +2818,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2832,7 +2833,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "derive_more", "displaydoc", @@ -2846,7 +2847,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2865,7 +2866,7 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.7.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "proc-macro2", "quote", @@ -2875,7 +2876,7 @@ dependencies = [ [[package]] name = "ibc-primitives" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "borsh", "derive_more", @@ -2915,7 +2916,7 @@ dependencies = [ [[package]] name = "ibc-query" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "displaydoc", "ibc", @@ -2926,7 +2927,7 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.53.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d#9f2df8a03d75558b3a8571b855b6ce5cea3b5f3d" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b#1dd9be8c1cdc773e6b5b0b3609f3390a9a69eb9b" dependencies = [ "basecoin-store", "derive_more", @@ -2938,7 +2939,7 @@ dependencies = [ "subtle-encoding", "tendermint 0.37.0", "tendermint-testgen", - "typed-builder 0.18.2", + "typed-builder", ] [[package]] @@ -3508,7 +3509,7 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "namada_account" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -3520,7 +3521,7 @@ dependencies = [ [[package]] name = "namada_controller" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "smooth-operator", @@ -3529,7 +3530,7 @@ dependencies = [ [[package]] name = "namada_core" -version = "0.41.0" +version = "0.42.0" dependencies = [ "bech32 0.8.1", "borsh", @@ -3579,7 +3580,7 @@ dependencies = [ [[package]] name = "namada_ethereum_bridge" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "ethers", @@ -3608,7 +3609,7 @@ dependencies = [ [[package]] name = "namada_events" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -3621,7 +3622,7 @@ dependencies = [ [[package]] name = "namada_gas" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -3633,7 +3634,7 @@ dependencies = [ [[package]] name = "namada_governance" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "itertools 0.12.1", @@ -3656,7 +3657,7 @@ dependencies = [ [[package]] name = "namada_ibc" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "data-encoding", @@ -3688,7 +3689,7 @@ dependencies = [ [[package]] name = "namada_macros" -version = "0.41.0" +version = "0.42.0" dependencies = [ "data-encoding", "proc-macro2", @@ -3699,7 +3700,7 @@ dependencies = [ [[package]] name = "namada_merkle_tree" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "eyre", @@ -3713,7 +3714,7 @@ dependencies = [ [[package]] name = "namada_parameters" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_macros", @@ -3728,7 +3729,7 @@ dependencies = [ [[package]] name = "namada_proof_of_stake" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "itertools 0.12.1", @@ -3753,14 +3754,14 @@ dependencies = [ [[package]] name = "namada_replay_protection" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", ] [[package]] name = "namada_sdk" -version = "0.41.0" +version = "0.42.0" dependencies = [ "async-trait", "bimap", @@ -3828,14 +3829,14 @@ dependencies = [ "tokio", "toml 0.5.11", "tracing", - "typed-builder 0.19.1", + "typed-builder", "xorf", "zeroize", ] [[package]] name = "namada_shielded_token" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "lazy_static", @@ -3862,7 +3863,7 @@ dependencies = [ [[package]] name = "namada_state" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "clru", @@ -3885,7 +3886,7 @@ dependencies = [ [[package]] name = "namada_storage" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "itertools 0.12.1", @@ -3902,7 +3903,7 @@ dependencies = [ [[package]] name = "namada_systems" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_storage", @@ -3910,16 +3911,18 @@ dependencies = [ [[package]] name = "namada_test_utils" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", + "namada_state", + "prost", "strum 0.24.1", ] [[package]] name = "namada_tests" -version = "0.41.0" +version = "0.42.0" dependencies = [ "concat-idents", "derivative", @@ -3949,7 +3952,7 @@ dependencies = [ [[package]] name = "namada_token" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -3965,7 +3968,7 @@ dependencies = [ [[package]] name = "namada_trans_token" -version = "0.41.0" +version = "0.42.0" dependencies = [ "konst", "namada_core", @@ -3981,7 +3984,7 @@ dependencies = [ [[package]] name = "namada_tx" -version = "0.41.0" +version = "0.42.0" dependencies = [ "ark-bls12-381", "bitflags 2.5.0", @@ -4009,7 +4012,7 @@ dependencies = [ [[package]] name = "namada_tx_env" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_events", @@ -4018,7 +4021,7 @@ dependencies = [ [[package]] name = "namada_tx_prelude" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "masp_primitives", @@ -4040,7 +4043,7 @@ dependencies = [ [[package]] name = "namada_vm" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "clru", @@ -4068,7 +4071,7 @@ dependencies = [ [[package]] name = "namada_vm_env" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "masp_primitives", @@ -4077,7 +4080,7 @@ dependencies = [ [[package]] name = "namada_vote_ext" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_core", @@ -4088,7 +4091,7 @@ dependencies = [ [[package]] name = "namada_vp" -version = "0.41.0" +version = "0.42.0" dependencies = [ "namada_core", "namada_events", @@ -4103,7 +4106,7 @@ dependencies = [ [[package]] name = "namada_vp_env" -version = "0.41.0" +version = "0.42.0" dependencies = [ "derivative", "masp_primitives", @@ -4116,7 +4119,7 @@ dependencies = [ [[package]] name = "namada_vp_prelude" -version = "0.41.0" +version = "0.42.0" dependencies = [ "borsh", "namada_account", @@ -6801,6 +6804,21 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tx_proposal_ibc_client_upgrade" +version = "0.41.0" +dependencies = [ + "getrandom 0.2.15", + "namada_test_utils", + "namada_tests", + "namada_tx_prelude", + "proptest", + "rlsf", + "test-log", + "tracing", + "tracing-subscriber", +] + [[package]] name = "tx_proposal_ibc_token_inflation" version = "0.41.0" @@ -6858,33 +6876,13 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "typed-builder" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" -dependencies = [ - "typed-builder-macro 0.18.2", -] - [[package]] name = "typed-builder" version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06fbd5b8de54c5f7c91f6fe4cebb949be2125d7758e630bb58b1d831dbce600" dependencies = [ - "typed-builder-macro 0.19.1", -] - -[[package]] -name = "typed-builder-macro" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.65", + "typed-builder-macro", ] [[package]] diff --git a/wasm_for_tests/Cargo.toml b/wasm_for_tests/Cargo.toml index 34b65d16a5..fc782df086 100644 --- a/wasm_for_tests/Cargo.toml +++ b/wasm_for_tests/Cargo.toml @@ -9,6 +9,7 @@ members = [ "tx_memory_limit", "tx_no_op", "tx_proposal_code", + "tx_proposal_ibc_client_upgrade", "tx_proposal_ibc_token_inflation", "tx_proposal_masp_reward", "tx_read_storage_key", diff --git a/wasm_for_tests/Makefile b/wasm_for_tests/Makefile index d0617bb03b..67a95dbbc1 100644 --- a/wasm_for_tests/Makefile +++ b/wasm_for_tests/Makefile @@ -12,6 +12,7 @@ wasms += tx_invalid_data wasms += tx_memory_limit wasms += tx_no_op wasms += tx_proposal_code +wasms += tx_proposal_ibc_client_upgrade wasms += tx_proposal_ibc_token_inflation wasms += tx_proposal_masp_reward wasms += tx_read_storage_key @@ -58,4 +59,4 @@ clean: deps: $(rustup) target add wasm32-unknown-unknown -.PHONY: all debug check clippy clippy-fix fmt fmt-check test clean deps \ No newline at end of file +.PHONY: all debug check clippy clippy-fix fmt fmt-check test clean deps diff --git a/wasm_for_tests/tx_fail.wasm b/wasm_for_tests/tx_fail.wasm index ef7832bdc0..f0c67486af 100755 Binary files a/wasm_for_tests/tx_fail.wasm and b/wasm_for_tests/tx_fail.wasm differ diff --git a/wasm_for_tests/tx_infinite_guest_gas.wasm b/wasm_for_tests/tx_infinite_guest_gas.wasm index 83a1c14ca3..81a18030a9 100755 Binary files a/wasm_for_tests/tx_infinite_guest_gas.wasm and b/wasm_for_tests/tx_infinite_guest_gas.wasm differ diff --git a/wasm_for_tests/tx_infinite_host_gas.wasm b/wasm_for_tests/tx_infinite_host_gas.wasm index 2ae250eabb..47375b4859 100755 Binary files a/wasm_for_tests/tx_infinite_host_gas.wasm and b/wasm_for_tests/tx_infinite_host_gas.wasm differ diff --git a/wasm_for_tests/tx_invalid_data.wasm b/wasm_for_tests/tx_invalid_data.wasm index e60a96c9ef..04b69b343a 100755 Binary files a/wasm_for_tests/tx_invalid_data.wasm and b/wasm_for_tests/tx_invalid_data.wasm differ diff --git a/wasm_for_tests/tx_memory_limit.wasm b/wasm_for_tests/tx_memory_limit.wasm index 141f247755..86ed951c73 100755 Binary files a/wasm_for_tests/tx_memory_limit.wasm and b/wasm_for_tests/tx_memory_limit.wasm differ diff --git a/wasm_for_tests/tx_no_op.wasm b/wasm_for_tests/tx_no_op.wasm index a789ec9ca2..1c383f22b8 100755 Binary files a/wasm_for_tests/tx_no_op.wasm and b/wasm_for_tests/tx_no_op.wasm differ diff --git a/wasm_for_tests/tx_proposal_code.wasm b/wasm_for_tests/tx_proposal_code.wasm index e771fb2839..0bfc9be8df 100755 Binary files a/wasm_for_tests/tx_proposal_code.wasm and b/wasm_for_tests/tx_proposal_code.wasm differ diff --git a/wasm_for_tests/tx_proposal_ibc_client_upgrade.wasm b/wasm_for_tests/tx_proposal_ibc_client_upgrade.wasm new file mode 100755 index 0000000000..4931f6efa0 Binary files /dev/null and b/wasm_for_tests/tx_proposal_ibc_client_upgrade.wasm differ diff --git a/wasm_for_tests/tx_proposal_ibc_client_upgrade/Cargo.toml b/wasm_for_tests/tx_proposal_ibc_client_upgrade/Cargo.toml new file mode 100644 index 0000000000..8af7fc02fb --- /dev/null +++ b/wasm_for_tests/tx_proposal_ibc_client_upgrade/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "tx_proposal_ibc_client_upgrade" +description = "Wasm transaction used for testing." +authors.workspace = true +edition.workspace = true +license.workspace = true +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +namada_test_utils.workspace = true +namada_tx_prelude.workspace = true +rlsf.workspace = true +getrandom.workspace = true + +[dev-dependencies] +namada_tests = { path = "../../crates/tests" } + +proptest = "1.4.0" +test-log = {version = "0.2.14", default-features = false, features = ["trace"]} +tracing = "0.1.30" +tracing-subscriber = {version = "0.3.7", default-features = false, features = ["env-filter", "fmt"]} + +[lib] +crate-type = ["cdylib"] diff --git a/wasm_for_tests/tx_proposal_ibc_client_upgrade/src/lib.rs b/wasm_for_tests/tx_proposal_ibc_client_upgrade/src/lib.rs new file mode 100644 index 0000000000..82db4e42b2 --- /dev/null +++ b/wasm_for_tests/tx_proposal_ibc_client_upgrade/src/lib.rs @@ -0,0 +1,30 @@ +use namada_test_utils::ibc::{ + make_new_client_state_bytes, make_new_consensus_state_bytes, +}; +use namada_tx_prelude::*; + +#[transaction] +fn apply_tx(ctx: &mut Ctx, _tx_data: BatchedTx) -> TxResult { + // This transaction will just store the IBC client state and the consensus + // state as if the chain was upgraded + let current_height = ctx.get_block_height()?.0; + // Make the states based on the last committed height + let last_committed_height = current_height - 1; + // Need to read the upgrade state with the next height + let upgrade_height = current_height + 1; + // The height of the new client state is the next after the upgrade + let height_after_upgrade = upgrade_height + 1; + let client_state = make_new_client_state_bytes(height_after_upgrade); + + let header = ctx.get_block_header(last_committed_height.into())?.unwrap(); + let consensus_state = make_new_consensus_state_bytes(header); + + let height = format!("0-{upgrade_height}").parse().unwrap(); + let upgraded_client_state_key = ibc::upgraded_client_state_key(height); + ctx.write_bytes(&upgraded_client_state_key, client_state)?; + let upgraded_consensus_state_key = + ibc::upgraded_consensus_state_key(height); + ctx.write_bytes(&upgraded_consensus_state_key, consensus_state)?; + + Ok(()) +} diff --git a/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm b/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm index 3aa222bd26..ba733efebd 100755 Binary files a/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm and b/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm differ diff --git a/wasm_for_tests/tx_proposal_masp_reward.wasm b/wasm_for_tests/tx_proposal_masp_reward.wasm index e47f6c426d..85172277d9 100755 Binary files a/wasm_for_tests/tx_proposal_masp_reward.wasm and b/wasm_for_tests/tx_proposal_masp_reward.wasm differ diff --git a/wasm_for_tests/tx_read_storage_key.wasm b/wasm_for_tests/tx_read_storage_key.wasm index 74291346c6..2fd89db131 100755 Binary files a/wasm_for_tests/tx_read_storage_key.wasm and b/wasm_for_tests/tx_read_storage_key.wasm differ diff --git a/wasm_for_tests/tx_write.wasm b/wasm_for_tests/tx_write.wasm index 9a58ce7495..ba1e822cf2 100755 Binary files a/wasm_for_tests/tx_write.wasm and b/wasm_for_tests/tx_write.wasm differ diff --git a/wasm_for_tests/vp_always_false.wasm b/wasm_for_tests/vp_always_false.wasm index 0cfe8b7d77..3d888d58d9 100755 Binary files a/wasm_for_tests/vp_always_false.wasm and b/wasm_for_tests/vp_always_false.wasm differ diff --git a/wasm_for_tests/vp_always_true.wasm b/wasm_for_tests/vp_always_true.wasm index c7841ca130..fbb6c3a2ba 100755 Binary files a/wasm_for_tests/vp_always_true.wasm and b/wasm_for_tests/vp_always_true.wasm differ diff --git a/wasm_for_tests/vp_eval.wasm b/wasm_for_tests/vp_eval.wasm index 7e58a7f092..0b01435788 100755 Binary files a/wasm_for_tests/vp_eval.wasm and b/wasm_for_tests/vp_eval.wasm differ diff --git a/wasm_for_tests/vp_infinite_guest_gas.wasm b/wasm_for_tests/vp_infinite_guest_gas.wasm index f4df2be7f9..41850ce091 100755 Binary files a/wasm_for_tests/vp_infinite_guest_gas.wasm and b/wasm_for_tests/vp_infinite_guest_gas.wasm differ diff --git a/wasm_for_tests/vp_infinite_host_gas.wasm b/wasm_for_tests/vp_infinite_host_gas.wasm index 86e21cfcab..9cc796851e 100755 Binary files a/wasm_for_tests/vp_infinite_host_gas.wasm and b/wasm_for_tests/vp_infinite_host_gas.wasm differ diff --git a/wasm_for_tests/vp_memory_limit.wasm b/wasm_for_tests/vp_memory_limit.wasm index 9c1d033f77..1a12e055a7 100755 Binary files a/wasm_for_tests/vp_memory_limit.wasm and b/wasm_for_tests/vp_memory_limit.wasm differ diff --git a/wasm_for_tests/vp_read_storage_key.wasm b/wasm_for_tests/vp_read_storage_key.wasm index 3bc22837d2..524a054244 100755 Binary files a/wasm_for_tests/vp_read_storage_key.wasm and b/wasm_for_tests/vp_read_storage_key.wasm differ