diff --git a/.github/workflows/rust-aptos-checks.yml b/.github/workflows/rust-aptos-checks.yml
index 9dd3e8d9d..66d208853 100644
--- a/.github/workflows/rust-aptos-checks.yml
+++ b/.github/workflows/rust-aptos-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/aptos
- run: cd rust/apps/aptos && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/aptos && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-arweave-checks.yml b/.github/workflows/rust-arweave-checks.yml
index 7b9576cc7..2cccc8567 100644
--- a/.github/workflows/rust-arweave-checks.yml
+++ b/.github/workflows/rust-arweave-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/arweave
- run: cd rust/apps/arweave && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/arweave && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-bitcoin-checks.yml b/.github/workflows/rust-bitcoin-checks.yml
index dc072311d..8ed35fb6d 100644
--- a/.github/workflows/rust-bitcoin-checks.yml
+++ b/.github/workflows/rust-bitcoin-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/bitcoin
- run: cd rust/apps/bitcoin && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/bitcoin && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-cardano-checks.yml b/.github/workflows/rust-cardano-checks.yml
index 83c0814e1..8529ec310 100644
--- a/.github/workflows/rust-cardano-checks.yml
+++ b/.github/workflows/rust-cardano-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/cardano
- run: cd rust/apps/cardano && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/cardano && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-cosmos-checks.yml b/.github/workflows/rust-cosmos-checks.yml
index 1c7e82982..5ed3ddfd9 100644
--- a/.github/workflows/rust-cosmos-checks.yml
+++ b/.github/workflows/rust-cosmos-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/cosmos
- run: cd rust/apps/cosmos && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/cosmos && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-ethereum-checks.yml b/.github/workflows/rust-ethereum-checks.yml
index 2cf10b92c..a5630cef5 100644
--- a/.github/workflows/rust-ethereum-checks.yml
+++ b/.github/workflows/rust-ethereum-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/ethereum
- run: cd rust/apps/ethereum && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/ethereum && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-fmt-checks.yml b/.github/workflows/rust-fmt-checks.yml
index ff58628fb..08fea9737 100644
--- a/.github/workflows/rust-fmt-checks.yml
+++ b/.github/workflows/rust-fmt-checks.yml
@@ -15,40 +15,40 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
target: x86_64-apple-darwin
components: rustfmt
- name: Run rust/apps/bitcoin
- run: cd rust/apps/bitcoin && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/bitcoin && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/ethereum
- run: cd rust/apps/ethereum && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/ethereum && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/solana
- run: cd rust/apps/solana && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/solana && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/cardano
- run: cd rust/apps/cardano && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/cardano && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/tron
- run: cd rust/apps/tron && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/tron && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/near
- run: cd rust/apps/near && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/near && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/xrp
- run: cd rust/apps/xrp && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/xrp && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/cosmos
- run: cd rust/apps/cosmos && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/cosmos && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/aptos
- run: cd rust/apps/aptos && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/aptos && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/sui
- run: cd rust/apps/sui && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/sui && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/arweave
- run: cd rust/apps/arweave && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/arweave && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/stellar
- run: cd rust/apps/stellar && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/stellar && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/utils
- run: cd rust/apps/utils && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/utils && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/apps/wallets
- run: cd rust/apps/wallets && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/apps/wallets && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/keystore
- run: cd rust/keystore && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/keystore && cargo +nightly-2024-01-31 fmt --check
- name: Run rust/rust_c
- run: cd rust/rust_c && cargo +nightly-2023-12-01 fmt --check
+ run: cd rust/rust_c && cargo +nightly-2024-01-31 fmt --check
diff --git a/.github/workflows/rust-keystore-checks.yml b/.github/workflows/rust-keystore-checks.yml
index 8eb078062..e1de29564 100644
--- a/.github/workflows/rust-keystore-checks.yml
+++ b/.github/workflows/rust-keystore-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/keystore
- run: cd rust/keystore && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/keystore && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-near-checks.yml b/.github/workflows/rust-near-checks.yml
index 858ca04b3..20ff8aff8 100644
--- a/.github/workflows/rust-near-checks.yml
+++ b/.github/workflows/rust-near-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/near
- run: cd rust/apps/near && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/near && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-solana-checks.yml b/.github/workflows/rust-solana-checks.yml
index a5cff2ae4..104896154 100644
--- a/.github/workflows/rust-solana-checks.yml
+++ b/.github/workflows/rust-solana-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/solana
- run: cd rust/apps/solana && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/solana && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-stellar-checks.yml b/.github/workflows/rust-stellar-checks.yml
index 2768f4d1c..0f74ee527 100644
--- a/.github/workflows/rust-stellar-checks.yml
+++ b/.github/workflows/rust-stellar-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/stellar
- run: cd rust/apps/stellar && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/stellar && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-sui-checks.yml b/.github/workflows/rust-sui-checks.yml
index 7695295a7..9358e10fd 100644
--- a/.github/workflows/rust-sui-checks.yml
+++ b/.github/workflows/rust-sui-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/sui
- run: cd rust/apps/sui && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/sui && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-ton-checks.yml b/.github/workflows/rust-ton-checks.yml
index 4c2fc63ac..f9769e04a 100644
--- a/.github/workflows/rust-ton-checks.yml
+++ b/.github/workflows/rust-ton-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/ton
- run: cd rust/apps/ton && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/ton && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-tron-checks.yml b/.github/workflows/rust-tron-checks.yml
index e948c4593..993b46215 100644
--- a/.github/workflows/rust-tron-checks.yml
+++ b/.github/workflows/rust-tron-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/tron
- run: cd rust/apps/tron && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/tron && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-utils-checks.yml b/.github/workflows/rust-utils-checks.yml
index 57ccdd767..9aec2192b 100644
--- a/.github/workflows/rust-utils-checks.yml
+++ b/.github/workflows/rust-utils-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/utils
- run: cd rust/apps/utils && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/utils && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-wallets-checks.yml b/.github/workflows/rust-wallets-checks.yml
index 1f64b82e9..60cbb9576 100644
--- a/.github/workflows/rust-wallets-checks.yml
+++ b/.github/workflows/rust-wallets-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/wallets
- run: cd rust/apps/wallets && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/wallets && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/.github/workflows/rust-xrp-checks.yml b/.github/workflows/rust-xrp-checks.yml
index 811732375..6b7d7a44a 100644
--- a/.github/workflows/rust-xrp-checks.yml
+++ b/.github/workflows/rust-xrp-checks.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
- toolchain: nightly-2023-12-01
+ toolchain: nightly-2024-01-31
override: true
components: rustfmt
target: x86_64-apple-darwin
@@ -24,4 +24,4 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov
- name: Run rust/apps/xrp
- run: cd rust/apps/xrp && cargo +nightly-2023-12-01 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
+ run: cd rust/apps/xrp && cargo +nightly-2024-01-31 llvm-cov --fail-under-functions 50 --fail-under-lines 50 --fail-under-regions 50
diff --git a/Dockerfile b/Dockerfile
index 7bd272899..1905bc7e9 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -16,8 +16,8 @@ RUN apt-get install -y \
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly -y
ENV PATH=/root/.cargo/bin:$PATH
-RUN rustup default nightly-2023-12-01
-RUN rustup target add thumbv7em-none-eabihf --toolchain nightly-2023-12-01
+RUN rustup default nightly-2024-01-31
+RUN rustup target add thumbv7em-none-eabihf --toolchain nightly-2024-01-31
RUN cargo install cbindgen bindgen-cli
RUN pip3 install PyYaml
diff --git a/README.md b/README.md
index 2ca35404e..f119f402b 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ brew install armmbed/formulae/arm-none-eabi-gcc
# Install Rust
# For instructions, visit https://www.rust-lang.org/tools/install
-rustup install nightly-2023-12-01
+rustup install nightly-2024-01-31
rustup target add thumbv7em-none-eabihf
cargo install bindgen-cli
cargo install cbindgen
diff --git a/docs/SIMULATOR.md b/docs/SIMULATOR.md
index 0315de44e..dc5b82234 100644
--- a/docs/SIMULATOR.md
+++ b/docs/SIMULATOR.md
@@ -13,7 +13,7 @@ We recommend creating a virtual env for this project: https://docs.python.org/3/
Please follow Rust official site: https://www.rust-lang.org/tools/install
We have fixed the rust version in most of our rust libs so please run this command when you finish rust setup:
-> rustup install nightly-2023-12-01
+> rustup install nightly-2024-01-31
`cbindgen` is also required to build essential C header files for Rust libs, so run the following after rust setup:
> cargo install cbindgen
diff --git a/docs/protocols/ur_registrys/draft/zcash.md b/docs/protocols/ur_registrys/draft/zcash.md
new file mode 100644
index 000000000..c41757a3f
--- /dev/null
+++ b/docs/protocols/ur_registrys/draft/zcash.md
@@ -0,0 +1,59 @@
+## Keystone Zcash UR Registries
+
+This protocol is based on the [Uniform Resources](https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md). It describes the data schemas (UR Registries) used in Zcash integrations.
+
+### Introduction
+
+Keystone's QR workflow involves two main steps: linking the wallet and signing data, broken down into three sub-steps:
+
+1. **Wallet Linking:** Keystone generates a QR code with public key info for the Watch-Only wallet to scan and import.
+2. **Transaction Creation:** The Watch-Only wallet creates a transaction and generates a QR code for Keystone to scan, parse, and display.
+3. **Signing Authorization:** Keystone signs the transaction, displays the result as a QR code for the Watch-Only wallet to scan and broadcast.
+
+Two UR Registries are needed for these steps, utilizing the Partially Created Zcash Transaction structure.
+
+### Zcash Accounts
+
+#### Unified Full Viewing Key (UFVK)
+
+UFVK is a standard account expression format in Zcash as per [ZIP-316](https://zips.z.cash/zip-0316). It consists of:
+
+1. Transparent
+2. Sprout
+3. Sapling
+4. Orchard
+
+This protocol focuses on the Transparent and Orchard components.
+
+#### CDDL for Zcash Accounts
+
+The specification uses CDDL and includes `crypto-hdkey` and `crypto-key-path` specs defined in https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-007-hdkey.md.
+
+```cddl
+zcash-accounts = {
+ seed-fingerprint: bytes.32, ; the seed fingerprint specified by ZIP-32 to identify the wallet
+ accounts: [+ zcash-ufvk],
+ ? origin: text, ; source of data, e.g., Keystone
+}
+
+zcash-ufvk = {
+ ? transparent: crypto-hdkey,
+ orchard: zcash-fvk,
+ ? name: text,
+}
+
+zcash-fvk = {
+ key-path: crypto-key-path,
+ key-data: bytes,
+}
+```
+
+`zcash-ufvk` describes the UFVK of a Zcash account. Each seed has multiple accounts with different indexes. For index 0, `zcash-ufvk` should contain a BIP32 extended public key with path `M/44'/133'/0'` (transparent) and an Orchard FVK with path `M_orchard/32'/133'/0'` (Orchard).
+
+#### CDDL for Zcash PCZT
+
+```cddl
+zcash-pczt {
+ data: bytes, ; Zcash PCZT, signatures inserted after signing.
+}
+```
diff --git a/images/coin/coinZec.png b/images/coin/coinZec.png
new file mode 100644
index 000000000..98e2b0968
Binary files /dev/null and b/images/coin/coinZec.png differ
diff --git a/images/wallet/walletZashi.png b/images/wallet/walletZashi.png
new file mode 100644
index 000000000..30a1217db
Binary files /dev/null and b/images/wallet/walletZashi.png differ
diff --git a/images/walletList/walletListZashi.png b/images/walletList/walletListZashi.png
new file mode 100644
index 000000000..64a7dd70c
Binary files /dev/null and b/images/walletList/walletListZashi.png differ
diff --git a/keystone3-firmware-release b/keystone3-firmware-release
index 463a64395..659306f6e 160000
--- a/keystone3-firmware-release
+++ b/keystone3-firmware-release
@@ -1 +1 @@
-Subproject commit 463a643957ae2e2045ec6f257f65646791cab078
+Subproject commit 659306f6e234e43e732ae93b7ed2e24ffe6bd5ef
diff --git a/rust-toolchain b/rust-toolchain
index 3d41b0cc4..a88cc5761 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1 +1 @@
-nightly-2023-12-01
\ No newline at end of file
+nightly-2024-01-31
\ No newline at end of file
diff --git a/rust/CMakeLists.txt b/rust/CMakeLists.txt
index f092de89d..ccc78dbb2 100644
--- a/rust/CMakeLists.txt
+++ b/rust/CMakeLists.txt
@@ -22,7 +22,7 @@ if(NOT BUILD_TYPE STREQUAL "Simulator")
add_custom_target(rust_c ALL
COMMAND ${CBINDGEN_EXE} ${CBINDGEN_FLAG}
- COMMAND rustup run nightly-2023-12-01 ${RUST_CARGO_EXECUTABLE} build ${CARGO_FLAG}
+ COMMAND rustup run nightly-2024-01-31 ${RUST_CARGO_EXECUTABLE} build ${CARGO_FLAG}
COMMAND ${COPY_COMMAND}
WORKING_DIRECTORY ${RUST_DIR}
)
@@ -44,7 +44,7 @@ else()
add_custom_target(rust_c ALL
COMMAND ${CBINDGEN_EXE} ${CBINDGEN_FLAG}
- COMMAND rustup run nightly-2023-12-01 ${RUST_CARGO_EXECUTABLE} build ${CARGO_FLAG}
+ COMMAND rustup run nightly-2024-01-31 ${RUST_CARGO_EXECUTABLE} build ${CARGO_FLAG}
COMMAND ${COPY_COMMAND}
WORKING_DIRECTORY ${RUST_DIR}
)
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index 1347260a5..d49d086ab 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -20,6 +20,16 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
+[[package]]
+name = "aead"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
+dependencies = [
+ "crypto-common",
+ "generic-array",
+]
+
[[package]]
name = "aes"
version = "0.8.4"
@@ -119,14 +129,14 @@ version = "0.1.0"
dependencies = [
"app_utils",
"base64 0.11.0",
- "bech32 0.10.0-beta",
+ "bech32 0.11.0",
"bitcoin",
- "bitcoin_hashes 0.13.0",
+ "bitcoin_hashes 0.14.0",
"core2",
"cryptoxide",
"either",
"hex",
- "itertools",
+ "itertools 0.13.0",
"keystore",
"rust_tools",
"serde",
@@ -140,7 +150,7 @@ name = "app_cardano"
version = "0.1.0"
dependencies = [
"app_utils",
- "bech32 0.10.0-beta",
+ "bech32 0.11.0",
"bitcoin",
"cardano-serialization-lib",
"cryptoxide",
@@ -158,7 +168,7 @@ version = "0.1.0"
dependencies = [
"app_utils",
"base64 0.11.0",
- "bech32 0.10.0-beta",
+ "bech32 0.11.0",
"bitcoin",
"cryptoxide",
"hex",
@@ -230,7 +240,7 @@ dependencies = [
"serde",
"serde_derive",
"serde_json",
- "sha2 0.9.9",
+ "sha2 0.10.8",
"thiserror-core",
"uint",
"ur-registry",
@@ -276,7 +286,7 @@ dependencies = [
"crc",
"cryptoxide",
"hex",
- "itertools",
+ "itertools 0.13.0",
"keystore",
"lazy_static",
"num-bigint",
@@ -330,6 +340,7 @@ dependencies = [
"rust_tools",
"serde_json",
"ur-registry",
+ "zcash_vendor",
]
[[package]]
@@ -350,6 +361,23 @@ dependencies = [
"thiserror-core",
]
+[[package]]
+name = "app_zcash"
+version = "0.1.0"
+dependencies = [
+ "app_utils",
+ "bitcoin",
+ "bitvec",
+ "blake2b_simd",
+ "hex",
+ "keystore",
+ "rand_core 0.6.4",
+ "rust_tools",
+ "thiserror-core",
+ "zcash_note_encryption",
+ "zcash_vendor",
+]
+
[[package]]
name = "aptos_rust_c"
version = "0.1.0"
@@ -403,6 +431,15 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
+[[package]]
+name = "atomic-polyfill"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
+dependencies = [
+ "critical-section",
+]
+
[[package]]
name = "autocfg"
version = "1.4.0"
@@ -415,6 +452,16 @@ version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
+[[package]]
+name = "base58ck"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f"
+dependencies = [
+ "bitcoin-internals",
+ "bitcoin_hashes 0.14.0",
+]
+
[[package]]
name = "base64"
version = "0.11.0"
@@ -457,9 +504,9 @@ checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
[[package]]
name = "bech32"
-version = "0.10.0-beta"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea"
+checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d"
[[package]]
name = "bincode"
@@ -470,6 +517,21 @@ dependencies = [
"serde",
]
+[[package]]
+name = "bip32"
+version = "0.5.2"
+source = "git+https://github.com/KeystoneHQ/crates.git?rev=9873e8fd56007d792fa60d6e844fdb75d527c858#9873e8fd56007d792fa60d6e844fdb75d527c858"
+dependencies = [
+ "bs58 0.5.1",
+ "hmac",
+ "rand_core 0.6.4",
+ "ripemd",
+ "secp256k1",
+ "sha2 0.10.8",
+ "subtle",
+ "zeroize",
+]
+
[[package]]
name = "bit_field"
version = "0.10.2"
@@ -478,13 +540,16 @@ checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]]
name = "bitcoin"
-version = "0.31.1"
-source = "git+https://github.com/KeystoneHQ/rust-bitcoin.git?tag=v0.31.2#f4fc5bef20b4ffe1f25cb45dee0f345e4f66ab54"
+version = "0.32.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026"
dependencies = [
- "bech32 0.10.0-beta",
+ "base58ck",
+ "bech32 0.11.0",
"bitcoin-internals",
- "bitcoin_hashes 0.13.0",
- "core2",
+ "bitcoin-io",
+ "bitcoin-units",
+ "bitcoin_hashes 0.14.0",
"hex-conservative",
"hex_lit",
"secp256k1",
@@ -492,9 +557,15 @@ dependencies = [
[[package]]
name = "bitcoin-internals"
-version = "0.2.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb"
+checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2"
+
+[[package]]
+name = "bitcoin-io"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf"
[[package]]
name = "bitcoin-private"
@@ -502,6 +573,15 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57"
+[[package]]
+name = "bitcoin-units"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2"
+dependencies = [
+ "bitcoin-internals",
+]
+
[[package]]
name = "bitcoin_hashes"
version = "0.12.0"
@@ -513,12 +593,11 @@ dependencies = [
[[package]]
name = "bitcoin_hashes"
-version = "0.13.0"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b"
+checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16"
dependencies = [
- "bitcoin-internals",
- "core2",
+ "bitcoin-io",
"hex-conservative",
]
@@ -560,6 +639,18 @@ dependencies = [
"core2",
]
+[[package]]
+name = "bitvec"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
[[package]]
name = "blake2"
version = "0.10.6"
@@ -569,6 +660,17 @@ dependencies = [
"digest 0.10.7",
]
+[[package]]
+name = "blake2b_simd"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "constant_time_eq",
+]
+
[[package]]
name = "block"
version = "0.1.6"
@@ -609,6 +711,19 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "bls12_381"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403"
+dependencies = [
+ "ff",
+ "group",
+ "pairing",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
[[package]]
name = "borsh"
version = "0.9.3"
@@ -774,7 +889,7 @@ dependencies = [
"ed25519-bip32-core",
"getrandom",
"hex",
- "itertools",
+ "itertools 0.10.5",
"js-sys",
"noop_proc_macro",
"num",
@@ -803,7 +918,7 @@ dependencies = [
"cty",
"ed25519-bip32-core",
"hex",
- "itertools",
+ "itertools 0.13.0",
"keystore",
"rust_tools",
"ur-registry",
@@ -847,6 +962,30 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+[[package]]
+name = "chacha20"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
+[[package]]
+name = "chacha20poly1305"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
+dependencies = [
+ "aead",
+ "chacha20",
+ "cipher",
+ "poly1305",
+ "zeroize",
+]
+
[[package]]
name = "chrono"
version = "0.4.38"
@@ -865,6 +1004,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
+ "zeroize",
]
[[package]]
@@ -885,6 +1025,12 @@ dependencies = [
"bitflags 1.3.2",
]
+[[package]]
+name = "cobs"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
+
[[package]]
name = "cocoa"
version = "0.24.1"
@@ -940,9 +1086,10 @@ dependencies = [
"app_utils",
"app_wallets",
"app_xrp",
+ "app_zcash",
"base64 0.11.0",
"bitcoin",
- "bitcoin_hashes 0.13.0",
+ "bitcoin_hashes 0.14.0",
"cryptoxide",
"cstr_core",
"cty",
@@ -963,6 +1110,12 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+[[package]]
+name = "constant_time_eq"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
+
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -1335,6 +1488,18 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+[[package]]
+name = "embedded-io"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
+
+[[package]]
+name = "embedded-io"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
+
[[package]]
name = "equivalent"
version = "1.0.1"
@@ -1442,7 +1607,7 @@ dependencies = [
"cstr_core",
"cty",
"hex",
- "itertools",
+ "itertools 0.13.0",
"keystore",
"rust_tools",
"serde_json",
@@ -1471,6 +1636,14 @@ dependencies = [
"zune-inflate",
]
+[[package]]
+name = "f4jumble"
+version = "0.1.1"
+source = "git+https://github.com/zcash/librustzcash.git?rev=9407f09208d5574a3ba7bf3e6963741114ba77c2#9407f09208d5574a3ba7bf3e6963741114ba77c2"
+dependencies = [
+ "blake2b_simd",
+]
+
[[package]]
name = "fastrand"
version = "2.1.1"
@@ -1486,6 +1659,17 @@ dependencies = [
"simd-adler32",
]
+[[package]]
+name = "ff"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+dependencies = [
+ "bitvec",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
[[package]]
name = "fixed-hash"
version = "0.7.0"
@@ -1590,12 +1774,32 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
+[[package]]
+name = "fpe"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26c4b37de5ae15812a764c958297cfc50f5c010438f60c6ce75d11b802abd404"
+dependencies = [
+ "cbc",
+ "cipher",
+ "libm",
+ "num-bigint",
+ "num-integer",
+ "num-traits",
+]
+
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
+[[package]]
+name = "funty"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
+
[[package]]
name = "futures"
version = "0.3.31"
@@ -1704,6 +1908,18 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "getset"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c"
+dependencies = [
+ "proc-macro-error2",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.85",
+]
+
[[package]]
name = "gif"
version = "0.13.1"
@@ -1724,6 +1940,17 @@ dependencies = [
"hashbrown 0.11.2",
]
+[[package]]
+name = "group"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+dependencies = [
+ "ff",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
[[package]]
name = "half"
version = "2.4.1"
@@ -1734,6 +1961,27 @@ dependencies = [
"crunchy",
]
+[[package]]
+name = "halo2_poseidon"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa3da60b81f02f9b33ebc6252d766f843291fb4d2247a07ae73d20b791fc56f"
+dependencies = [
+ "bitvec",
+ "ff",
+ "group",
+ "pasta_curves",
+]
+
+[[package]]
+name = "hash32"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
+dependencies = [
+ "byteorder",
+]
+
[[package]]
name = "hashbrown"
version = "0.11.2"
@@ -1774,6 +2022,20 @@ version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
+[[package]]
+name = "heapless"
+version = "0.7.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
+dependencies = [
+ "atomic-polyfill",
+ "hash32",
+ "rustc_version",
+ "serde",
+ "spin",
+ "stable_deref_trait",
+]
+
[[package]]
name = "heck"
version = "0.4.1"
@@ -1794,11 +2056,11 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hex-conservative"
-version = "0.1.2"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20"
+checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd"
dependencies = [
- "core2",
+ "arrayvec",
]
[[package]]
@@ -1807,6 +2069,15 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd"
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest 0.10.7",
+]
+
[[package]]
name = "home"
version = "0.5.9"
@@ -1878,6 +2149,15 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "incrementalmerkletree"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "216c71634ac6f6ed13c2102d64354c0a04dcbdc30e31692c5972d3974d8b6d97"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -1928,6 +2208,15 @@ dependencies = [
"either",
]
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itoa"
version = "1.0.11"
@@ -1952,6 +2241,20 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "jubjub"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8499f7a74008aafbecb2a2e608a3e13e4dd3e84df198b604451efe93f2de6e61"
+dependencies = [
+ "bitvec",
+ "bls12_381",
+ "ff",
+ "group",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
[[package]]
name = "keccak"
version = "0.1.5"
@@ -1974,10 +2277,12 @@ dependencies = [
"hex",
"num-bigint-dig",
"rand_chacha",
+ "rand_core 0.6.4",
"rsa",
"rust_tools",
"sha2 0.10.8",
"thiserror-core",
+ "zcash_vendor",
]
[[package]]
@@ -2119,6 +2424,12 @@ dependencies = [
"autocfg",
]
+[[package]]
+name = "memuse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964"
+
[[package]]
name = "minicbor"
version = "0.19.1"
@@ -2221,7 +2532,7 @@ dependencies = [
"common_rust_c",
"cstr_core",
"cty",
- "itertools",
+ "itertools 0.13.0",
"keystore",
"rust_tools",
"ur-registry",
@@ -2240,6 +2551,11 @@ dependencies = [
"pin-utils",
]
+[[package]]
+name = "nonempty"
+version = "0.10.0"
+source = "git+https://github.com/nuttycom/nonempty.git?rev=38d37189faecb2a0e3d6adc05aa24e1b93c2483b#38d37189faecb2a0e3d6adc05aa24e1b93c2483b"
+
[[package]]
name = "noop_proc_macro"
version = "0.3.0"
@@ -2390,6 +2706,38 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
+[[package]]
+name = "orchard"
+version = "0.10.1"
+source = "git+https://github.com/zcash/orchard.git?rev=e0cc7ac53ad8c97661b312a8b1c064f4cd3c6629#e0cc7ac53ad8c97661b312a8b1c064f4cd3c6629"
+dependencies = [
+ "aes",
+ "bitvec",
+ "blake2b_simd",
+ "core2",
+ "ff",
+ "fpe",
+ "getset",
+ "group",
+ "halo2_poseidon",
+ "hex",
+ "incrementalmerkletree",
+ "lazy_static",
+ "memuse",
+ "nonempty",
+ "pasta_curves",
+ "rand",
+ "reddsa",
+ "serde",
+ "sinsemilla",
+ "subtle",
+ "tracing",
+ "visibility",
+ "zcash_note_encryption",
+ "zcash_spec",
+ "zip32",
+]
+
[[package]]
name = "ordered-float"
version = "3.9.2"
@@ -2399,6 +2747,15 @@ dependencies = [
"num-traits",
]
+[[package]]
+name = "pairing"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f"
+dependencies = [
+ "group",
+]
+
[[package]]
name = "parity-scale-codec"
version = "3.6.12"
@@ -2423,12 +2780,45 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "pasta_curves"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095"
+dependencies = [
+ "blake2b_simd",
+ "ff",
+ "group",
+ "lazy_static",
+ "rand",
+ "static_assertions",
+ "subtle",
+]
+
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+[[package]]
+name = "pczt"
+version = "0.1.0"
+source = "git+https://github.com/zcash/librustzcash.git?rev=9407f09208d5574a3ba7bf3e6963741114ba77c2#9407f09208d5574a3ba7bf3e6963741114ba77c2"
+dependencies = [
+ "ff",
+ "getset",
+ "nonempty",
+ "orchard",
+ "pasta_curves",
+ "postcard",
+ "secp256k1",
+ "serde",
+ "serde_with 3.11.0",
+ "zcash_protocol",
+ "zcash_transparent",
+]
+
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -2540,12 +2930,36 @@ dependencies = [
"miniz_oxide 0.8.0",
]
+[[package]]
+name = "poly1305"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
+dependencies = [
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash",
+]
+
[[package]]
name = "portable-atomic"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
+[[package]]
+name = "postcard"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8"
+dependencies = [
+ "cobs",
+ "embedded-io 0.4.0",
+ "embedded-io 0.6.1",
+ "heapless",
+ "serde",
+]
+
[[package]]
name = "powerfmt"
version = "0.2.0"
@@ -2636,6 +3050,28 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "proc-macro-error-attr2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "proc-macro-error2"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
+dependencies = [
+ "proc-macro-error-attr2",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.85",
+]
+
[[package]]
name = "proc-macro-regex"
version = "1.0.0"
@@ -2676,7 +3112,7 @@ checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270"
dependencies = [
"bytes",
"heck",
- "itertools",
+ "itertools 0.10.5",
"lazy_static",
"log",
"multimap",
@@ -2697,7 +3133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
dependencies = [
"anyhow",
- "itertools",
+ "itertools 0.10.5",
"proc-macro2",
"quote",
"syn 1.0.109",
@@ -2759,6 +3195,12 @@ dependencies = [
"proc-macro2",
]
+[[package]]
+name = "radium"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
+
[[package]]
name = "rand"
version = "0.8.5"
@@ -2799,6 +3241,9 @@ name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
[[package]]
name = "rand_os"
@@ -2853,6 +3298,21 @@ dependencies = [
"rand_core 0.3.1",
]
+[[package]]
+name = "reddsa"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78a5191930e84973293aa5f532b513404460cd2216c1cfb76d08748c15b40b02"
+dependencies = [
+ "blake2b_simd",
+ "byteorder",
+ "group",
+ "hex",
+ "jubjub",
+ "pasta_curves",
+ "rand_core 0.6.4",
+]
+
[[package]]
name = "ref-cast"
version = "1.0.23"
@@ -2908,6 +3368,15 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+[[package]]
+name = "ripemd"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f"
+dependencies = [
+ "digest 0.10.7",
+]
+
[[package]]
name = "rippled_binary_codec"
version = "0.0.6"
@@ -2988,6 +3457,7 @@ dependencies = [
"cstr_core",
"cty",
"ethereum_rust_c",
+ "getrandom",
"keystore",
"near_rust_c",
"simulator_rust_c",
@@ -2999,6 +3469,7 @@ dependencies = [
"tron_rust_c",
"wallet_rust_c",
"xrp_rust_c",
+ "zcash_rust_c",
]
[[package]]
@@ -3035,6 +3506,15 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
[[package]]
name = "rustix"
version = "0.38.38"
@@ -3141,23 +3621,38 @@ dependencies = [
[[package]]
name = "secp256k1"
-version = "0.28.2"
+version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10"
+checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113"
dependencies = [
- "bitcoin_hashes 0.13.0",
+ "bitcoin_hashes 0.14.0",
"secp256k1-sys",
]
[[package]]
name = "secp256k1-sys"
-version = "0.9.2"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb"
+checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9"
dependencies = [
"cc",
]
+[[package]]
+name = "secrecy"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
+dependencies = [
+ "zeroize",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
+
[[package]]
name = "serde"
version = "1.0.214"
@@ -3241,7 +3736,23 @@ dependencies = [
"hex",
"serde",
"serde_json",
- "serde_with_macros",
+ "serde_with_macros 2.3.3",
+ "time",
+]
+
+[[package]]
+name = "serde_with"
+version = "3.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817"
+dependencies = [
+ "base64 0.22.1",
+ "chrono",
+ "hex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "serde_with_macros 3.11.0",
"time",
]
@@ -3257,6 +3768,18 @@ dependencies = [
"syn 2.0.85",
]
+[[package]]
+name = "serde_with_macros"
+version = "3.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d"
+dependencies = [
+ "darling 0.20.10",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.85",
+]
+
[[package]]
name = "sha1"
version = "0.10.6"
@@ -3358,6 +3881,17 @@ dependencies = [
"sim_qr_reader",
]
+[[package]]
+name = "sinsemilla"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d268ae0ea06faafe1662e9967cd4f9022014f5eeb798e0c302c876df8b7af9c"
+dependencies = [
+ "group",
+ "pasta_curves",
+ "subtle",
+]
+
[[package]]
name = "siphasher"
version = "0.3.11"
@@ -3379,7 +3913,7 @@ dependencies = [
"common_rust_c",
"cstr_core",
"cty",
- "itertools",
+ "itertools 0.13.0",
"keystore",
"rust_tools",
"ur-registry",
@@ -3404,6 +3938,12 @@ dependencies = [
"der",
]
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
[[package]]
name = "static_assertions"
version = "1.1.0"
@@ -3509,7 +4049,7 @@ dependencies = [
"once_cell",
"serde",
"serde_json",
- "serde_with",
+ "serde_with 2.3.3",
"strum_macros",
"sui-macros",
"thiserror-core",
@@ -3565,6 +4105,12 @@ dependencies = [
"syn 2.0.85",
]
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
[[package]]
name = "tempfile"
version = "3.13.0"
@@ -3815,6 +4361,16 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+[[package]]
+name = "universal-hash"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
+dependencies = [
+ "crypto-common",
+ "subtle",
+]
+
[[package]]
name = "ur"
version = "0.3.0"
@@ -3868,6 +4424,17 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+[[package]]
+name = "visibility"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.85",
+]
+
[[package]]
name = "wallet_rust_c"
version = "0.1.0"
@@ -4315,6 +4882,15 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "wyz"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
+dependencies = [
+ "tap",
+]
+
[[package]]
name = "xcb"
version = "1.4.0"
@@ -4343,6 +4919,161 @@ dependencies = [
"ur-registry",
]
+[[package]]
+name = "zcash_address"
+version = "0.6.2"
+source = "git+https://github.com/zcash/librustzcash.git?rev=9407f09208d5574a3ba7bf3e6963741114ba77c2#9407f09208d5574a3ba7bf3e6963741114ba77c2"
+dependencies = [
+ "bech32 0.11.0",
+ "bs58 0.5.1",
+ "core2",
+ "f4jumble",
+ "zcash_encoding",
+ "zcash_protocol",
+]
+
+[[package]]
+name = "zcash_encoding"
+version = "0.2.2"
+source = "git+https://github.com/zcash/librustzcash.git?rev=9407f09208d5574a3ba7bf3e6963741114ba77c2#9407f09208d5574a3ba7bf3e6963741114ba77c2"
+dependencies = [
+ "core2",
+]
+
+[[package]]
+name = "zcash_keys"
+version = "0.6.0"
+source = "git+https://github.com/zcash/librustzcash.git?rev=9407f09208d5574a3ba7bf3e6963741114ba77c2#9407f09208d5574a3ba7bf3e6963741114ba77c2"
+dependencies = [
+ "bech32 0.11.0",
+ "bip32",
+ "blake2b_simd",
+ "bls12_381",
+ "bs58 0.5.1",
+ "core2",
+ "group",
+ "memuse",
+ "nonempty",
+ "orchard",
+ "rand_core 0.6.4",
+ "secrecy",
+ "subtle",
+ "tracing",
+ "zcash_address",
+ "zcash_encoding",
+ "zcash_protocol",
+ "zcash_transparent",
+ "zip32",
+]
+
+[[package]]
+name = "zcash_note_encryption"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77efec759c3798b6e4d829fcc762070d9b229b0f13338c40bf993b7b609c2272"
+dependencies = [
+ "chacha20",
+ "chacha20poly1305",
+ "cipher",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
+[[package]]
+name = "zcash_protocol"
+version = "0.4.3"
+source = "git+https://github.com/zcash/librustzcash.git?rev=9407f09208d5574a3ba7bf3e6963741114ba77c2#9407f09208d5574a3ba7bf3e6963741114ba77c2"
+dependencies = [
+ "core2",
+ "hex",
+]
+
+[[package]]
+name = "zcash_rust_c"
+version = "0.1.0"
+dependencies = [
+ "app_utils",
+ "app_zcash",
+ "common_rust_c",
+ "cstr_core",
+ "cty",
+ "keystore",
+ "rust_tools",
+ "ur-registry",
+ "zcash_vendor",
+]
+
+[[package]]
+name = "zcash_spec"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cede95491c2191d3e278cab76e097a44b17fde8d6ca0d4e3a22cf4807b2d857"
+dependencies = [
+ "blake2b_simd",
+]
+
+[[package]]
+name = "zcash_transparent"
+version = "0.1.0"
+source = "git+https://github.com/zcash/librustzcash.git?rev=9407f09208d5574a3ba7bf3e6963741114ba77c2#9407f09208d5574a3ba7bf3e6963741114ba77c2"
+dependencies = [
+ "bip32",
+ "blake2b_simd",
+ "bs58 0.5.1",
+ "core2",
+ "getset",
+ "hex",
+ "ripemd",
+ "secp256k1",
+ "sha2 0.10.8",
+ "subtle",
+ "zcash_address",
+ "zcash_encoding",
+ "zcash_protocol",
+ "zcash_spec",
+ "zip32",
+]
+
+[[package]]
+name = "zcash_vendor"
+version = "0.1.0"
+dependencies = [
+ "aes",
+ "bech32 0.11.0",
+ "bip32",
+ "bitvec",
+ "blake2b_simd",
+ "bs58 0.5.1",
+ "byteorder",
+ "chacha20poly1305",
+ "core2",
+ "f4jumble",
+ "ff",
+ "fpe",
+ "getset",
+ "group",
+ "hex",
+ "orchard",
+ "pasta_curves",
+ "pczt",
+ "postcard",
+ "rand_chacha",
+ "reddsa",
+ "ripemd",
+ "secp256k1",
+ "serde",
+ "serde_with 3.11.0",
+ "sha2 0.10.8",
+ "sinsemilla",
+ "subtle",
+ "zcash_address",
+ "zcash_encoding",
+ "zcash_keys",
+ "zcash_protocol",
+ "zcash_transparent",
+ "zip32",
+]
+
[[package]]
name = "zerocopy"
version = "0.7.35"
@@ -4370,6 +5101,18 @@ version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+[[package]]
+name = "zip32"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e9943793abf9060b68e1889012dafbd5523ab5b125c0fcc24802d69182f2ac9"
+dependencies = [
+ "blake2b_simd",
+ "memuse",
+ "subtle",
+ "zcash_spec",
+]
+
[[package]]
name = "zune-inflate"
version = "0.2.54"
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 1a4605d56..2db60a2e5 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -17,6 +17,7 @@ members = [
"apps/utils",
"apps/wallets",
"apps/xrp",
+ "apps/zcash",
# C interface entry
"rust_c",
@@ -38,6 +39,7 @@ members = [
"rust_c/src/tron",
"rust_c/src/wallet",
"rust_c/src/xrp",
+ "rust_c/src/zcash",
"rust_c/src/test_cmd",
"rust_c/src/test_cmd/src/btc_test_cmd",
@@ -47,6 +49,7 @@ members = [
"keystore",
"sim_qr_reader",
"tools",
+ "zcash_vendor",
]
[workspace.dependencies]
@@ -65,27 +68,26 @@ app_tron = { path = "apps/tron" }
app_utils = { path = "apps/utils" }
app_wallets = { path = "apps/wallets" }
app_xrp = { path = "apps/xrp" }
-
+app_zcash = { path = "apps/zcash" }
keystore = { path = "keystore", default-features = false }
tools = { path = "tools" }
sim_qr_reader = { path = "sim_qr_reader" }
rust_tools = { path = "tools" }
+zcash_vendor = { path = "zcash_vendor" }
# third party dependencies
cty = "0.2.0"
cstr_core = "0.2.6"
either = { version = "1.13.0", default-features = false }
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
-itertools = { version = "0.10.5", default-features = false, features = [
+itertools = { version = "0.13.0", default-features = false, features = [
"use_alloc",
] }
-
-bitcoin = { version = "0.31.1", default-features = false, features = [
- "no-std",
+bitcoin = { version = "0.32.4", default-features = false, features = [
"secp-recovery",
] }
-bech32 = { version = "0.10.0-beta", default-features = false }
-bitcoin_hashes = { version = "0.13.0", default-features = false }
+bech32 = { version = "0.11.0", default-features = false, features = ["alloc"] }
+bitcoin_hashes = { version = "0.14.0", default-features = false }
core2 = { version = "0.3.3", default_features = false, features = ["alloc"] }
thiserror = { version = "1.0", package = "thiserror-core", default-features = false }
rsa = { version = "0.8.2", default-features = false }
@@ -111,6 +113,7 @@ serde_derive = { version = "1.0.159" }
serde_bytes = { version = "0.11.5", default-features = false, features = [
"alloc",
] }
+rand_core = { version = "0.6" }
rand_chacha = { version = "0.3.1", default-features = false }
sha2 = { version = "0.10.6", default-features = false, features = ["oid"] }
aes = { version = "0.8.4", default-features = false }
@@ -127,10 +130,18 @@ prost-types = { version = "0.11", default-features = false }
num-bigint = { version = "0.4.5", default-features = false }
num-integer = { version = "0.1.46", default-features = false }
num-traits = { version = "0.2.19", default-features = false }
+blake2b_simd = { version = "1.0.2", default-features = false }
+getrandom = "0.2"
# third party dependencies end
-[patch.crates-io.bitcoin]
-git = "https://github.com/KeystoneHQ/rust-bitcoin.git"
-tag = "v0.31.2"
-default-features = false
-features = ["no-std", "secp-recovery"]
+[patch.crates-io]
+bip32 = { git = "https://github.com/KeystoneHQ/crates.git", rev = "9873e8fd56007d792fa60d6e844fdb75d527c858" }
+f4jumble = { git = "https://github.com/zcash/librustzcash.git", rev = "9407f09208d5574a3ba7bf3e6963741114ba77c2" }
+nonempty = { git = "https://github.com/nuttycom/nonempty.git", rev = "38d37189faecb2a0e3d6adc05aa24e1b93c2483b" }
+orchard = { git = "https://github.com/zcash/orchard.git", rev = "e0cc7ac53ad8c97661b312a8b1c064f4cd3c6629" }
+pczt = { git = "https://github.com/zcash/librustzcash.git", rev = "9407f09208d5574a3ba7bf3e6963741114ba77c2" }
+transparent = { package = "zcash_transparent", git = "https://github.com/zcash/librustzcash.git", rev = "9407f09208d5574a3ba7bf3e6963741114ba77c2" }
+zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "9407f09208d5574a3ba7bf3e6963741114ba77c2" }
+zcash_encoding = { git = "https://github.com/zcash/librustzcash.git", rev = "9407f09208d5574a3ba7bf3e6963741114ba77c2" }
+zcash_keys = { git = "https://github.com/zcash/librustzcash.git", rev = "9407f09208d5574a3ba7bf3e6963741114ba77c2" }
+zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "9407f09208d5574a3ba7bf3e6963741114ba77c2" }
diff --git a/rust/apps/bitcoin/src/addresses/address.rs b/rust/apps/bitcoin/src/addresses/address.rs
index cb24d5d4c..aac67770b 100644
--- a/rust/apps/bitcoin/src/addresses/address.rs
+++ b/rust/apps/bitcoin/src/addresses/address.rs
@@ -13,12 +13,12 @@ use crate::errors::BitcoinError;
use crate::network::Network;
use alloc::string::ToString;
use bech32;
-use bitcoin::address::Payload;
+use bitcoin::address::AddressData as Payload;
use bitcoin::blockdata::script;
use bitcoin::script::PushBytesBuf;
use bitcoin::secp256k1::{Secp256k1, XOnlyPublicKey};
-use bitcoin::PublicKey;
-use bitcoin::{base58, TapNodeHash};
+use bitcoin::{base58, Script, ScriptBuf, TapNodeHash};
+use bitcoin::{CompressedPublicKey, PublicKey};
use bitcoin::{PubkeyHash, ScriptHash};
use bitcoin::{WitnessProgram, WitnessVersion};
use bitcoin_hashes::Hash;
@@ -41,7 +41,9 @@ impl Address {
| Network::BitcoinCash
| Network::Dash => Ok(Address {
network,
- payload: Payload::p2pkh(pk),
+ payload: Payload::P2pkh {
+ pubkey_hash: pk.pubkey_hash(),
+ },
}),
}
}
@@ -49,9 +51,13 @@ impl Address {
pub fn p2wpkh(pk: &PublicKey, network: Network) -> Result
{
match network {
Network::Bitcoin | Network::BitcoinTestnet => {
- let payload = Payload::p2wpkh(pk).map_err(|_e| {
- BitcoinError::AddressError(format!("invalid payload for p2wpkh"))
- })?;
+ let payload = Payload::Segwit {
+ witness_program: WitnessProgram::p2wpkh(
+ &CompressedPublicKey::try_from(pk.clone()).map_err(|e| {
+ BitcoinError::AddressError(format!("invalid payload for p2wpkh: {}", e))
+ })?,
+ ),
+ };
Ok(Address { network, payload })
}
_ => Err(BitcoinError::AddressError(format!(
@@ -65,7 +71,13 @@ impl Address {
match network {
Network::Bitcoin | Network::BitcoinTestnet => {
let secp = Secp256k1::verification_only();
- let payload = Payload::p2tr(&secp, XOnlyPublicKey::from(pk.inner), None);
+ let payload = Payload::Segwit {
+ witness_program: WitnessProgram::p2tr(
+ &secp,
+ XOnlyPublicKey::from(pk.inner),
+ None,
+ ),
+ };
Ok(Address { network, payload })
}
_ => Err(BitcoinError::AddressError(format!(
@@ -83,7 +95,9 @@ impl Address {
match network {
Network::Bitcoin | Network::BitcoinTestnet => {
let secp = Secp256k1::verification_only();
- let payload = Payload::p2tr(&secp, *x_only_pubkey, merkle_root);
+ let payload = Payload::Segwit {
+ witness_program: WitnessProgram::p2tr(&secp, *x_only_pubkey, merkle_root),
+ };
Ok(Address { network, payload })
}
_ => Err(BitcoinError::AddressError(format!(
@@ -96,9 +110,17 @@ impl Address {
pub fn p2shp2wpkh(pk: &PublicKey, network: Network) -> Result {
match network {
Network::Bitcoin | Network::BitcoinTestnet | Network::Litecoin => {
- let payload = Payload::p2shwpkh(pk).map_err(|_e| {
- BitcoinError::AddressError(format!("invalid payload for p2shwpkh"))
- })?;
+ let builder =
+ script::Builder::new()
+ .push_int(0)
+ .push_slice(pk.wpubkey_hash().map_err(|e| {
+ BitcoinError::AddressError(format!(
+ "invalid payload for p2shwpkh: {}",
+ e
+ ))
+ })?);
+ let script_hash = builder.as_script().script_hash();
+ let payload = Payload::P2sh { script_hash };
Ok(Address { network, payload })
}
_ => Err(BitcoinError::AddressError(format!(
@@ -108,11 +130,51 @@ impl Address {
}
pub fn from_script(script: &script::Script, network: Network) -> Result {
- Ok(Address {
- payload: Payload::from_script(script)
- .map_err(|e| BitcoinError::AddressError(format!("invalid payload, {}", e)))?,
- network,
- })
+ if script.is_p2pkh() {
+ let bytes = script.as_bytes()[3..23]
+ .try_into()
+ .expect("statically 20B long");
+ let hash = PubkeyHash::from_byte_array(bytes);
+ Ok(Address {
+ network,
+ payload: Payload::P2pkh { pubkey_hash: hash },
+ })
+ } else if script.is_p2sh() {
+ let bytes = script.as_bytes()[2..22]
+ .try_into()
+ .expect("statically 20B long");
+ let hash = ScriptHash::from_byte_array(bytes);
+ Ok(Address {
+ network,
+ payload: Payload::P2sh { script_hash: hash },
+ })
+ } else if script.is_witness_program() {
+ let opcode = script
+ .first_opcode()
+ .expect("is_witness_program guarantees len > 4");
+
+ let version = WitnessVersion::try_from(opcode).map_err(|e| {
+ BitcoinError::AddressError(format!("invalid witness version: {}", e))
+ })?;
+ let program = WitnessProgram::new(version, &script.as_bytes()[2..])?;
+ Ok(Address {
+ network,
+ payload: Payload::Segwit {
+ witness_program: program,
+ },
+ })
+ } else {
+ Err(BitcoinError::AddressError(format!("unrecognized script")))
+ }
+ }
+
+ pub fn script_pubkey(&self) -> ScriptBuf {
+ match self.payload {
+ Payload::P2pkh { pubkey_hash } => ScriptBuf::new_p2pkh(&pubkey_hash),
+ Payload::P2sh { script_hash } => ScriptBuf::new_p2sh(&script_hash),
+ Payload::Segwit { witness_program } => ScriptBuf::new_witness_program(&witness_program),
+ _ => panic!("unrecognized payload"),
+ }
}
}
@@ -190,11 +252,11 @@ impl FromStr for Address {
let (_hrp, version, data) = bech32::segwit::decode(s)?;
let version = WitnessVersion::try_from(version).expect("we know this is in range 0-16");
let program = PushBytesBuf::try_from(data).expect("decode() guarantees valid length");
- let witness_program = WitnessProgram::new(version, program)?;
+ let witness_program = WitnessProgram::new(version, program.as_bytes())?;
return Ok(Address {
network,
- payload: Payload::WitnessProgram(witness_program),
+ payload: Payload::Segwit { witness_program },
});
// let (_, payload, variant) = bech32::decode(s)
// .map_err(|_e_| Self::Err::AddressError(format!("bech32 decode failed")))?;
@@ -261,42 +323,42 @@ impl FromStr for Address {
PUBKEY_ADDRESS_PREFIX_BTC => {
let pubkey_hash = PubkeyHash::from_slice(&data[1..])
.map_err(|_| Self::Err::AddressError(format!("failed to get pubkey hash")))?;
- (Network::Bitcoin, Payload::PubkeyHash(pubkey_hash))
+ (Network::Bitcoin, Payload::P2pkh { pubkey_hash })
}
PUBKEY_ADDRESS_PREFIX_TEST => {
let pubkey_hash = PubkeyHash::from_slice(&data[1..])
.map_err(|_| Self::Err::AddressError(format!("failed to get pubkey hash")))?;
- (Network::BitcoinTestnet, Payload::PubkeyHash(pubkey_hash))
+ (Network::BitcoinTestnet, Payload::P2pkh { pubkey_hash })
}
PUBKEY_ADDRESS_PREFIX_DASH => {
let pubkey_hash = PubkeyHash::from_slice(&data[1..])
.map_err(|_| Self::Err::AddressError(format!("failed to get pubkey hash")))?;
- (Network::Dash, Payload::PubkeyHash(pubkey_hash))
+ (Network::Dash, Payload::P2pkh { pubkey_hash })
}
PUBKEY_ADDRESS_PREFIX_DASH_P2SH => {
let script_hash = ScriptHash::from_slice(&data[1..])
.map_err(|_| Self::Err::AddressError(format!("failed to get script hash")))?;
- (Network::Dash, Payload::ScriptHash(script_hash))
+ (Network::Dash, Payload::P2sh { script_hash })
}
SCRIPT_ADDRESS_PREFIX_LTC_P2PKH => {
let pubkey_hash = PubkeyHash::from_slice(&data[1..])
.map_err(|_| Self::Err::AddressError(format!("failed to get pubkey hash")))?;
- (Network::Litecoin, Payload::PubkeyHash(pubkey_hash))
+ (Network::Litecoin, Payload::P2pkh { pubkey_hash })
}
SCRIPT_ADDRESS_PREFIX_LTC => {
let script_hash = ScriptHash::from_slice(&data[1..])
.map_err(|_| Self::Err::AddressError(format!("failed to get script hash")))?;
- (Network::Litecoin, Payload::ScriptHash(script_hash))
+ (Network::Litecoin, Payload::P2sh { script_hash })
}
SCRIPT_ADDRESS_PREFIX_BTC => {
let script_hash = ScriptHash::from_slice(&data[1..])
.map_err(|_| Self::Err::AddressError(format!("failed to get script hash")))?;
- (Network::Bitcoin, Payload::ScriptHash(script_hash))
+ (Network::Bitcoin, Payload::P2sh { script_hash })
}
SCRIPT_ADDRESS_PREFIX_TEST => {
let script_hash = ScriptHash::from_slice(&data[1..])
.map_err(|_| Self::Err::AddressError(format!("failed to get script hash")))?;
- (Network::BitcoinTestnet, Payload::ScriptHash(script_hash))
+ (Network::BitcoinTestnet, Payload::P2sh { script_hash })
}
_x => return Err(Self::Err::AddressError(format!("invalid address version"))),
};
diff --git a/rust/apps/bitcoin/src/addresses/cashaddr.rs b/rust/apps/bitcoin/src/addresses/cashaddr.rs
index f55711e30..15cbef7bc 100644
--- a/rust/apps/bitcoin/src/addresses/cashaddr.rs
+++ b/rust/apps/bitcoin/src/addresses/cashaddr.rs
@@ -7,7 +7,7 @@ use crate::errors::Result;
use crate::network::Network;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
-use bitcoin::address::Payload;
+use bitcoin::address::AddressData as Payload;
use bitcoin::PubkeyHash;
use bitcoin_hashes::Hash;
use core::{fmt, str};
@@ -338,7 +338,9 @@ impl CashAddrCodec {
let publickey_hash = PubkeyHash::from_slice(&body.to_vec())
.map_err(|_| BitcoinError::AddressError(format!("invalid public key hash")))?;
Ok(Address {
- payload: Payload::PubkeyHash(publickey_hash),
+ payload: Payload::P2pkh {
+ pubkey_hash: publickey_hash,
+ },
network: Network::BitcoinCash,
})
}
@@ -347,15 +349,17 @@ impl CashAddrCodec {
#[cfg(test)]
mod tests {
use super::*;
+ use bitcoin::ScriptBuf;
use hex::ToHex;
#[test]
fn test_decode_cash_addr() {
let addr_str = "qz65ywjm92m27wshfnew2w3us5vsgxqkxc55t9lqcw";
let address = CashAddrCodec::decode(addr_str).unwrap();
+ let script = address.script_pubkey();
assert_eq!(
- address.payload.script_pubkey().encode_hex::(),
- "76a914b5423a5b2ab6af3a174cf2e53a3c85190418163688ac"
+ script.encode_hex::(),
+ "76a914b5423a5b2ab6af3a174cf2e53a3c85190418163688ac"
);
}
}
diff --git a/rust/apps/bitcoin/src/addresses/encoding.rs b/rust/apps/bitcoin/src/addresses/encoding.rs
index c993d5ed9..5feb56549 100644
--- a/rust/apps/bitcoin/src/addresses/encoding.rs
+++ b/rust/apps/bitcoin/src/addresses/encoding.rs
@@ -1,7 +1,6 @@
use bech32::Hrp;
-use bitcoin::address::Payload;
+use bitcoin::address::AddressData as Payload;
use bitcoin::base58;
-use bitcoin::bech32;
use core::fmt;
use crate::addresses::cashaddr::{Base58Codec, CashAddrCodec};
@@ -45,27 +44,27 @@ impl fmt::Write for UpperWriter {
impl<'a> fmt::Display for BTCAddressEncoding<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.payload {
- Payload::PubkeyHash(hash) => {
+ Payload::P2pkh { pubkey_hash } => {
let mut prefixed = [0; 21];
prefixed[0] = self.p2pkh_prefix;
- prefixed[1..].copy_from_slice(&hash[..]);
+ prefixed[1..].copy_from_slice(&pubkey_hash[..]);
base58::encode_check_to_fmt(fmt, &prefixed[..])
}
- Payload::ScriptHash(hash) => {
+ Payload::P2sh { script_hash } => {
let mut prefixed = [0; 21];
prefixed[0] = self.p2sh_prefix;
- prefixed[1..].copy_from_slice(&hash[..]);
+ prefixed[1..].copy_from_slice(&script_hash[..]);
base58::encode_check_to_fmt(fmt, &prefixed[..])
}
- Payload::WitnessProgram(witness) => {
+ Payload::Segwit { witness_program } => {
let hrp = Hrp::parse_unchecked(self.bech32_hrp);
- let version = witness.version().to_fe();
- let program = witness.program().as_bytes();
+ let version = witness_program.version().to_fe();
+ let program = witness_program.program().as_bytes();
if fmt.alternate() {
- bech32::segwit::encode_upper_to_fmt_unchecked(fmt, &hrp, version, program)
+ bech32::segwit::encode_upper_to_fmt_unchecked(fmt, hrp, version, program)
} else {
- bech32::segwit::encode_lower_to_fmt_unchecked(fmt, &hrp, version, program)
+ bech32::segwit::encode_lower_to_fmt_unchecked(fmt, hrp, version, program)
}
}
_ => {
@@ -78,10 +77,10 @@ impl<'a> fmt::Display for BTCAddressEncoding<'a> {
impl<'a> fmt::Display for BCHAddressEncoding<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.payload {
- Payload::PubkeyHash(hash) => {
+ Payload::P2pkh { pubkey_hash } => {
let mut prefixed = [0; 21];
prefixed[0] = self.p2pkh_prefix;
- prefixed[1..].copy_from_slice(&hash[..]);
+ prefixed[1..].copy_from_slice(&pubkey_hash[..]);
let base58_addr = base58::encode_check(&prefixed[..]);
let decoded = Base58Codec::decode(base58_addr.as_str());
match decoded {
@@ -99,27 +98,27 @@ impl<'a> fmt::Display for BCHAddressEncoding<'a> {
impl<'a> fmt::Display for LTCAddressEncoding<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.payload {
- Payload::PubkeyHash(hash) => {
+ Payload::P2pkh { pubkey_hash } => {
let mut prefixed = [0; 21];
prefixed[0] = self.p2pkh_prefix;
- prefixed[1..].copy_from_slice(&hash[..]);
+ prefixed[1..].copy_from_slice(&pubkey_hash[..]);
base58::encode_check_to_fmt(fmt, &prefixed[..])
}
- Payload::ScriptHash(hash) => {
+ Payload::P2sh { script_hash } => {
let mut prefixed = [0; 21];
prefixed[0] = self.p2sh_prefix;
- prefixed[1..].copy_from_slice(&hash[..]);
+ prefixed[1..].copy_from_slice(&script_hash[..]);
base58::encode_check_to_fmt(fmt, &prefixed[..])
}
- Payload::WitnessProgram(witness) => {
+ Payload::Segwit { witness_program } => {
let hrp = Hrp::parse_unchecked(self.bech32_hrp);
- let version = witness.version().to_fe();
- let program = witness.program().as_bytes();
+ let version = witness_program.version().to_fe();
+ let program = witness_program.program().as_bytes();
if fmt.alternate() {
- bech32::segwit::encode_upper_to_fmt_unchecked(fmt, &hrp, version, program)
+ bech32::segwit::encode_upper_to_fmt_unchecked(fmt, hrp, version, program)
} else {
- bech32::segwit::encode_lower_to_fmt_unchecked(fmt, &hrp, version, program)
+ bech32::segwit::encode_lower_to_fmt_unchecked(fmt, hrp, version, program)
}
}
_ => {
@@ -132,16 +131,16 @@ impl<'a> fmt::Display for LTCAddressEncoding<'a> {
impl<'a> fmt::Display for DASHAddressEncoding<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.payload {
- Payload::PubkeyHash(hash) => {
+ Payload::P2pkh { pubkey_hash } => {
let mut prefixed = [0; 21];
prefixed[0] = self.p2pkh_prefix;
- prefixed[1..].copy_from_slice(&hash[..]);
+ prefixed[1..].copy_from_slice(&pubkey_hash[..]);
base58::encode_check_to_fmt(fmt, &prefixed[..])
}
- Payload::ScriptHash(hash) => {
+ Payload::P2sh { script_hash } => {
let mut prefixed = [0; 21];
prefixed[0] = self.p2sh_prefix;
- prefixed[1..].copy_from_slice(&hash[..]);
+ prefixed[1..].copy_from_slice(&script_hash[..]);
base58::encode_check_to_fmt(fmt, &prefixed[..])
}
_ => {
diff --git a/rust/apps/bitcoin/src/errors.rs b/rust/apps/bitcoin/src/errors.rs
index bbe2c7bee..a4d85b027 100644
--- a/rust/apps/bitcoin/src/errors.rs
+++ b/rust/apps/bitcoin/src/errors.rs
@@ -89,6 +89,12 @@ impl From for BitcoinError {
}
}
+impl From for BitcoinError {
+ fn from(value: bitcoin::io::Error) -> Self {
+ Self::TransactionConsensusEncodeError(format!("{}", value))
+ }
+}
+
impl From for BitcoinError {
fn from(value: PushBytesError) -> Self {
Self::PushBytesFailed(format!("{}", value))
@@ -116,15 +122,11 @@ impl From for BitcoinError {
impl From for BitcoinError {
fn from(value: Base58Error) -> Self {
match value {
- Base58Error::BadByte(byte) => Self::Base58Error(format!("bad bytes: {}", byte)),
- Base58Error::TooShort(size) => Self::Base58Error(format!("too short: {}", size)),
- Base58Error::InvalidLength(size) => {
- Self::Base58Error(format!("invalid length: {}", size))
+ Base58Error::IncorrectChecksum(e) => {
+ Self::Base58Error(format!("incorrect checksum: {}", e))
}
- Base58Error::BadChecksum(expected, actual) => Self::Base58Error(format!(
- "bad checksum, expected {}, actual {}",
- expected, actual
- )),
+ Base58Error::TooShort(e) => Self::Base58Error(format!("too short: {}", e)),
+ Base58Error::Decode(e) => Self::Base58Error(format!("invalid character: {}", e)),
_ => Self::Base58Error(format!(": {}", value)),
}
}
diff --git a/rust/apps/bitcoin/src/lib.rs b/rust/apps/bitcoin/src/lib.rs
index 8d8d62ddb..2e1173ed3 100644
--- a/rust/apps/bitcoin/src/lib.rs
+++ b/rust/apps/bitcoin/src/lib.rs
@@ -15,11 +15,11 @@ use alloc::vec::Vec;
pub use addresses::get_address;
use app_utils::keystone;
use bitcoin::bip32::Fingerprint;
+use bitcoin::hashes::Hash;
use bitcoin::psbt::Psbt;
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
use bitcoin::secp256k1::Message;
use bitcoin::sign_message;
-use bitcoin_hashes::Hash;
use either::{Left, Right};
use hex;
pub use transactions::legacy::sign_legacy_tx;
diff --git a/rust/apps/bitcoin/src/transactions/legacy/input.rs b/rust/apps/bitcoin/src/transactions/legacy/input.rs
index 3b7b2b03a..b403f5282 100644
--- a/rust/apps/bitcoin/src/transactions/legacy/input.rs
+++ b/rust/apps/bitcoin/src/transactions/legacy/input.rs
@@ -4,11 +4,11 @@ use crate::transactions::script_type::ScriptType;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use bitcoin;
+use bitcoin::hashes::Hash;
use bitcoin::script::{Builder, PushBytesBuf};
use bitcoin::secp256k1::ecdsa::Signature;
use bitcoin::WPubkeyHash;
use bitcoin::{PublicKey, ScriptBuf, Sequence};
-use bitcoin_hashes::Hash;
use core::iter;
use core::str::FromStr;
use ur_registry::pb::protoc;
@@ -78,7 +78,8 @@ impl TryInto for TxIn {
type Error = BitcoinError;
fn try_into(self) -> Result {
- let tx_id = bitcoin::Txid::from_str(self.previous_output.as_str())?;
+ let tx_id = bitcoin::Txid::from_str(self.previous_output.as_str())
+ .map_err(|_| BitcoinError::InvalidTransaction(format!("invalid txid")))?;
Ok(bitcoin::TxIn {
previous_output: bitcoin::OutPoint {
txid: tx_id,
diff --git a/rust/apps/bitcoin/src/transactions/legacy/output.rs b/rust/apps/bitcoin/src/transactions/legacy/output.rs
index 7c3023b7f..e8c5b0696 100644
--- a/rust/apps/bitcoin/src/transactions/legacy/output.rs
+++ b/rust/apps/bitcoin/src/transactions/legacy/output.rs
@@ -3,7 +3,8 @@ use crate::collect;
use crate::errors::{BitcoinError, Result};
use alloc::string::{String, ToString};
use alloc::vec::Vec;
-use bitcoin::{self, Amount};
+use bitcoin::address::AddressData as Payload;
+use bitcoin::{self, Amount, ScriptBuf};
use core::str::FromStr;
use ur_registry::pb::protoc;
use ur_registry::pb::protoc::sign_transaction::Transaction::{BchTx, BtcTx, DashTx, LtcTx};
@@ -21,7 +22,7 @@ impl TryInto for TxOut {
fn try_into(self) -> Result {
let address = Address::from_str(self.address.as_str())?;
- let script_pubkey = address.payload.script_pubkey();
+ let script_pubkey = address.script_pubkey();
Ok(bitcoin::TxOut {
value: Amount::from_sat(self.value),
script_pubkey,
diff --git a/rust/apps/bitcoin/src/transactions/legacy/tx_data.rs b/rust/apps/bitcoin/src/transactions/legacy/tx_data.rs
index ba326936a..60bd40bac 100644
--- a/rust/apps/bitcoin/src/transactions/legacy/tx_data.rs
+++ b/rust/apps/bitcoin/src/transactions/legacy/tx_data.rs
@@ -3,6 +3,7 @@ use crate::errors::BitcoinError;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use bitcoin::absolute::LockTime;
+use bitcoin::hashes::Hash;
use keystore::algorithms::secp256k1::derive_public_key;
use {bitcoin, hex};
@@ -11,7 +12,7 @@ use bitcoin::consensus::Encodable;
use bitcoin::sighash::{EcdsaSighashType, LegacySighash, SegwitV0Sighash, SighashCache};
use bitcoin::{Amount, Script};
use bitcoin::{PubkeyHash, ScriptBuf, Transaction};
-use bitcoin_hashes::{sha256, sha256d, Hash};
+use bitcoin_hashes::{sha256, sha256d};
use core::str::FromStr;
use crate::addresses::cashaddr::{Base58Codec, CashAddrCodec};
@@ -166,8 +167,8 @@ impl TxData {
}
fn common_cache(&mut self) -> Result {
- let mut enc_prevouts = sha256::Hash::engine();
- let mut enc_sequences = sha256::Hash::engine();
+ let mut enc_prevouts = sha256::HashEngine::default();
+ let mut enc_sequences = sha256::HashEngine::default();
for txin in self.transaction.input.iter() {
txin.previous_output.consensus_encode(&mut enc_prevouts)?;
txin.sequence.consensus_encode(&mut enc_sequences)?;
@@ -176,9 +177,9 @@ impl TxData {
prevouts: sha256::Hash::from_engine(enc_prevouts),
sequences: sha256::Hash::from_engine(enc_sequences),
outputs: {
- let mut enc = sha256::Hash::engine();
+ let mut enc = sha256::HashEngine::default();
for txout in self.transaction.output.iter() {
- txout.consensus_encode(&mut &mut enc)?;
+ txout.consensus_encode(&mut enc)?;
}
sha256::Hash::from_engine(enc)
},
@@ -305,15 +306,15 @@ impl TxData {
input.script_sig = raw_input.script_sig(signature, signature_type, &script_type)?;
} else if script_type == ScriptType::P2WPKH {
let sig = EcdsaSignature {
- sig: signature,
- hash_ty: EcdsaSighashType::All,
+ signature,
+ sighash_type: EcdsaSighashType::All,
};
input.witness.push_ecdsa_signature(&sig);
input.witness.push(pubkey_slice);
} else if script_type == ScriptType::P2SHP2WPKH {
let sig = EcdsaSignature {
- sig: signature.clone(),
- hash_ty: EcdsaSighashType::All,
+ signature,
+ sighash_type: EcdsaSighashType::All,
};
input.witness.push_ecdsa_signature(&sig);
input.witness.push(pubkey_slice);
diff --git a/rust/apps/bitcoin/src/transactions/psbt/parsed_psbt.rs b/rust/apps/bitcoin/src/transactions/psbt/parsed_psbt.rs
index a928465b8..2c89133c2 100644
--- a/rust/apps/bitcoin/src/transactions/psbt/parsed_psbt.rs
+++ b/rust/apps/bitcoin/src/transactions/psbt/parsed_psbt.rs
@@ -4,6 +4,7 @@ use crate::transactions::parsed_tx::{ParseContext, ParsedInput, ParsedOutput, Pa
use crate::transactions::psbt::wrapped_psbt::WrappedPsbt;
use alloc::vec::Vec;
use bitcoin::bip32::ChildNumber;
+use bitcoin::NetworkKind;
use core::ops::Index;
impl TxParser for WrappedPsbt {
@@ -33,7 +34,7 @@ impl TxParser for WrappedPsbt {
fn determine_network(&self) -> Result {
if let Some((xpub, _)) = self.psbt.xpub.first_key_value() {
- return if xpub.network == bitcoin::network::Network::Bitcoin {
+ return if xpub.network == NetworkKind::Main {
Ok(Network::Bitcoin)
} else {
Ok(Network::BitcoinTestnet)
@@ -84,12 +85,12 @@ mod tests {
use bitcoin::bip32::{DerivationPath, Fingerprint, Xpub};
use core::str::FromStr;
+ use hex::FromHex;
use std::collections::BTreeMap;
use super::*;
use crate::parsed_tx::TxParser;
use bitcoin::psbt::Psbt;
- use bitcoin_hashes::hex::FromHex;
#[test]
fn test_parse_psbt() {
diff --git a/rust/apps/bitcoin/src/transactions/psbt/wrapped_psbt.rs b/rust/apps/bitcoin/src/transactions/psbt/wrapped_psbt.rs
index a279ec587..dcf4fca3e 100644
--- a/rust/apps/bitcoin/src/transactions/psbt/wrapped_psbt.rs
+++ b/rust/apps/bitcoin/src/transactions/psbt/wrapped_psbt.rs
@@ -20,9 +20,9 @@ use crate::multi_sig::MultiSigFormat;
use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, KeySource, Xpub};
use bitcoin::psbt::{GetKey, KeyRequest, Psbt};
use bitcoin::psbt::{Input, Output};
-use bitcoin::secp256k1;
use bitcoin::secp256k1::{Secp256k1, Signing, XOnlyPublicKey};
use bitcoin::taproot::TapLeafHash;
+use bitcoin::{secp256k1, NetworkKind};
use bitcoin::{Network, PrivateKey};
use bitcoin::{PublicKey, ScriptBuf, TxOut};
@@ -508,10 +508,9 @@ impl WrappedPsbt {
let (threshold, total) = self.get_multi_sig_input_threshold_and_total(script)?;
let network = if let Some((xpub, _)) = self.psbt.xpub.first_key_value() {
- if xpub.network == bitcoin::network::Network::Bitcoin {
- network::Network::Bitcoin
- } else {
- network::Network::BitcoinTestnet
+ match xpub.network {
+ NetworkKind::Main => network::Network::Bitcoin,
+ _ => network::Network::BitcoinTestnet,
}
} else {
return Err(BitcoinError::MultiSigNetworkError(
@@ -865,9 +864,8 @@ mod tests {
use core::str::FromStr;
use crate::TxChecker;
- use bitcoin_hashes::hex::FromHex;
use either::Left;
- use hex::{self, ToHex};
+ use hex::{self, FromHex, ToHex};
use super::*;
diff --git a/rust/apps/cosmos/src/errors.rs b/rust/apps/cosmos/src/errors.rs
index cbb089cad..56122a9e3 100644
--- a/rust/apps/cosmos/src/errors.rs
+++ b/rust/apps/cosmos/src/errors.rs
@@ -27,6 +27,12 @@ impl From for CosmosError {
}
}
+impl From for CosmosError {
+ fn from(value: bech32::EncodeError) -> Self {
+ Self::InvalidAddressError(format!("bech32 encode error {:?}", value.to_string()))
+ }
+}
+
impl From for CosmosError {
fn from(value: KeystoreError) -> Self {
Self::KeystoreError(value.to_string())
diff --git a/rust/apps/near/src/primitives_core/serialize.rs b/rust/apps/near/src/primitives_core/serialize.rs
index 969f8fa4b..8e0bab355 100644
--- a/rust/apps/near/src/primitives_core/serialize.rs
+++ b/rust/apps/near/src/primitives_core/serialize.rs
@@ -13,7 +13,7 @@ pub fn to_base(input: &Vec) -> String {
}
pub fn from_base(s: &str) -> Result, bs58::Error> {
- bs58::decode(s)
+ bs58::decode(s).map_err(|e| bs58::Error::Decode(e))
}
pub fn to_base64>(input: T) -> String {
diff --git a/rust/apps/solana/Cargo.toml b/rust/apps/solana/Cargo.toml
index b18b0ce06..565ce13ae 100644
--- a/rust/apps/solana/Cargo.toml
+++ b/rust/apps/solana/Cargo.toml
@@ -11,22 +11,27 @@ thiserror = { workspace = true }
serde_json = { workspace = true }
serde = { workspace = true }
hex = { workspace = true }
-bincode = { version = "2.0.0-rc.3", default-features = false, features=['alloc','serde'] }
+bincode = { version = "2.0.0-rc.3", default-features = false, features = [
+ 'alloc',
+ 'serde',
+] }
num-derive = "0.3.3"
serde_derive = { workspace = true }
uint = { version = "0.9.3", default-features = false }
arrayref = "0.3.6"
app_utils = { workspace = true }
rust_tools = { workspace = true }
-sha2 = {version = "0.9.9",default-features = false}
+sha2 = { workspace = true }
bs58 = { version = "0.5.1", default-features = false, features = ["alloc"] }
-borsh = {version = "1.5.1", default-features = false,features = ["derive","borsh-derive","unstable__schema"]}
+borsh = { version = "1.5.1", default-features = false, features = [
+ "derive",
+ "borsh-derive",
+ "unstable__schema",
+] }
bitcoin = { workspace = true }
ur-registry = { workspace = true }
-
-
[dev-dependencies]
keystore = { path = "../../keystore" }
@@ -35,4 +40,4 @@ default = ["std"]
std = []
[lib]
-doctest = false
\ No newline at end of file
+doctest = false
diff --git a/rust/apps/ton/resources/wallet/highload_v1r1.code b/rust/apps/ton/resources/wallet/highload_v1r1.code
deleted file mode 100644
index 70ae403fa..000000000
--- a/rust/apps/ton/resources/wallet/highload_v1r1.code
+++ /dev/null
@@ -1 +0,0 @@
-te6ccgEBBgEAhgABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQC88oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhghgBD0eG+hb6EgmALTB9QwAfsAkTLiAbPmWwGkyMsfyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw==
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/highload_v1r2.code b/rust/apps/ton/resources/wallet/highload_v1r2.code
deleted file mode 100644
index a98d08382..000000000
--- a/rust/apps/ton/resources/wallet/highload_v1r2.code
+++ /dev/null
@@ -1 +0,0 @@
-te6ccgEBCAEAmQABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQC88oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhghgBD0eG+hb6EgmALTB9QwAfsAkTLiAbPmWwGkyMsfyx/L/8ntVAAE0DACAUgGBwAXuznO1E0NM/MdcL/4ABG4yX7UTQ1wsfg=
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/highload_v2.code b/rust/apps/ton/resources/wallet/highload_v2.code
deleted file mode 100644
index 865330dbf..000000000
--- a/rust/apps/ton/resources/wallet/highload_v2.code
+++ /dev/null
@@ -1 +0,0 @@
-te6ccgEBCQEA5QABFP8A9KQT9LzyyAsBAgEgAgcCAUgDBAAE0DACASAFBgAXvZznaiaGmvmOuF/8AEG+X5dqJoaY+Y6Z/p/5j6AmipEEAgegc30JjJLb/JXdHxQB6vKDCNcYINMf0z/4I6ofUyC58mPtRNDTH9M/0//0BNFTYIBA9A5voTHyYFFzuvKiB/kBVBCH+RDyowL0BNH4AH+OFiGAEPR4b6UgmALTB9QwAfsAkTLiAbPmW4MlochANIBA9EOK5jEByMsfE8s/y//0AMntVAgANCCAQPSWb6VsEiCUMFMDud4gkzM2AZJsIeKz
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/highload_v2r1.code b/rust/apps/ton/resources/wallet/highload_v2r1.code
deleted file mode 100644
index 8e0157954..000000000
--- a/rust/apps/ton/resources/wallet/highload_v2r1.code
+++ /dev/null
@@ -1 +0,0 @@
-te6ccgEBBwEA1gABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQHu8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44YIYAQ9HhvoW+hIJgC0wfUMAH7AJEy4gGz5luDJaHIQDSAQPRDiuYxyBLLHxPLP8v/9ADJ7VQGAATQMABBoZfl2omhpj5jpn+n/mPoCaKkQQCB6BzfQmMktv8ld0fFADgggED0lm+hb6EyURCUMFMDud4gkzM2AZIyMOKz
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/highload_v2r2.code b/rust/apps/ton/resources/wallet/highload_v2r2.code
deleted file mode 100644
index bde5df023..000000000
--- a/rust/apps/ton/resources/wallet/highload_v2r2.code
+++ /dev/null
@@ -1 +0,0 @@
-te6ccgEBCQEA6QABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQHu8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44YIYAQ9HhvoW+hIJgC0wfUMAH7AJEy4gGz5luDJaHIQDSAQPRDiuYxyBLLHxPLP8v/9ADJ7VQIAATQMAIBIAYHABe9nOdqJoaa+Y64X/wAQb5fl2omhpj5jpn+n/mPoCaKkQQCB6BzfQmMktv8ld0fFAA4IIBA9JZvoW+hMlEQlDBTA7neIJMzNgGSMjDisw==
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/wallet_v1r1.code b/rust/apps/ton/resources/wallet/wallet_v1r1.code
deleted file mode 100644
index 6dc38b0ca..000000000
--- a/rust/apps/ton/resources/wallet/wallet_v1r1.code
+++ /dev/null
@@ -1 +0,0 @@
-te6cckEBAQEARAAAhP8AIN2k8mCBAgDXGCDXCx/tRNDTH9P/0VESuvKhIvkBVBBE+RDyovgAAdMfMSDXSpbTB9QC+wDe0aTIyx/L/8ntVEH98Ik=
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/wallet_v1r2.code b/rust/apps/ton/resources/wallet/wallet_v1r2.code
deleted file mode 100644
index 02b989623..000000000
--- a/rust/apps/ton/resources/wallet/wallet_v1r2.code
+++ /dev/null
@@ -1 +0,0 @@
-te6cckEBAQEAUwAAov8AIN0gggFMl7qXMO1E0NcLH+Ck8mCBAgDXGCDXCx/tRNDTH9P/0VESuvKhIvkBVBBE+RDyovgAAdMfMSDXSpbTB9QC+wDe0aTIyx/L/8ntVNDieG8=
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/wallet_v1r3.code b/rust/apps/ton/resources/wallet/wallet_v1r3.code
deleted file mode 100644
index 1c67c7119..000000000
--- a/rust/apps/ton/resources/wallet/wallet_v1r3.code
+++ /dev/null
@@ -1 +0,0 @@
-te6cckEBAQEAXwAAuv8AIN0gggFMl7ohggEznLqxnHGw7UTQ0x/XC//jBOCk8mCBAgDXGCDXCx/tRNDTH9P/0VESuvKhIvkBVBBE+RDyovgAAdMfMSDXSpbTB9QC+wDe0aTIyx/L/8ntVLW4bkI=
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/wallet_v2r1.code b/rust/apps/ton/resources/wallet/wallet_v2r1.code
deleted file mode 100644
index 6cbf12061..000000000
--- a/rust/apps/ton/resources/wallet/wallet_v2r1.code
+++ /dev/null
@@ -1 +0,0 @@
-te6cckEBAQEAVwAAqv8AIN0gggFMl7qXMO1E0NcLH+Ck8mCDCNcYINMf0x8B+CO78mPtRNDTH9P/0VExuvKhA/kBVBBC+RDyovgAApMg10qW0wfUAvsA6NGkyMsfy//J7VShNwu2
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/wallet_v2r2.code b/rust/apps/ton/resources/wallet/wallet_v2r2.code
deleted file mode 100644
index 81d52d11a..000000000
--- a/rust/apps/ton/resources/wallet/wallet_v2r2.code
+++ /dev/null
@@ -1 +0,0 @@
-te6cckEBAQEAYwAAwv8AIN0gggFMl7ohggEznLqxnHGw7UTQ0x/XC//jBOCk8mCDCNcYINMf0x8B+CO78mPtRNDTH9P/0VExuvKhA/kBVBBC+RDyovgAApMg10qW0wfUAvsA6NGkyMsfy//J7VQETNeh
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/wallet_v3r1.code b/rust/apps/ton/resources/wallet/wallet_v3r1.code
deleted file mode 100644
index b4073e474..000000000
--- a/rust/apps/ton/resources/wallet/wallet_v3r1.code
+++ /dev/null
@@ -1 +0,0 @@
-te6cckEBAQEAYgAAwP8AIN0gggFMl7qXMO1E0NcLH+Ck8mCDCNcYINMf0x/TH/gjE7vyY+1E0NMf0x/T/9FRMrryoVFEuvKiBPkBVBBV+RDyo/gAkyDXSpbTB9QC+wDo0QGkyMsfyx/L/8ntVD++buA=
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/wallet_v3r2.code b/rust/apps/ton/resources/wallet/wallet_v3r2.code
deleted file mode 100644
index 18dbaf76a..000000000
--- a/rust/apps/ton/resources/wallet/wallet_v3r2.code
+++ /dev/null
@@ -1 +0,0 @@
-te6cckEBAQEAcQAA3v8AIN0gggFMl7ohggEznLqxn3Gw7UTQ0x/THzHXC//jBOCk8mCDCNcYINMf0x/TH/gjE7vyY+1E0NMf0x/T/9FRMrryoVFEuvKiBPkBVBBV+RDyo/gAkyDXSpbTB9QC+wDo0QGkyMsfyx/L/8ntVBC9ba0=
\ No newline at end of file
diff --git a/rust/apps/ton/resources/wallet/wallet_v4r1.code b/rust/apps/ton/resources/wallet/wallet_v4r1.code
deleted file mode 100644
index c27d4e891..000000000
--- a/rust/apps/ton/resources/wallet/wallet_v4r1.code
+++ /dev/null
@@ -1 +0,0 @@
-te6cckECFQEAAvUAART/APSkE/S88sgLAQIBIAIDAgFIBAUE+PKDCNcYINMf0x/THwL4I7vyY+1E0NMf0x/T//QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/8REhMUA+7QAdDTAwFxsJFb4CHXScEgkVvgAdMfIYIQcGx1Z70ighBibG5jvbAighBkc3RyvbCSXwPgAvpAMCD6RAHIygfL/8nQ7UTQgQFA1yH0BDBcgQEI9ApvoTGzkl8F4ATTP8glghBwbHVnupEx4w0kghBibG5juuMABAYHCAIBIAkKAFAB+gD0BDCCEHBsdWeDHrFwgBhQBcsFJ88WUAP6AvQAEstpyx9SEMs/AFL4J28ighBibG5jgx6xcIAYUAXLBSfPFiT6AhTLahPLH1Iwyz8B+gL0AACSghBkc3Ryuo41BIEBCPRZMO1E0IEBQNcgyAHPFvQAye1UghBkc3Rygx6xcIAYUATLBVjPFiL6AhLLassfyz+UEDRfBOLJgED7AAIBIAsMAFm9JCtvaiaECAoGuQ+gIYRw1AgIR6STfSmRDOaQPp/5g3gSgBt4EBSJhxWfMYQCAVgNDgARuMl+1E0NcLH4AD2ynftRNCBAUDXIfQEMALIygfL/8nQAYEBCPQKb6ExgAgEgDxAAGa3OdqJoQCBrkOuF/8AAGa8d9qJoQBBrkOuFj8AAbtIH+gDU1CL5AAXIygcVy//J0Hd0gBjIywXLAiLPFlAF+gIUy2sSzMzJcfsAyEAUgQEI9FHypwIAbIEBCNcYyFQgJYEBCPRR8qeCEG5vdGVwdIAYyMsFywJQBM8WghAF9eEA+gITy2oSyx/JcfsAAgBygQEI1xgwUgKBAQj0WfKn+CWCEGRzdHJwdIAYyMsFywJQBc8WghAF9eEA+gIUy2oTyx8Syz/Jc/sAAAr0AMntVEap808=
\ No newline at end of file
diff --git a/rust/apps/ton/src/vendor/wallet/mod.rs b/rust/apps/ton/src/vendor/wallet/mod.rs
index 87674a73b..c343dbb8f 100644
--- a/rust/apps/ton/src/vendor/wallet/mod.rs
+++ b/rust/apps/ton/src/vendor/wallet/mod.rs
@@ -13,99 +13,22 @@ use crate::vendor::cell::{ArcCell, BagOfCells, Cell, StateInit, TonCellError};
pub const DEFAULT_WALLET_ID: i32 = 0x29a9a317;
lazy_static! {
- pub static ref WALLET_V1R1_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/wallet_v1r1.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref WALLET_V1R2_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/wallet_v1r2.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref WALLET_V1R3_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/wallet_v1r3.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref WALLET_V2R1_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/wallet_v2r1.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref WALLET_V2R2_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/wallet_v2r2.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref WALLET_V3R1_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/wallet_v3r1.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref WALLET_V3R2_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/wallet_v3r2.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref WALLET_V4R1_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/wallet_v4r1.code");
- BagOfCells::parse_base64(code).unwrap()
- };
pub static ref WALLET_V4R2_CODE: BagOfCells = {
let code = include_str!("../../../resources/wallet/wallet_v4r2.code");
BagOfCells::parse_base64(code).unwrap()
};
- pub static ref HIGHLOAD_V1R1_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/highload_v1r1.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref HIGHLOAD_V1R2_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/highload_v1r2.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref HIGHLOAD_V2_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/highload_v2.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref HIGHLOAD_V2R1_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/highload_v2r1.code");
- BagOfCells::parse_base64(code).unwrap()
- };
- pub static ref HIGHLOAD_V2R2_CODE: BagOfCells = {
- let code = include_str!("../../../resources/wallet/highload_v2r2.code");
- BagOfCells::parse_base64(code).unwrap()
- };
}
#[derive(PartialEq, Eq, Clone, Hash)]
pub enum WalletVersion {
- V1R1,
- V1R2,
- V1R3,
- V2R1,
- V2R2,
- V3R1,
- V3R2,
- V4R1,
V4R2,
- HighloadV1R1,
- HighloadV1R2,
- HighloadV2,
- HighloadV2R1,
- HighloadV2R2,
}
impl WalletVersion {
pub fn code(&self) -> Result<&ArcCell, TonCellError> {
let code: &BagOfCells = match self {
- WalletVersion::V1R1 => &WALLET_V1R1_CODE,
- WalletVersion::V1R2 => &WALLET_V1R2_CODE,
- WalletVersion::V1R3 => &WALLET_V1R3_CODE,
- WalletVersion::V2R1 => &WALLET_V2R1_CODE,
- WalletVersion::V2R2 => &WALLET_V2R2_CODE,
- WalletVersion::V3R1 => &WALLET_V3R1_CODE,
- WalletVersion::V3R2 => &WALLET_V3R2_CODE,
- WalletVersion::V4R1 => &WALLET_V4R1_CODE,
+ // reduce firmware size, ignore all other unsupported versions
WalletVersion::V4R2 => &WALLET_V4R2_CODE,
- WalletVersion::HighloadV1R1 => &HIGHLOAD_V1R1_CODE,
- WalletVersion::HighloadV1R2 => &HIGHLOAD_V1R2_CODE,
- WalletVersion::HighloadV2 => &HIGHLOAD_V2_CODE,
- WalletVersion::HighloadV2R1 => &HIGHLOAD_V2R1_CODE,
- WalletVersion::HighloadV2R2 => &HIGHLOAD_V2R2_CODE,
};
code.single_root()
}
@@ -121,41 +44,12 @@ impl WalletVersion {
.map_err(|_| TonCellError::InternalError("Invalid public key size".to_string()))?;
let data_cell: Cell = match &self {
- WalletVersion::V1R1
- | WalletVersion::V1R2
- | WalletVersion::V1R3
- | WalletVersion::V2R1
- | WalletVersion::V2R2 => WalletDataV1V2 {
- seqno: 0,
- public_key,
- }
- .try_into()?,
- WalletVersion::V3R1 | WalletVersion::V3R2 => WalletDataV3 {
- seqno: 0,
- wallet_id,
- public_key,
- }
- .try_into()?,
- WalletVersion::V4R1 | WalletVersion::V4R2 => WalletDataV4 {
+ WalletVersion::V4R2 => WalletDataV4 {
seqno: 0,
wallet_id,
public_key,
}
.try_into()?,
- WalletVersion::HighloadV2R2 => WalletDataHighloadV2R2 {
- wallet_id,
- last_cleaned_time: 0,
- public_key,
- }
- .try_into()?,
- WalletVersion::HighloadV1R1
- | WalletVersion::HighloadV1R2
- | WalletVersion::HighloadV2
- | WalletVersion::HighloadV2R1 => {
- return Err(TonCellError::InternalError(
- "No generation for this wallet version".to_string(),
- ));
- }
};
Ok(Arc::new(data_cell))
diff --git a/rust/apps/ton/src/vendor/wallet/types.rs b/rust/apps/ton/src/vendor/wallet/types.rs
index 4d2775160..ea9b47b17 100644
--- a/rust/apps/ton/src/vendor/wallet/types.rs
+++ b/rust/apps/ton/src/vendor/wallet/types.rs
@@ -1,70 +1,5 @@
use crate::vendor::cell::{Cell, CellBuilder, TonCellError};
-/// WalletVersion::V1R1 | WalletVersion::V1R2 | WalletVersion::V1R3 | WalletVersion::V2R1 | WalletVersion::V2R2
-pub struct WalletDataV1V2 {
- pub seqno: u32,
- pub public_key: [u8; 32],
-}
-
-impl TryFrom for WalletDataV1V2 {
- type Error = TonCellError;
-
- fn try_from(value: Cell) -> Result {
- let mut parser = value.parser();
- let seqno = parser.load_u32(32)?;
- let mut public_key = [0u8; 32];
- parser.load_slice(&mut public_key)?;
- Ok(Self { seqno, public_key })
- }
-}
-
-impl TryFrom for Cell {
- type Error = TonCellError;
-
- fn try_from(value: WalletDataV1V2) -> Result {
- CellBuilder::new()
- .store_u32(32, value.seqno)?
- .store_slice(&value.public_key)?
- .build()
- }
-}
-
-/// WalletVersion::V3R1 | WalletVersion::V3R2
-pub struct WalletDataV3 {
- pub seqno: u32,
- pub wallet_id: i32,
- pub public_key: [u8; 32],
-}
-
-impl TryFrom for WalletDataV3 {
- type Error = TonCellError;
-
- fn try_from(value: Cell) -> Result {
- let mut parser = value.parser();
- let seqno = parser.load_u32(32)?;
- let wallet_id = parser.load_i32(32)?;
- let mut public_key = [0u8; 32];
- parser.load_slice(&mut public_key)?;
- Ok(Self {
- seqno,
- wallet_id,
- public_key,
- })
- }
-}
-
-impl TryFrom for Cell {
- type Error = TonCellError;
-
- fn try_from(value: WalletDataV3) -> Result {
- CellBuilder::new()
- .store_u32(32, value.seqno)?
- .store_i32(32, value.wallet_id)?
- .store_slice(&value.public_key)?
- .build()
- }
-}
-
/// WalletVersion::V4R1 | WalletVersion::V4R2
pub struct WalletDataV4 {
pub seqno: u32,
@@ -103,43 +38,3 @@ impl TryFrom for Cell {
.build()
}
}
-
-/// WalletVersion::HighloadV2R2
-pub struct WalletDataHighloadV2R2 {
- pub wallet_id: i32,
- pub last_cleaned_time: u64,
- pub public_key: [u8; 32],
-}
-
-impl TryFrom for WalletDataHighloadV2R2 {
- type Error = TonCellError;
-
- fn try_from(value: Cell) -> Result {
- let mut parser = value.parser();
- let wallet_id = parser.load_i32(32)?;
- let last_cleaned_time = parser.load_u64(64)?;
- let mut public_key = [0u8; 32];
- parser.load_slice(&mut public_key)?;
- // TODO: handle queries dict
- Ok(Self {
- wallet_id,
- last_cleaned_time,
- public_key,
- })
- }
-}
-
-impl TryFrom for Cell {
- type Error = TonCellError;
-
- fn try_from(value: WalletDataHighloadV2R2) -> Result {
- CellBuilder::new()
- .store_i32(32, value.wallet_id)?
- // TODO: not sure what goes into last_cleaned_time, so I set it to 0
- .store_u64(64, value.last_cleaned_time)?
- .store_slice(&value.public_key)?
- // empty plugin dict
- .store_bit(false)?
- .build()
- }
-}
diff --git a/rust/apps/wallets/Cargo.toml b/rust/apps/wallets/Cargo.toml
index e48025111..5b69df7b4 100644
--- a/rust/apps/wallets/Cargo.toml
+++ b/rust/apps/wallets/Cargo.toml
@@ -15,3 +15,4 @@ ur-registry = { workspace = true }
bitcoin = { workspace = true }
cryptoxide = { workspace = true }
serde_json = { workspace = true }
+zcash_vendor = { workspace = true }
diff --git a/rust/apps/wallets/src/backpack.rs b/rust/apps/wallets/src/backpack.rs
index ac23eaa69..769569190 100644
--- a/rust/apps/wallets/src/backpack.rs
+++ b/rust/apps/wallets/src/backpack.rs
@@ -17,9 +17,9 @@ use {
use crate::{common::get_path_component, ExtendedPublicKey};
-const ETH_STANDARD_PREFIX: &str = "m/44'/60'/0'";
-const ETH_LEDGER_LIVE_PREFIX: &str = "m/44'/60'"; //overlap with ETH_STANDARD at 0
-const SOL_PREFIX: &str = "m/44'/501'";
+const ETH_STANDARD_PREFIX: &str = "44'/60'/0'";
+const ETH_LEDGER_LIVE_PREFIX: &str = "44'/60'"; //overlap with ETH_STANDARD at 0
+const SOL_PREFIX: &str = "44'/501'";
pub fn generate_crypto_multi_accounts(
master_fingerprint: [u8; 4],
diff --git a/rust/apps/wallets/src/bitget.rs b/rust/apps/wallets/src/bitget.rs
index 1eb13bc15..11d58091c 100644
--- a/rust/apps/wallets/src/bitget.rs
+++ b/rust/apps/wallets/src/bitget.rs
@@ -23,13 +23,13 @@ fn get_device_id(serial_number: &str) -> String {
hex::encode(&sha256(&sha256(serial_number.as_bytes()))[0..20])
}
-const BTC_LEGACY_PREFIX: &str = "m/44'/0'/0'";
-const BTC_SEGWIT_PREFIX: &str = "m/49'/0'/0'";
-const BTC_NATIVE_SEGWIT_PREFIX: &str = "m/84'/0'/0'";
-const BTC_TAPROOT_PREFIX: &str = "m/86'/0'/0'";
-const ETH_STANDARD_PREFIX: &str = "m/44'/60'/0'";
-const ETH_LEDGER_LIVE_PREFIX: &str = "m/44'/60'"; //overlap with ETH_STANDARD at 0
-const TON_PREFIX: &str = "m/44'/607'";
+const BTC_LEGACY_PREFIX: &str = "44'/0'/0'";
+const BTC_SEGWIT_PREFIX: &str = "49'/0'/0'";
+const BTC_NATIVE_SEGWIT_PREFIX: &str = "84'/0'/0'";
+const BTC_TAPROOT_PREFIX: &str = "86'/0'/0'";
+const ETH_STANDARD_PREFIX: &str = "44'/60'/0'";
+const ETH_LEDGER_LIVE_PREFIX: &str = "44'/60'"; //overlap with ETH_STANDARD at 0
+const TON_PREFIX: &str = "44'/607'";
pub fn generate_crypto_multi_accounts(
master_fingerprint: [u8; 4],
diff --git a/rust/apps/wallets/src/lib.rs b/rust/apps/wallets/src/lib.rs
index fcfea6484..0d6f1224c 100644
--- a/rust/apps/wallets/src/lib.rs
+++ b/rust/apps/wallets/src/lib.rs
@@ -30,6 +30,7 @@ pub mod tonkeeper;
mod utils;
pub mod xbull;
pub mod xrp_toolkit;
+pub mod zcash;
//TODO: get these value from device
pub const DEVICE_TYPE: &str = "Keystone 3 Pro";
diff --git a/rust/apps/wallets/src/okx.rs b/rust/apps/wallets/src/okx.rs
index 220e7d036..bacefd433 100644
--- a/rust/apps/wallets/src/okx.rs
+++ b/rust/apps/wallets/src/okx.rs
@@ -22,16 +22,16 @@ fn get_device_id(serial_number: &str) -> String {
hex::encode(&sha256(&sha256(serial_number.as_bytes()))[0..20])
}
-const BTC_LEGACY_PREFIX: &str = "m/44'/0'/0'";
-const BTC_SEGWIT_PREFIX: &str = "m/49'/0'/0'";
-const BTC_NATIVE_SEGWIT_PREFIX: &str = "m/84'/0'/0'";
-const BTC_TAPROOT_PREFIX: &str = "m/86'/0'/0'";
-const ETH_STANDARD_PREFIX: &str = "m/44'/60'/0'";
-const ETH_LEDGER_LIVE_PREFIX: &str = "m/44'/60'"; //overlap with ETH_STANDARD at 0
-const TRX_PREFIX: &str = "m/44'/195'/0'";
-const LTC_PREFIX: &str = "m/49'/2'/0'";
-const BCH_PREFIX: &str = "m/44'/145'/0'";
-const DASH_PREFIX: &str = "m/44'/5'/0'";
+const BTC_LEGACY_PREFIX: &str = "44'/0'/0'";
+const BTC_SEGWIT_PREFIX: &str = "49'/0'/0'";
+const BTC_NATIVE_SEGWIT_PREFIX: &str = "84'/0'/0'";
+const BTC_TAPROOT_PREFIX: &str = "86'/0'/0'";
+const ETH_STANDARD_PREFIX: &str = "44'/60'/0'";
+const ETH_LEDGER_LIVE_PREFIX: &str = "44'/60'"; //overlap with ETH_STANDARD at 0
+const TRX_PREFIX: &str = "44'/195'/0'";
+const LTC_PREFIX: &str = "49'/2'/0'";
+const BCH_PREFIX: &str = "44'/145'/0'";
+const DASH_PREFIX: &str = "44'/5'/0'";
pub fn generate_crypto_multi_accounts(
master_fingerprint: [u8; 4],
diff --git a/rust/apps/wallets/src/thor_wallet.rs b/rust/apps/wallets/src/thor_wallet.rs
index 4ab456f44..3898c8598 100644
--- a/rust/apps/wallets/src/thor_wallet.rs
+++ b/rust/apps/wallets/src/thor_wallet.rs
@@ -22,12 +22,12 @@ fn get_device_id(serial_number: &str) -> String {
hex::encode(&sha256(&sha256(serial_number.as_bytes()))[0..20])
}
-const BTC_LEGACY_PREFIX: &str = "m/44'/0'/0'";
-const BTC_SEGWIT_PREFIX: &str = "m/49'/0'/0'";
-const BTC_NATIVE_SEGWIT_PREFIX: &str = "m/84'/0'/0'";
-const ETH_STANDARD_PREFIX: &str = "m/44'/60'/0'";
-const ETH_LEDGER_LIVE_PREFIX: &str = "m/44'/60'"; //overlap with ETH_STANDARD at 0
-const THORCHAIN_PREFIX: &str = "m/44'/931'/0'";
+const BTC_LEGACY_PREFIX: &str = "44'/0'/0'";
+const BTC_SEGWIT_PREFIX: &str = "49'/0'/0'";
+const BTC_NATIVE_SEGWIT_PREFIX: &str = "84'/0'/0'";
+const ETH_STANDARD_PREFIX: &str = "44'/60'/0'";
+const ETH_LEDGER_LIVE_PREFIX: &str = "44'/60'"; //overlap with ETH_STANDARD at 0
+const THORCHAIN_PREFIX: &str = "44'/931'/0'";
pub fn generate_crypto_multi_accounts(
master_fingerprint: [u8; 4],
diff --git a/rust/apps/wallets/src/zcash.rs b/rust/apps/wallets/src/zcash.rs
new file mode 100644
index 000000000..82b53f229
--- /dev/null
+++ b/rust/apps/wallets/src/zcash.rs
@@ -0,0 +1,37 @@
+use alloc::string::{String, ToString};
+use alloc::vec;
+use alloc::vec::Vec;
+
+use app_utils::impl_public_struct;
+use ur_registry::{
+ crypto_hd_key::CryptoHDKey,
+ crypto_key_path::CryptoKeyPath,
+ error::{URError, URResult},
+ zcash::{
+ zcash_accounts::ZcashAccounts, zcash_unified_full_viewing_key::ZcashUnifiedFullViewingKey,
+ },
+};
+
+impl_public_struct!(UFVKInfo {
+ key_text: String,
+ key_name: String,
+ index: u32
+});
+
+pub fn generate_sync_ur(
+ key_infos: Vec,
+ seed_fingerprint: [u8; 32],
+) -> URResult {
+ let keys = key_infos
+ .iter()
+ .map(|info| {
+ Ok(ZcashUnifiedFullViewingKey::new(
+ info.key_text.clone(),
+ info.index,
+ Some(info.key_name.clone()),
+ ))
+ })
+ .collect::>>()?;
+ let accounts = ZcashAccounts::new(seed_fingerprint.to_vec(), keys);
+ Ok(accounts)
+}
diff --git a/rust/apps/zcash/Cargo.toml b/rust/apps/zcash/Cargo.toml
new file mode 100644
index 000000000..f66488fa9
--- /dev/null
+++ b/rust/apps/zcash/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "app_zcash"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+keystore = { workspace = true }
+rust_tools = { workspace = true }
+app_utils = { workspace = true }
+bitcoin = { workspace = true }
+thiserror = { workspace = true }
+zcash_vendor = { workspace = true }
+hex = { workspace = true }
+bitvec = {version = "1.0.1", default-features = false, features = ["alloc"]}
+blake2b_simd = { workspace = true }
+rand_core = { workspace = true, features = ["getrandom"] }
+zcash_note_encryption = "0.4.1"
+
+[dev-dependencies]
+keystore = { path = "../../keystore" }
diff --git a/rust/apps/zcash/src/errors.rs b/rust/apps/zcash/src/errors.rs
new file mode 100644
index 000000000..218f58966
--- /dev/null
+++ b/rust/apps/zcash/src/errors.rs
@@ -0,0 +1,30 @@
+use alloc::string::String;
+use thiserror;
+use thiserror::Error;
+use zcash_vendor::{orchard, transparent};
+
+pub type Result = core::result::Result;
+
+#[derive(Error, Debug, PartialEq)]
+pub enum ZcashError {
+ #[error("failed to generate zcash address, {0}")]
+ GenerateAddressError(String),
+ #[error("invalid zcash data: {0}")]
+ InvalidDataError(String),
+ #[error("failed to sign zcash data, {0}")]
+ SigningError(String),
+ #[error("invalid pczt, {0}")]
+ InvalidPczt(String),
+}
+
+impl From for ZcashError {
+ fn from(e: orchard::pczt::ParseError) -> Self {
+ Self::InvalidPczt(alloc::format!("Invalid Orchard bundle: {:?}", e))
+ }
+}
+
+impl From for ZcashError {
+ fn from(e: transparent::pczt::ParseError) -> Self {
+ Self::InvalidPczt(alloc::format!("Invalid transparent bundle: {:?}", e))
+ }
+}
diff --git a/rust/apps/zcash/src/lib.rs b/rust/apps/zcash/src/lib.rs
new file mode 100644
index 000000000..3859cb402
--- /dev/null
+++ b/rust/apps/zcash/src/lib.rs
@@ -0,0 +1,79 @@
+#![no_std]
+#![feature(error_in_core)]
+extern crate alloc;
+
+pub mod errors;
+pub mod pczt;
+
+use errors::{Result, ZcashError};
+
+use alloc::{
+ format,
+ string::{String, ToString},
+ vec::Vec,
+};
+use pczt::structs::ParsedPczt;
+use zcash_vendor::{
+ pczt::Pczt,
+ zcash_keys::keys::UnifiedFullViewingKey,
+ zcash_protocol::consensus::{self},
+ zip32,
+};
+
+pub fn get_address(params: &P, ufvk_text: &str) -> Result {
+ let ufvk = UnifiedFullViewingKey::decode(params, ufvk_text)
+ .map_err(|e| ZcashError::GenerateAddressError(e.to_string()))?;
+ let (address, _) = ufvk
+ .default_address(None)
+ .map_err(|e| ZcashError::GenerateAddressError(e.to_string()))?;
+ Ok(address.encode(params))
+}
+
+pub fn check_pczt(
+ params: &P,
+ pczt: &[u8],
+ ufvk_text: &str,
+ seed_fingerprint: &[u8; 32],
+ account_index: u32,
+) -> Result<()> {
+ let ufvk = UnifiedFullViewingKey::decode(params, ufvk_text)
+ .map_err(|e| ZcashError::InvalidDataError(e.to_string()))?;
+ let pczt =
+ Pczt::parse(pczt).map_err(|_e| ZcashError::InvalidPczt(format!("invalid pczt data")))?;
+ let account_index = zip32::AccountId::try_from(account_index)
+ .map_err(|_e| ZcashError::InvalidDataError(format!("invalid account index")))?;
+ pczt::check::check_pczt(params, seed_fingerprint, account_index, &ufvk, &pczt)
+}
+
+pub fn parse_pczt(
+ params: &P,
+ pczt: &[u8],
+ ufvk_text: &str,
+ seed_fingerprint: &[u8; 32],
+) -> Result {
+ let ufvk = UnifiedFullViewingKey::decode(params, ufvk_text)
+ .map_err(|e| ZcashError::InvalidDataError(e.to_string()))?;
+ let pczt =
+ Pczt::parse(pczt).map_err(|_e| ZcashError::InvalidPczt(format!("invalid pczt data")))?;
+ pczt::parse::parse_pczt(params, seed_fingerprint, &ufvk, &pczt)
+}
+
+pub fn sign_pczt(pczt: &[u8], seed: &[u8]) -> Result> {
+ let pczt =
+ Pczt::parse(pczt).map_err(|_e| ZcashError::InvalidPczt(format!("invalid pczt data")))?;
+ pczt::sign::sign_pczt(pczt, seed)
+}
+
+#[cfg(test)]
+mod tests {
+ use consensus::MainNetwork;
+
+ use super::*;
+ extern crate std;
+ use std::println;
+ #[test]
+ fn test_get_address() {
+ let address = get_address(&MainNetwork, "uview1s2e0495jzhdarezq4h4xsunfk4jrq7gzg22tjjmkzpd28wgse4ejm6k7yfg8weanaghmwsvc69clwxz9f9z2hwaz4gegmna0plqrf05zkeue0nevnxzm557rwdkjzl4pl4hp4q9ywyszyjca8jl54730aymaprt8t0kxj8ays4fs682kf7prj9p24dnlcgqtnd2vnskkm7u8cwz8n0ce7yrwx967cyp6dhkc2wqprt84q0jmwzwnufyxe3j0758a9zgk9ssrrnywzkwfhu6ap6cgx3jkxs3un53n75s3");
+ println!("{:?}", address);
+ }
+}
diff --git a/rust/apps/zcash/src/pczt/check.rs b/rust/apps/zcash/src/pczt/check.rs
new file mode 100644
index 000000000..d821fc571
--- /dev/null
+++ b/rust/apps/zcash/src/pczt/check.rs
@@ -0,0 +1,386 @@
+use super::*;
+
+use orchard::{keys::FullViewingKey, value::ValueSum};
+use zcash_vendor::{
+ pczt::{self, roles::verifier::Verifier, Pczt},
+ ripemd::Ripemd160,
+ sha2::{Digest, Sha256},
+ transparent::{self, address::TransparentAddress, keys::AccountPubKey},
+ zcash_address::{ToAddress, ZcashAddress},
+ zcash_protocol::consensus::{self, NetworkConstants},
+ zip32,
+};
+
+pub fn check_pczt(
+ params: &P,
+ seed_fingerprint: &[u8; 32],
+ account_index: zip32::AccountId,
+ ufvk: &UnifiedFullViewingKey,
+ pczt: &Pczt,
+) -> Result<(), ZcashError> {
+ let xpub = ufvk.transparent().ok_or(ZcashError::InvalidDataError(
+ "transparent xpub is not present".to_string(),
+ ))?;
+ let orchard = ufvk.orchard().ok_or(ZcashError::InvalidDataError(
+ "orchard fvk is not present".to_string(),
+ ))?;
+ Verifier::new(pczt.clone())
+ .with_orchard(|bundle| {
+ check_orchard(params, &seed_fingerprint, account_index, &orchard, bundle)
+ .map_err(pczt::roles::verifier::OrchardError::Custom)
+ })
+ .map_err(|e| ZcashError::InvalidDataError(alloc::format!("{:?}", e)))?
+ .with_transparent(|bundle| {
+ check_transparent(params, seed_fingerprint, account_index, &xpub, bundle)
+ .map_err(pczt::roles::verifier::TransparentError::Custom)
+ })
+ .map_err(|e| ZcashError::InvalidDataError(alloc::format!("{:?}", e)))?;
+ Ok(())
+}
+
+fn check_transparent(
+ params: &P,
+ seed_fingerprint: &[u8; 32],
+ account_index: zip32::AccountId,
+ xpub: &AccountPubKey,
+ bundle: &transparent::pczt::Bundle,
+) -> Result<(), ZcashError> {
+ bundle.inputs().iter().try_for_each(|input| {
+ check_transparent_input(params, seed_fingerprint, account_index, xpub, input)?;
+ Ok::<_, ZcashError>(())
+ })?;
+ bundle.outputs().iter().try_for_each(|output| {
+ check_transparent_output(params, seed_fingerprint, account_index, xpub, output)?;
+ Ok::<_, ZcashError>(())
+ })?;
+ Ok(())
+}
+
+fn check_transparent_input(
+ params: &P,
+ seed_fingerprint: &[u8; 32],
+ account_index: zip32::AccountId,
+ xpub: &AccountPubKey,
+ input: &transparent::pczt::Input,
+) -> Result<(), ZcashError> {
+ let script = input.script_pubkey().clone();
+ //p2sh transparent input is not supported yet
+ match script.address() {
+ Some(TransparentAddress::PublicKeyHash(hash)) => {
+ // 1: find my derivation
+ let my_derivation = input
+ .bip32_derivation()
+ .iter()
+ .find(|(_pubkey, derivation)| seed_fingerprint == derivation.seed_fingerprint());
+ match my_derivation {
+ None => {
+ //not my input, pass
+ return Ok(());
+ }
+ Some((pubkey, derivation)) => {
+ // 2: derive my pubkey
+ let target = xpub
+ .derive_pubkey_at_bip32_path(
+ params,
+ account_index,
+ &derivation.derivation_path(),
+ )
+ .map_err(|_| {
+ ZcashError::InvalidPczt(
+ "transparent input bip32 derivation path invalid".to_string(),
+ )
+ })?;
+ // 3: check my pubkey
+ if &target.serialize() != pubkey {
+ return Err(ZcashError::InvalidPczt(
+ "transparent input script pubkey mismatch".to_string(),
+ ));
+ }
+ // 4: check script pubkey
+ if hash[..] != Ripemd160::digest(Sha256::digest(pubkey))[..] {
+ return Err(ZcashError::InvalidPczt(
+ "transparent input script pubkey mismatch".to_string(),
+ ));
+ }
+ Ok(())
+ }
+ }
+ }
+ _ => Err(ZcashError::InvalidPczt(
+ "transparent input script pubkey is not a public key hash".to_string(),
+ )),
+ }
+}
+
+fn check_transparent_output(
+ params: &P,
+ seed_fingerprint: &[u8; 32],
+ account_index: zip32::AccountId,
+ xpub: &AccountPubKey,
+ output: &transparent::pczt::Output,
+) -> Result<(), ZcashError> {
+ let script = output.script_pubkey().clone();
+ match script.address() {
+ Some(TransparentAddress::PublicKeyHash(hash)) => {
+ //check user_address and script_pubkey
+ match output.user_address() {
+ Some(user_address) => {
+ let ta =
+ ZcashAddress::from_transparent_p2pkh(params.network_type(), hash).encode();
+ if user_address != &ta {
+ return Err(ZcashError::InvalidPczt(
+ "transparent output user_address mismatch".to_string(),
+ ));
+ }
+ }
+ None => {
+ return Err(ZcashError::InvalidPczt(
+ "transparent output user_address is None".to_string(),
+ ))
+ }
+ }
+
+ let pubkey = output
+ .bip32_derivation()
+ .keys()
+ .find(|pubkey| hash[..] == Ripemd160::digest(Sha256::digest(pubkey))[..]);
+ match pubkey {
+ Some(pubkey) => {
+ match output.bip32_derivation().get(pubkey) {
+ Some(bip32_derivation) => {
+ if seed_fingerprint == bip32_derivation.seed_fingerprint() {
+ //verify public key
+ let target = xpub
+ .derive_pubkey_at_bip32_path(
+ params,
+ account_index,
+ bip32_derivation.derivation_path(),
+ )
+ .map_err(|_| {
+ ZcashError::InvalidPczt(
+ "transparent input bip32 derivation path invalid"
+ .to_string(),
+ )
+ })?;
+ if &target.serialize() != pubkey {
+ return Err(ZcashError::InvalidPczt(
+ "transparent output script pubkey mismatch".to_string(),
+ ));
+ }
+ Ok(())
+ } else {
+ //not my output, pass
+ Ok(())
+ }
+ }
+ //not my output, pass
+ None => Ok(()),
+ }
+ }
+ //not my output, pass
+ None => Ok(()),
+ }
+ }
+ Some(TransparentAddress::ScriptHash(hash)) => {
+ //check user_address
+ match output.user_address() {
+ Some(user_address) => {
+ let ta =
+ ZcashAddress::from_transparent_p2sh(params.network_type(), hash).encode();
+ if user_address != &ta {
+ return Err(ZcashError::InvalidPczt(
+ "transparent output user_address mismatch".to_string(),
+ ));
+ }
+ }
+ None => {
+ return Err(ZcashError::InvalidPczt(
+ "transparent output user_address is None".to_string(),
+ ))
+ }
+ }
+ // 1: find my derivation
+ let my_derivation = output
+ .bip32_derivation()
+ .iter()
+ .find(|(_pubkey, derivation)| seed_fingerprint == derivation.seed_fingerprint());
+ match my_derivation {
+ None => {
+ //not my output, pass
+ return Ok(());
+ }
+ Some((pubkey, derivation)) => {
+ // 2: derive my pubkey
+ let target = xpub
+ .derive_pubkey_at_bip32_path(
+ params,
+ account_index,
+ &derivation.derivation_path(),
+ )
+ .map_err(|_| {
+ ZcashError::InvalidPczt(
+ "transparent input bip32 derivation path invalid".to_string(),
+ )
+ })?;
+ // 3: check my pubkey
+ if &target.serialize() != pubkey {
+ return Err(ZcashError::InvalidPczt(
+ "transparent input script pubkey mismatch".to_string(),
+ ));
+ }
+ // TODO: find a proper way to check script pubkey
+ Ok(())
+ }
+ }
+ }
+ _ => Err(ZcashError::InvalidPczt(
+ "transparent output script pubkey is not a public key hash".to_string(),
+ )),
+ }
+}
+
+fn check_orchard(
+ params: &P,
+ seed_fingerprint: &[u8; 32],
+ account_index: zip32::AccountId,
+ fvk: &FullViewingKey,
+ bundle: &orchard::pczt::Bundle,
+) -> Result<(), ZcashError> {
+ bundle.actions().iter().try_for_each(|action| {
+ check_action(params, seed_fingerprint, account_index, fvk, action)?;
+ Ok::<_, ZcashError>(())
+ })?;
+
+ // At this point, we know that every `value` field in the Orchard bundle is present.
+ // Check that `value_sum` is correct so we can use it for fee calculations later.
+ let calculated_value_balance = bundle
+ .actions()
+ .iter()
+ .map(|action| {
+ action.spend().value().expect("present") - action.output().value().expect("present")
+ })
+ .sum::>();
+
+ match calculated_value_balance {
+ Ok(value_balance) if &value_balance == bundle.value_sum() => Ok(()),
+ _ => Err(ZcashError::InvalidPczt(
+ "invalid Orchard bundle value balance".into(),
+ )),
+ }
+}
+
+fn check_action(
+ params: &P,
+ seed_fingerprint: &[u8; 32],
+ account_index: zip32::AccountId,
+ fvk: &FullViewingKey,
+ action: &orchard::pczt::Action,
+) -> Result<(), ZcashError> {
+ // Check `cv_net` first so we know that the `value` fields for both the spend and the
+ // output are present and correct.
+ action.verify_cv_net().map_err(|e| {
+ ZcashError::InvalidPczt(alloc::format!("invalid cv_net in Orchard action: {:?}", e))
+ })?;
+
+ check_action_spend(
+ params,
+ seed_fingerprint,
+ account_index,
+ fvk,
+ &action.spend(),
+ )?;
+ check_action_output(action)
+}
+
+// check spend nullifier
+fn check_action_spend(
+ params: &P,
+ seed_fingerprint: &[u8; 32],
+ account_index: zip32::AccountId,
+ fvk: &FullViewingKey,
+ spend: &orchard::pczt::Spend,
+) -> Result<(), ZcashError> {
+ // We can only verify the `nullifier` and `rk` fields of a spend if we know its FVK.
+ let can_verify_nf_rk = match (spend.value(), spend.fvk(), spend.zip32_derivation()) {
+ // If the spend is marked as matching the accounts's FVK, verify with it.
+ (_, _, Some(zip32_derivation))
+ if zip32_derivation.seed_fingerprint() == seed_fingerprint
+ && zip32_derivation.derivation_path()
+ == &[
+ zip32::ChildIndex::hardened(32),
+ zip32::ChildIndex::hardened(params.network_type().coin_type()),
+ account_index.into(),
+ ] =>
+ {
+ Some(Some(fvk))
+ }
+ // Dummy notes use randomly-generated FVKs, so if one is already present then
+ // don't validate using the account's FVK.
+ (Some(value), Some(_), _) if value.inner() == 0 => Some(None),
+ // Don't verify `nullifier` or `rk` for any other spends.
+ _ => None,
+ };
+
+ if let Some(expected_fvk) = can_verify_nf_rk {
+ spend.verify_nullifier(expected_fvk).map_err(|e| {
+ ZcashError::InvalidPczt(alloc::format!("invalid Orchard action nullifier: {:?}", e))
+ })?;
+ spend.verify_rk(expected_fvk).map_err(|e| {
+ ZcashError::InvalidPczt(alloc::format!("invalid Orchard action rk: {:?}", e))
+ })?;
+ }
+
+ Ok(())
+}
+
+//check output cmx
+fn check_action_output(action: &orchard::pczt::Action) -> Result<(), ZcashError> {
+ action
+ .output()
+ .verify_note_commitment(action.spend())
+ .map_err(|e| {
+ ZcashError::InvalidPczt(alloc::format!("invalid Orchard action cmx: {:?}", e))
+ })?;
+
+ // TODO: Currently the "can decrypt output" check is performed implicitly by
+ // `parse_orchard_output`. If desired, that code could be called from here and
+ // checked; then in `parse_orchard_output` it would never error if reached.
+
+ Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+ use zcash_vendor::{pczt::Pczt, zcash_protocol::consensus::MAIN_NETWORK};
+ use super::*;
+
+ #[test]
+ fn test_check_pczt_to_transparent_output() {
+ {
+ let fingerprint =
+ hex::decode("2fac20755b7bb7c99d302b782ea36f62a1b0cfe8d7d4d09a58e8ba5da26f4578")
+ .unwrap();
+
+ let ufvk = "uview10zf3gnxd08cne6g7ryh6lln79duzsayg0qxktvyc3l6uutfk0agmyclm5g82h5z0lqv4c2gzp0eu0qc0nxzurxhj4ympwn3gj5c3dc9g7ca4eh3q09fw9kka7qplzq0wnauekf45w9vs4g22khtq57sc8k6j6s70kz0rtqlyat6zsjkcqfrlm9quje8vzszs8y9mjvduf7j2vx329hk2v956g6svnhqswxfp3n760mw233w7ffgsja2szdhy5954hsfldalf28wvav0tctxwkmkgrk43tq2p7sqchzc6";
+
+ let unified_fvk = UnifiedFullViewingKey::decode(&MAIN_NETWORK, ufvk).unwrap();
+
+ let hex_str = "50435a5401000000058ace9cb502d5a09cc70c0100d989a80185010001227a636173685f636c69656e745f6261636b656e643a70726f706f73616c5f696e666f144951eeff9ccf4eb390ff94a60aa5673db189a8010001a08d061976a9149517c77b7fcc08e66122dccb6ee6713eb7712d2b88ac00000123743158547742385031783459697042744c6850575331334a50445135524d6b4d41364d01207a636173685f636c69656e745f6261636b656e643a6f75747075745f696e666f0100000000fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e010000000000000000000000000000000000000000000000000000000000000000023ad18a78e48f81fe95b3569486ee1db9eed90a319fac6faea1eed4e35b936717236c4a092e80c35e67e0b51b7a41de4013eaffed855b138934b9dcf28ad51f1ea51f60210a8d7f4f6ffb848bbafd4cdfd09df400e53c595861cc0dd8afc32dae010fba942a1bc32f2cc78408be742cd13846bbd50f3869c09d59bffc4e758949b56f422def9eb9d491721b9fc198edf183e9c32920eb30c476f236009a16355d1401b169abb973b87b0fd009693c349a5fdccaa2f1a266ea99f4e7f1fa13d2a8ec96023d73d0573b6fcdbe1b95010001986da568298f3de75fc0bf29de32aec6f2dada30c4e20286eb23667048d21d29017dd8c0825f1f2bc7aac48163e06f44024a657495e7c75fd1d2192336eef159640181679891b0cc1eaf42df83756d69c6833d552e0faa6d3c6af1405f2fcd4fbe0c360dff7f03b6da416da80b533cfb442be30185c9a7f4cba15f7fc836ccbd5d3e88daccb4be13ee8b9f850e542106ecb8107538ea23f4e21882e0c3fa46c0a228018daff38304e9759e20f4bb6f424a1040b554548feaf87e285a0a2ac9de930047e4bdc7042e08965e83fee3c20b18e3a7119457853e42b704f3df3449da1c365804abe0dd16ea51dbe4502e425ef8bb0103a9c314b041a9bf531facdc6ccab8404459261003b77426a46dff084bc2ff8f9a3da8c250bdd0ba8419d086b88fb25285d4fe8d047041cd2be273e8ccfabe154a818f491ea3fb9b9d854f4935480aa253fe35882ddfcc90b2b71eaa44f5299a34a946993fef33bc55c87a5f3427ac646f42eabe190c6856f4c8c1d1f505262b85353de115b061e2a1df24e69ec911e8f1c78b5c0716b8f01d16c560e3b81a07b3030c3beb15613b23e925c9456a9bfee1a25ef51f1ce9bf853c1264f6dd6fa2ea7087a8a78051626518afc8e88a1ed226f0cec1159a4a5ec4131041b3d8cc58ba10c7f676f52805be117a5689fa1a474e3f5bce38349f10e63ba7721a019ced0b63be870cef6f9ef2d228d8a58e695e871f7c4b0e94445d5255708c50298b13c55044f8f5995a258826291eda6f1671681e8f101aad68a17330a3faf4017f87b315aa53bb57fb785953dd9a480c85dd1182fcb235df28c7d3f3d8b79fe72f3b42d63c7ae563f0a4df22de593a488ee514dbda39291a69a0fd09a17ca6786cba733fdadb0f785147676378e7fbdd2a00a45b14460f415578abf268306554e68261022eb4c1e60df1566ac1853d01b2685924329e17963014ba9cd39f6c1c7f7e169574bab623fc15066223196ce0b1ef2251e5dc1f56707910d825c1451bf98115afd2dff4800fcfefc74c237b7bfec5cc2bf20e158f09cbd482b2f17cb0dcef82660ff0f697459e9cb1fdc77a10cffa9b91d88c3791b4a47e11781e0a7e1215315900a40bad41570d70ed6e7598d48eb8956ef90afda546e823446a3cb65a80f1407ea065d196f07524561be836cb5de0b9d5ba3665d2abf29c30bcef800dbeee9e293c59e4c5cee22984e205ebd67147ed3bf8234e654e32053e16bfe2cdeb70f83e1288793284056aac734eb8593feae99c48036b3d852f228febddd3c402bc5ae92d1e1adc313a53eae14213d67afb688efe0c2cdbff9ff826ad0b6cb2d8907949fbacc71fa539a9c60e6c3e2b79ba68b4b73b5b7d6f6e8f08ab80eb53099df60f6bd0c06d9b1e701c7471b9e9453bc78fa00ecaa28a1dbc9b56d2b0750eb5d038d58257a94fc57072f676555b9120536834309db16e168d8dc3f2b8680435853f216b576e39e9ea212f3fb2804c85065d801cf77c2586a76c404023554755ee41cffc358a30d67a26f758979f7f52233a680f0fa64ecdce560dfb206f232ec18450806a8fd8eccf23ea0cbd2dbe3374ccce23449d58aef4512452a329c037f96294f7a97a99fd7721e7bf07e32940b96dbb29e91a6bf267dfecf3e7bccaa657d405d2e7fd76ff8d51203b532a54868089c81d010b3b1b123a1303ec7643dbd09c1f396bc6915f6c4a02cdeba9becd724bb1f42e000000e0ebfc0224e6821685772ac6261127fa8dc097c4ce073ae9e468dbf8edb67a0131399b289425cf7741a1e779f1a089700276df5b193e1822bbf4416c89d4bc94c404b2ca1419e8f7cd98ed4f692efa5f01cc21558245469cfb558da73c13b42074ac966cc41733ffdfcade01c68062a0e0b4a74a3ab15123d62a6e270ea03c2ce88d337034e9537d7f871e8b1363b14096fd4ceb6ba46b2f7308ee1e0824eadd073dbdad58da08aa58b87fa7328710759597fe5a70516299c4a4302888b974da65c259cf8b3b4a1b7207e4d30f4b0f97e48702a25e17d51fa7ea2889d5926d9c66a151d8c713f267f95e0e730d89dbf2140cddcdc2d3508fa7902b1c360244ec407723929891f3990577a7478d4e0e3e374e4fc59e2ee704fca7a51196170e517eb74c339b016eeb3ff49ce10c13b217bbea0f4c234e4fe2766a788cd23000fe8920f973227ef987104d4d458f7754ed14fa2c798d7081d9311e0109c27ad89f362b24818cd803a600b2f21cf36e321c89ac785268e566e850d4c328eefce8062bbad81a854e08fa9a48f110f00072523cb6a670c52891af6e893ac010d4cf540a7ef598437803488d203de92966eb8ca9594d36ccb023d229ac8c391f4b9d50a569890052f27d9271f122c10f78b4c94c256f1e67a9e9c20779d34a0898daedb972ccee455ebb0e48b39d405f74f9074b943c5b5a38612e94bc8c82ec6176b90156289a99f816f64a5cd8cdfd8a9d1de4158e144869e3c535d1928f14d76d6a806b8730b92ada3353ededeb8c2151e876c566121ea2a6cfc93e3da2b1780b827ed7e5420c716b52b7811e650befc972685d153ac68ec9bf7d8b0a09659c5b36bd8226796770ebc05a6b9057a2c82feaae40a281edec65993cd792c980a845d2fbff8189d288500875f768205053e84b399b1a6141f380b7cfc235f26d3ce316cf2afae0404be86ea803a2733c9d32478c822dfa905a4e360c5fef6e05419088fe8921392c4366f976ecfd33332c0273e6ad6770a7a993010bf78b0565a3aa4fbb531de5fbd44a6caa636b2c03f0a38250bf599389154c4a55e4599a13b719551486bf010001587617b07bb6120ac6886c2a4641b8a0b9180ebd3375cf55e1f4066464ad43450000000001e902c227e9c4f4206e1f917c596fe9f4e6d2dca81063093d7065a70ed79674052df49c10eb57f2dda99dee1c1c01e9ed7efd1c9f6f971bf62906a97830b7ad2beec2cfcb30451b6c157fd144041e0429fa1aa2f9f7d0e84e74014205f0a9bd08171a83f92b3493fe29fa0802eefab10ecef3904aa569d82f6e95fdf2dc9cdd28000114b0cac3e14c4e1a4a4fd22c98563b9cbe859c67768a39f67abd5dbe55d3d16ff58e5c45b21d8c573f54b901a8ce920701de6d3d52208c36d6a557c3ed5843cf85a03b029ec491b8ad2541db678ab25a3d0125056d422f2e1393ba7e5295422e9ff38ce8276124ae0fec4bb06e147be83a8f017d6d7535f6e3eade13042662d05eefa91d1f4757fcd0b4b844554e77366f4b36a7068e15c2f06aaa11f6bcfd2e9e36231530069f7fb99a2771050689f24f332b427fdd05d1d5f3219230a1406f0955e3ddc0ef5ce2c7f160d797f3e54ef5782001cfdcac17ee2155c2c8b84c2ddc976891132206e97f7296033a7ef7eaa12ef214c4abf71d1439d50cefd21bedf293df7e11e187c64e13dd9a7905a1e2a26d2647cc1004394bba40a982173a00559da43ccad644d32eb4c4f785264fe3ebd9b12a1d7a6c31aab9e988f717752dbb6d8f555dcf360e25f71a7b1d95ab6b54761c3774882f16455a42d4ee6692b641bd0ccf14d81b56f0503932377bf5fae7d5a9c103c10e2ccd48e8778e0b217e8255746c998108508a6e81e1f1c1992ccd65ee9bfb196e0f7257c5dd5392cc0947e0b77bd30e18165c8a3541e62949e40c88c90fdf827133cbd17ab082f151d390180ca92cf0d8c4bd08e01b2f4f50b18bd589171d96723d00a3716420df0a98200f20a5136f36e955b51946a471eb029951e42268c00c34c53b660d2c636bf39e6f67e8933002c7b64fb410cd5e07cdac9e47d9d21c150a6fac33462496e7df033277558b54ac238f073776cb533551ced42caeba694f31fd8d40ccb9fb2e104aa0357a122141052c9a741c4c2c736b6dd0363ddbf27e2922ae2800cb93abe63b70c172de70362d9830e53800398884a7a64ff68ed99e0b9d2e26bdef115ced7bd36305a54386996133c4e65759f3731637a40eba67da103f98adbe364f148b0cc2042cafc6be1166fae39090ab4b354bfb6217b964453b63f8dbd10df936f1734973e0b3bd25f4ed440566c923085903f696bc6347ec0f6f3f63aab58e63b6449583df5658a91972a20291c6311b5b3e5240aff8d7d00212278dfeae9949f887b70ae81e084f8897a5054627acef3efd01c8b29793d522ca2ced953b7fb95e3ba986333da9e69cd355223c929731094b6c2174c7638d2e60040850b766b126a2b4843fcdfdffa5d5cab3f53bc860a3bef68958b5f066177097b04c2aa045a0deffcaca41c5ac92e694466578f5909e72bb78d33310f705cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d354708102dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402cdaf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234151f91982912012669f74d0cfa1030ff37b152324e5b8346b3335a0aaeb63a0a2de2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1be8ae2ad91d463bab75ee941d33cc5817b613c63cda943a4c07f600591b088a25d53fdee371cef596766823f4a518a583b1158243afe89700f0da76da46d0060f15d2444cefe7914c9a61e829c730eceb216288fee825f6b3b6298f6f6b6bd62e4c57a617a0aa10ea7a83aa6b6b0ed685b6a3d9e5b8fd14f56cdc18021b12253f3fd4915c19bd831a7920be55d969b2ac23359e2559da77de2373f06ca014ba2787d063cd07ee4944222b7762840eb94c688bec743fa8bdf7715c8fe29f104c2a014c18207b76f3808351694eae9a99f8d7786e4c3e6b0c3452a518b0375deb0829012fac20755b7bb7c99d302b782ea36f62a1b0cfe8d7d4d09a58e8ba5da26f457803a080808008858180800880808080080000c86d0beb146429ab2ddc5e2b67b68cd0fa540c8a2c1637cde3220874577fd72337afa5c4823cffe1c5c57ba90eb737f081827bbf51437a2c420afa809bb04f3cc4046b05a8223b1b1114958bc0e10ecb6ae0b383ebd22f686f57d2f905acca999ae1e85f85acc5cb5b517b4233d3db94dc05259c76e8a04ae5d84f4331348388387edd327e40ae6b542f5b92cfa0a55f01ba9ba3f0035d64311f55042c1b86a8178f3ce47592cc1cdc3d4dfcbe66b267906a2c38313651863037d5fb3aeb4fcb85cb06e489536fe35784e5a1c0bc9a8083fd43ca2aeb18881caa02e9bde0a29ebb0ed1687299d97ce49bb6545050756fda15ee31c9cd947bf9019d90db96e89e3ee3e63717c34b485530590387b8bd2f57adc2c5b2fea35209ea22b4e2cb5e2d65e1f56cd1f16e5954bfb8425826cd87b75e57262d710bd1d5c9bd3b4a2c99a89926cc32c59e16ceb64698e1bcd82ae21d02ee4cb67e814861cd22810a0adaff558df41125e37179d16adc7cd4e1296bd31f44290e8c218664074158e724aee81a5ee5fb7f16852263b6902521c90dc4380b54aaf700a1ca6bd93a22ec1fd062f14b32f6d2d6ff51e151bfda4ccd569bfb966d294be0ee61dae648877e25b0841a27d5c224d4fd949926d4dfde6d28b7d14e16ae60d2112a79da714bb454a9f6a034a191c659fcd0c20a35d85f18b8700a29c5cb9c386f2afb10e8fafa892c3a1c5fbfee08cd58610339b7222f5945e775cfbe87089f48081b38775541cadeebbd5b51ee981b9558a0d4e01a0fba29d0b50fa9b843db2dbcc25071352041a199d7a85d5bd956d7f61db4a95cc26b1709fa48c0eba34676ee7f855b70ea4f8657f6f00180b43be23c6edd3259a84b873d560f60f5a7d7fd54b0330f835398c4ef2bb3a61d2fae5088b03c542ac58f663ad15cb471e39f6f06d2a47cd696bda59923f64718e81a5438f1711d43e284b9c566e596dc77f1e0809f96d40f76804c265ab9654c1ff8c18a1e8410164d09ae5bc1dd982eceb57c0114b0cac3e14c4e1a4a4fd22c98563b9cbe859c67768a39f67abd5dbe55d3d16ff58e5c45b21d8c573f54b901f0cb8b0701cdf9bded0827a82dc56ad98807f9c96ca814b2651a6b82d22a5c10d5fc80cdbd00000001207a636173685f636c69656e745f6261636b656e643a6f75747075745f696e666f11024951eeff9ccf4eb390ff94a60aa5673d015249a562d4ea0bc08e26f627c4a418d274e930230cab2139e2766d2654f0ed3903b882070039fb66568096852da4cb54410485be43a51a0269351ed32433ed7ddd1b12d43b00013b4c678abdaf00e1fc4587a41d1402c75bbc0dcc1c0e2b7652dc14352b87623f";
+ let pczt_hex = hex::decode(hex_str).unwrap();
+ let pczt = Pczt::parse(&pczt_hex).unwrap();
+
+ let fingerprint = fingerprint.try_into().unwrap();
+
+ let result = check_pczt(
+ &MAIN_NETWORK,
+ &fingerprint,
+ zip32::AccountId::ZERO,
+ &unified_fvk,
+ &pczt,
+ );
+
+ assert_eq!(true, result.is_ok());
+ }
+ }
+ //TODO: add test for happy path
+}
diff --git a/rust/apps/zcash/src/pczt/mod.rs b/rust/apps/zcash/src/pczt/mod.rs
new file mode 100644
index 000000000..1f526a81d
--- /dev/null
+++ b/rust/apps/zcash/src/pczt/mod.rs
@@ -0,0 +1,12 @@
+use alloc::{string::ToString, vec::Vec};
+
+use keystore::algorithms::secp256k1::{get_public_key_by_seed};
+use keystore::algorithms::zcash::{calculate_seed_fingerprint, sign_message_orchard};
+use zcash_vendor::{orchard, zcash_keys::keys::UnifiedFullViewingKey};
+
+use crate::errors::ZcashError;
+
+pub mod check;
+pub mod parse;
+pub mod sign;
+pub mod structs;
diff --git a/rust/apps/zcash/src/pczt/parse.rs b/rust/apps/zcash/src/pczt/parse.rs
new file mode 100644
index 000000000..3f003c998
--- /dev/null
+++ b/rust/apps/zcash/src/pczt/parse.rs
@@ -0,0 +1,656 @@
+use alloc::{
+ format,
+ string::{String, ToString},
+ vec,
+};
+use zcash_note_encryption::{
+ try_output_recovery_with_ovk, try_output_recovery_with_pkd_esk, Domain,
+};
+use zcash_vendor::{
+ orchard::{
+ self, keys::OutgoingViewingKey, note::Note, note_encryption::OrchardDomain, Address,
+ },
+ pczt::{self, roles::verifier::Verifier, sapling, Pczt},
+ ripemd::{Digest, Ripemd160},
+ sha2::Sha256,
+ transparent::{self, address::TransparentAddress},
+ zcash_address::{
+ unified::{self, Encoding, Receiver},
+ ToAddress, ZcashAddress,
+ },
+ zcash_keys::keys::UnifiedFullViewingKey,
+ zcash_protocol::{
+ consensus::{self},
+ value::ZatBalance,
+ },
+};
+
+use crate::errors::ZcashError;
+
+use super::structs::{ParsedFrom, ParsedOrchard, ParsedPczt, ParsedTo, ParsedTransparent};
+
+const ZEC_DIVIDER: u32 = 1_000_000_00;
+
+fn format_zec_value(value: f64) -> String {
+ let zec_value = format!("{:.8}", value as f64 / ZEC_DIVIDER as f64);
+ let zec_value = zec_value
+ .trim_end_matches('0')
+ .trim_end_matches('.')
+ .to_string();
+ format!("{} ZEC", zec_value)
+}
+
+/// Attempts to decrypt the output with the given `ovk`, or (if `None`) directly via the
+/// PCZT's fields.
+///
+/// Returns:
+/// - `Ok(Some(_))` if the output can be decrypted.
+/// - `Ok(None)` if the output cannot be decrypted.
+/// - `Err(_)` if `ovk` is `None` and the PCZT is missing fields needed to directly
+/// decrypt the output.
+pub fn decode_output_enc_ciphertext(
+ action: &orchard::pczt::Action,
+ ovk: Option<&OutgoingViewingKey>,
+) -> Result | | |