Blog

/

Zcash integration Guide

Zcash integration Guide

December 12, 2024

10 min read

Security


The new Zcash Shielded App is now available, but Ledger support is limited to a ZecWallet fork by Zondax.This guide details steps to integrate Ledger into wallets like Ledger Live, Zingo, YWallet, Zashi etc.

For devs, how to integrate Zcash Shielded app into your wallet

Intro


  • The new Zcash Shielded Application has become officially available to the public recently.

  • While numerous wallets support Zcash, currently, there is no support for Ledger devices for this new app besides the development ZecWallet fork from zondax

  • This article provides a comprehensive overview of the essential steps required to integrate support for the Ledger Zcash Shielded App into your wallet.

  • This initiative is expected to benefit a wide range of wallets including Ledger Live, Zingo, YWallet, Zashi, Flexa, Nighthawk, Unstoppable etc.

First thing first


In order to integrate the Ledger Zcash Shielded application into your wallet there aren’t magical recipes but we’ll make an exhaustive list of all the available resources and some general guidelines to achieve this.

You’ll need to establish communication with the device. To achieve this, Zondax provides 2 communication packages:

Those packages provide the abstraction for establishing communication with your device, using a protocol called APDU (the same protocol as SIM cards). This implies that the zcash application running on the ledger device cannot initiate communication but just respond to commands.

To get the updated list of commands that the app will understand, you can check it on the APDU spec documentation

You have one extra thing to have in consideration when working with Ledger devices: private keys / highly sensitive information won’t be shared with any external party. This means that the different keys that are part of either Transparent/Sapling protocols will be computed and used on the device. You won’t have direct access to them. This means that any signing process or revealing information regarding shielded transactions must be done in the device itself.

Integrating Zcash Shielded app


Key management integration guidelines


In order to integrate our Ledger application, first you need to design a common interface that handles key management, which would provide access to view/public keys and also useful methods for signing transactions or any other operation that requires access to private keys. A common interface like this would be called a Keystore component that would integrate your current key management system in your wallet that generates keys probably in-memory, and the Ledger application.

The first step is to abstract both elements into one type that generalizes over methods for handling and using keys. In the case of Rust, it is suggested to use a sum type like Enum that holds both variants. You can check how this was implemented by Zondax in ZecWallet, where we added an enum type that abstracts the in-memory Keystore and the LedgerKeystore component while providing a common set of methods that the rest of your wallet would use for dealing with keys, either requesting view/public keys or signing transactions.

Keep in mind that the common interface must align with the security of the Ledger application, which will not allow any spending/private key to be sent out of the device. That means you cannot keep any sensitive information in-memory in your wallet implementation. If your current design relies on this, you must change it to align with this requirement.

At the moment, Zondax is collaborating with Zingolabs and Zashi to add support for the app. Even though the integration is not completed, you can check how the approach was there for Keystore abstraction and LedgerKeystore component.

Signing Integration guideline


This functionality must be centralized as well by the Keystore component. The reason is that as mentioned in the previous sections, private keys must not be kept in memory as the ledger application won't let them be moved out of the device. Because of this strong requirement, both keystore implementations must align in this regard. This implies that the common interface would provide a method for revealing/signing data using the private keys. For example in our ZecWallet integration, the Keystore integration provides methods for creating node commitments, signing transactions, and many more that require the usage of private keys.

You can see how we check for the current Keystore variant being used, and call the corresponding handler. It is important to mention that in the zecwallet integration, only one instance could be used at the time.

It is relevant to note that the ledger keystore component internally uses the ZcashApp abstraction provided by our ledger-zcash-rs library. The ZcashApp component provides a defined set of methods that at the moment we consider sufficient for transparent and sapling operations within zcash protocol. This means that the Orchard and unified addresses protocols are not supported yet. In the following section, we will describe some of the supported operations this component provides and how to use it for establishing communication with the device. A further list of available methods can be found in the source code here.

Basic commands


Before you can start sending commands to the app, you need to open the communication channel. This can be done using Ledger transport. This is just a generic interface for communicating with a Ledger hardware device. There are different kinds of transports based on the technology (channels like U2F, HID, Bluetooth, Webusb) and environment (Node, Web,...)

So.. let’s start with simple commands like or since they don’t need any additional parameters.

You can check some tests that will be really helpful examples:

Here you can see the rest of the examples for both Rust and Javascript.

Transparent Address


To get the transparent address from your device, you’ll need the command . It will need a derivation path. Keep in mind that this is an asynchronous operation and it might fail. This command and any other that doesn’t share sensitive information can be retrieved without explicit user confirmation.
Showing the address on the device is a really important confirmation step that the user needs to do before sharing an address. It would be good to add a button or some UI element to allow the user to verify that the wallet and the device show the same address.

Sapling keys


Within the Sapling upgrade in Zcash, there are several types of keys, each serving different purposes. These keys can be categorized into private and public keys:

Spending key: this would be like your private key and therefore will never be moved out of the device. Any operation that uses this key will be carried out within the device.

Viewing keys: even though these can be considered public keys, since they can be used to disclose sensitive information, they will need an explicit approval from the user to be shared with the wallet or any other party.

Nullifiers: in order to prevent double-spending, Zcash relies on nullifiers that are revealed and recorded in the blockchain when the tokens are spent. These will be needed by the wallets to keep the right balance from your account. Once again, an explicit approval from the user is necessary here.

Payment addresses: these addresses are are inherently public since the user creates them to shared with someone in order to get a payment. Having one of these addresses doesn't reveal the movements from any other payment address or any of the keys.

The Ledger application provides functionalities for retrieving Sapling public keys and addresses. Bellow a short example of the provided API in rust to get the incomming viewing key (IVK):

And the next code block demostrates how to use the ZcashApp interface for getting a shielded address from the device:

The device, as mentioned previously, features a limited UI that enables the review of transaction fields and relevant data. The user is required to confirm the accuracy of this data and approve the operation. This verification and approval process will be conducted by the user each time sensitive information needs to leave the device.

Transaction signing


This is one of the most important command that our communication interface provides. The overall idea is that the transaction data is sent serialized to the devices, users would them have to review the transaction and upon user confirmation, it would be signed. The returned data to the wallet would contain the signature. This is the general idea but to integrate the Zcash transaction signing feature of our Ledger application into your wallet, it's crucial to understand that the signing process is not straightforward, but rather interactive and step-by-step due to the cryptographic complexities involved, and the limited resources in terms of storage, memory and computing power from Ledger devices. Below you can see an overview of the process:

  1. Initialization: The process begins with gathering transaction input data, including transparent and shielded inputs and outputs. This would depend of the kind of transaction:

    • transparent->shielded

    • transparent->transparent

    • shielded->transparent

    • shielded->shielded transactions

  1. Building the Transaction:

    • Transparent Inputs: Add transparent inputs to the transaction builder without needing fresh information from the Ledger. This step requires the public key and outpoint from the blockchain.

    • Shielded Spends: For each shielded spend, the Ledger device provides the proof generation key, value commitment randomness (), and randomness for the random verification key (). This data is added to the transaction builder.

    • Shielded Outputs: Similar to shielded spends, adding shielded outputs requires randomness for the value commitment (), note commitment (), and random encryption key (), provided by the Ledger. This step is repeated for each shielded output.

  2. Finalizing the Transaction: Once all inputs and outputs are added, the transaction builder compiles the transaction, including Zero-Knowledge (ZK) proofs. This compiled transaction data () is then sent back to the Ledger for validation and signing.

  3. Extracting Signatures: The final step involves extracting signatures for both shielded spends and any transparent inputs from the Ledger. These signatures are then added to the transaction builder.

  4. Completion: With all signatures in place, the transaction builder finalizes the transaction, making it ready for broadcast to the Zcash network.

This interactive process ensures the security and integrity of the transaction by leveraging the Ledger's cryptographic capabilities. It's essential for wallet developers to implement this step-by-step approach to integrate Zcash transaction signing functionality successfully. For further details, you can look at our transaction builder component written in Rust, and some tests on how it is used to build a transactions. If you are integrating this Ledger application in , you can take a look at our tests that provides a good insight on how perform this interactive process.

Considerations



Generic communication package


The communication package is completely decoupled from any type used on ZecWallet or Zcash ecosystem. Therefore, it should fit well on any wallet or integration that wants to use it. This includes both Rust and Javascript/Typescript packages.

Documentation


The best place to find documentation about the app is located alongside with the app source code. You can find a mermaid diagram where the whole integration flow is explained clearly here. Besides, the APDU specification describes what each instruction is meant for, as well as expected input and output.

Useful test cases


The app counts with a wide set of test cases. Each of them is meant to verify a certain feature or instruction works as expected. They are extremely useful as a reference for full integration. You can find them here. Moreover, if you want to see how the review process in the ledger device would look like, you can check this folder. There are snapshots for each test case that is executed on CI using an emulator, called speculous.

Limitations


At the moment, there are some features that are not supported by the application and have to be considered when you plan to integrate this app in your wallet.

UTXO limitation


Due to the very limited resources from the device, the application can handle up to 5 transparent and 5 shielded inputs/outputs. If your transaction involves too many inputs/outputs, the device might not be able to handle it and it will be rejected every time.
At the moment, these values are fixed. So a transaction with 6 transparent inputs cannot be processed but a transaction with 5 transparent inputs, 5 shielded inputs, 5 transparent outputs and 5 shielded output would work just fine.

Unified address


After the activation from Network Upgrade 5 (NU5), the default address type is the Unified Address (UA). At the moment, the app is not able to generate these types of addresses, so you'll need to consider this while making the integration.

Orchard


Orchard protocol is not supported yet by the application. Consider that the application can only process Sapling transactions and you might need to adapt the wallet for it

Zondax zcash tools package


The zcash tools package is highly coupled with types that were used by ZecWallet. They are outdated, according to the latest version for zcash crates. As it is today, they are useful for implementation references for any wallet to incorporate support to the ledger app.


Read More


ETH Mexico 2024: A Night of Blockchain, Pizza, and Good Vibes

Teaming up with Filecoin Foundation, Zondax hosted an event as Orbit Ambassadors. 30+ attendees discussed Filecoin, Polkadot, Ledger, and the Mexican blockchain scene.


Unlocking Privacy: The New Zcash Shielded App for Ledger

The Zcash Shielded App, developed by Zondax, enables users to manage shielded transactions directly on Ledger devices, enhancing privacy and simplifying Zcash management.


Buenos Aires, Blockchain And Beers: An evening with Zondax and Filecoin Foundation

Zondax hosted a lively event in Buenos Aires, uniting blockchain communities over pizza, beer, and local treats, while showcasing Filecoin and Beryx.

Other Articles


6756fbab9b5f2900aab845c0

Security

December 12, 2024

Zcash integration Guide

The new Zcash Shielded App is now available, but Ledger support is limited to a ZecWallet fork by Zondax.This guide details steps to integrate Ledger into wallets like Ledger Live, Zingo, YWallet, Zashi etc.

6682f6679baa5800aa6ee776

Security

July 3, 2024

Ensuring a Smooth Transition: Using the Migration App for the Universal Polkadot Application

The new Polkadot app is here! Use the Migration App on Ledger to easily transfer your funds from your existing account to a new account with the updated Polkadot app.

678514d06dc6b200aabd5efa

Protocol

January 14, 2025

What Every Developer Needs to Know About Paseo Testnet

Paseo is the go-to testnet for Polkadot developers—offering a stable, community-driven space to test and refine projects. Zondax ensures seamless support and innovation.

Security

Ensuring a Smooth Transition: Using the Migration App for the Universal Polkadot Application

The new Polkadot app is here! Use the Migration App on Ledger to easily transfer your funds from your existing account to a new account with the updated Polkadot app.

6682f6679baa5800aa6ee776

Protocol

What Every Developer Needs to Know About Paseo Testnet

Paseo is the go-to testnet for Polkadot developers—offering a stable, community-driven space to test and refine projects. Zondax ensures seamless support and innovation.

678514d06dc6b200aabd5efa