This repository contains Ledger application to support baking on Tezos blockchain , i.e. signing new blocks and pre-attestations and attestations. For more information about baking, see Benefits and Risks of Home Baking.
It is possible to do all of these things without a hardware wallet, but using a hardware wallet provides you better security against key theft.
Install tezos-baking
app from Ledger-live. You may have to enable developer mode to see tezos-baking in the available apps list.
You also will need to install tezos-wallet
app for initial setup to stake tez for baking.
- Initialize your ledger device with your secret phrase and PIN and
- Install
tezos-baking
andtezos-wallet
apps.
- Setup ledger for baking using instructions given in this file in section Baking upto Staking tez.
- Exit the Tezos wallet app.
IMPORTANT
Make sure toenable screensaver
anddisable global PIN lock
in ledger settings.- Open the baking app and start baking with octez client.
Disabling global PIN lock makes it possible for baking app to continue respond to signing requests even when screensaver is running on the screen of the ledger. Baking app uses Ledger screensaver (custom screensaver for nanos) to avoid screen burn.
The baking app once opened can not be exited until you enter PIN again so disabling global PIN lock while baking does not pose any risk.
Caution
Make sure that a dedicated Ledger device is used for baking and not to leave any other app open in screensaver mode while global PIN lock is disabled.
To avoid double baking, double attestation and double pre-attestation, the application maintains a high water mark (HWM) corresponding to the last level/round encountered during signature requests. The HWMs are displayed on the home screen and are updated after each signature.
For performance reasons, the HWM screen is not updated dynamically. On Nano devices, press both buttons to update.
To make sure HWM values are preserved after a reboot/power_off, the HWM values are saved in non-volatile memory(NVRAM) on ledger device.
Previously baking_app
would store every new value to NVRAM, thus causing NVRAM burn. NVRAM has limited number of write cycles after which it stops working.
Therefore, in the new baking_app
we have added a setting to disable HWM. By default it is enabled.
When HWM setting is disabled, the HWM will be updated in RAM instead of NVRAM on every signing operation (Block/pre-attestation/attestation). Only when you exit the app properly by clicking Quit
, will the latest HWM value be written to NVRAM.
To disable HWM,
1. Go to settings
2. On the screeen High Watermark, press both buttons to toggle HWM to Disabled.
We request every user of baking_app
to disable HWM setting so that they dont experience NVRAM burn. For additional safety from double baking the users can use octez-signer
instead of octez-client
. Octez-signer has inherent HWM tracking and double baking protection.
Even when HWM is disabled, the baking_app
keeps track of HWM in RAM thus in normal operation of the app, the user is protected from double baking. Only when you reboot/power_off the device abruptly, you have to take extra care to make sure you dont double bake. You can achieve this either using octez-signer or reset HWM to the block level/round you have not signed yet.
The screen saver is the one provided by Ledger (Configure screen saver timeout).
On Nanos devices, the Ledger screensaver can slow down the baking app. This is why it is deactivated during signings. After a signature, a low-cost screensaver will take over. It will switch the screen off after 20 seconds of inactivity. Press any button to exit sleep mode. When the sleep mode is exited, the Ledger screen saver will take over again if there are no more signatures.
See CONTRIBUTING.md
You need to set udev
rules to set the permissions so that your user account
can access the Ledger device. This requires system administration privileges
on your Linux system.
LedgerHQ provides a script for this purpose. Download this script, read it, customize it, and run it as root:
$ wget https://raw.githubusercontent.com/LedgerHQ/udev-rules/master/add_udev_rules.sh
$ chmod +x add_udev_rules.sh
We recommend against running the next command without reviewing the script and modifying it to match your configuration.
$ sudo ./add_udev_rules.sh
Subsequently, unplug your ledger hardware wallet, and plug it in again for the changes to take effect.
For NixOS, you can set the udev rules by adding the following to the NixOS
configuration file typically located at /etc/nixos/configuration.nix
:
hardware.ledger.enable = true;
Once you have added this, run sudo nixos-rebuild switch
to activate the
configuration, and unplug your Ledger device and plug it in again for the changes to
take effect.
The easiest way to obtain and install the Tezos Ledger apps is to download them from Ledger Live. Tezos Baking is available when you enable 'Developer Mode' in Settings.
If you've used Ledger Live for application installation, you can skip the following section.
Download the source code for application from github repository App-tezos-baking.
$ git clone https://github.com/trilitech/ledger-app-tezos-baking.git
$ cd ledger-app-tezos-baking
Then run the following command to enter into docker container provided by Ledger. You will need to have docker cli installed.
Use the docker container ledger-app-dev-tools
provided by Ledger to build the app.
docker run --rm -ti -v $(pwd):/app ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest
Then build the baking app inside the docker container shell as follows :
BOLOS_SDK=$NANOS_SDK make
To enable debugging and log output, use
BOLOS_SDK=$NANOS_SDK make DEBUG=1
You can replace NANOS
with NANOSP
, NANOX
, STAX
, FLEX
for the other devices in BOLOS_SDK environmental variable.
The application tests are run using same docker container used for building. Inside the docker container run following script,
$ apk add gmp-dev libsodium-dev;
$ python3 -m venv tezos_test_env --system-site-package;
$ source ./tezos_test_env/bin/activate;
(tezos_test_env)$ python3 -m pip install -r test/requirements.txt -q ;
Now you can run ragger tests for any perticular ledger device. Please make sure you have built the app.elf files for that perticular device first. Then run following command:
(tezos_test_env)$ python3 -m pytest test --device nanosp
Replace nanosp with any of the following for respective device: nanos, nanosp, nanox , stax , flex.
These tests are run on Ledger emulator called speculos which emulates the actual ledger device. To run theese test on actual device you have to choose a backend. Run following commands to run these test on device:
(tezos_test_env)$ python3 -m pip install ragger[all_backends]
(tezos_test_env)$ python3 -m pytest test --device nanosp --backend ledgercomm -s
Note the -s
flag which is required when running interactive tests with pytest. You can also choose ledgerwallet
backend to run tests on device.
Manually installing the apps requires a command-line tool called LedgerBlue
Install libusb
and libudev
, with the relevant headers. On Debian-based
distros, including Ubuntu, the packages with the headers are suffixed with
-dev
. Other distros will have their own conventions. So, for example, on
Ubuntu, you can do this with:
$ sudo apt-get install libusb-1.0.0-dev libudev-dev # Ubuntu example
Then, you must enter the env
. If you do not successfully enter the env
,
future commands will fail. You can tell you have entered the virtualenv when your prompt is
prefixed with (ledger)
. Use the following command to enter env
.
$ source env/bin/activate
Your terminal session -- and only that terminal session -- will now be in the
virtual env. To have a new terminal session enter the virtualenv, run the above
source
command only in the same directory in the new terminal session.
We can now install ledgerblue
, which is a Python module designed originally for
Ledger Blue, but also is needed for the Ledger Nano S/X.
$ python3 -m pip install ledgerblue
Python package. This will install the Ledger Python packages into the virtualenv; they will be available only in a shell where the virtualenv has been activated.
If you have to use sudo
or pip3
here, that is an indication that you have
not correctly set up virtualenv
. It will still work in such a situation, but
please research other material on troubleshooting virtualenv
setup.
Next you'll use the installation script to install the application on your Ledger device.
The Ledger device must be in the following state:
- Plugged into your computer
- Unlocked (enter your PIN)
- On the home screen (do not have any application open)
- Not asleep (you should not see Ledger screensaver across the screen)
If you are already in an application or the Ledger device is asleep, your installation process will fail.
We recommend staying at your computer and keeping an eye on the Ledger device's screen as you continue. You may want to read the rest of these instructions before you begin installing, as you will need to confirm and verify a few things during the process.
Make sure you have built the appropriate device files by following the 'Building' section. We will be using the app.apdu
and app.elf
from build/<device>
directory. Here <device>
can take values nanos, nanos2 (for Nanosp), nanox, stax and flex.
$ python3 -m ledgerblue.runScript --scp --fileName build/<device>/bin/app.apdu --elfFile build/<device>/bin/app.elf
The first thing that should come up in your terminal is a message that looks like this:
Generated random root public key : <long string of digits and letters>
Look at your Ledger device's screen and verify that the digits of that key match the digits you can see on your terminal. What you see on your Ledger hardware wallet's screen should be just the beginning and ending few characters of the longer string that printed in your terminal.
You will need to push confirmation buttons on your Ledger device a few times during the installation process and re-enter your PIN code near the end of the process. You should finally see the Tezos logo appear on the screen.
If you see the "Generated random root public key" message and then something that looks like this:
Traceback (most recent call last):
File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
<...more file names...>
OSError: open failed
the most likely cause is that your udev
rules are not set up correctly, or you
did not unplug your Ledger hardware wallet between setting up the rules and attempting to
install. Please confirm the correctness of your udev
rules.
To load a new version of the Tezos application onto the Ledger device in the future, you can run the command again, and it will automatically remove any previously-loaded version.
If you'd like to remove your app, you can do this. In the virtualenv described in the last sections, run this command:
$ python -m ledgerblue.deleteApp --targetId 0x31100004 --appName 'Tezos Baking'
Replace the appName
parameter "Tezos" with whatever application name you used when you loaded the application onto the device.
Then follow the prompts on the Ledger device screen.
You should now have Tezos Baking
app installed on the device. The Tezos Baking
application should display a 0
under screen on the screen ,Highest Watermark
which is the highest block level baked so far (0
in case of no blocks).
The Tezos Baking Application supports the following operations:
- Get public key
- Setup ledger for baking
- Reset high watermark
- Get high watermark
- Sign (blocks and attestations)
It will only sign block headers and attestations, as the purpose of the baking application is that it cannot be co-opted to perform other types of operations (like transferring XTZ). If a Ledger device is running with the Tezos Baking Application, it is the expectation of its owner that no transactions will need to be signed with it. To sign transactions with that Ledger device, you will need to switch it to using the Tezos Wallet application, or have the Tezos Wallet application installed on a paired device. Therefore, if you have a larger stake and bake frequently, we recommend the paired device approach. If, however, you bake infrequently and can afford to have your baker offline temporarily, then switching to the Tezos Wallet application on the same Ledger device should suffice.
To connect ledger with Tezos client, you need to download Tezos. You need to have nix installed on your system. Build tezos with following commands:
$ git clone https://gitlab.com/tezos/tezos.git
$ cd tezos
$ nix-shell -j auto
$ make
This will build the latest version of tezos repo. Now connect the ledger device to USB port of your computer and run following command:
$ ./octez-client list connected ledgger
It will given output as follows:
## Ledger `masculine-pig-stupendous-dugong`
Found a Tezos Baking 2.4.7 (git-description: "v2.4.7-70-g3195b4d2")
application running on Ledger Nano S Plus at [1-1.4.6:1.0].
To use keys at BIP32 path m/44'/1729'/0'/0' (default Tezos key path), use one
of:
octez-client import secret key ledger_username "ledger://masculine-pig-stupendous-dugong/ed25519/0h/0h"
octez-client import secret key ledger_username "ledger://masculine-pig-stupendous-dugong/secp256k1/0h/0h"
octez-client import secret key ledger_username "ledger://masculine-pig-stupendous-dugong/P-256/0h/0h"
octez-client import secret key ledger_username "ledger://masculine-pig-stupendous-dugong/bip25519/0h/0h"
Here the last four lines give information about the available keys you can use to sign blocks/attestations etc. in baking. The names in front of ledger:// are generated randomly and represent a unique path to key derivations in ledger. Choose one of the keys listed above as follows:
$ ./octez-client import secret key ledger_username "ledger://masculine-pig-stupendous-dugong/bip25519/0h/0h"
Here we have chosen the last key type bip25519. You can choose any one of the available keys.
You can verify that you have successfully setup ledger with following command:
$ ./octez-client list known addresses
It will show output as follows:
ledger_<...>: tz1N4GQ8gYgMdq6gUsja783KJButHUHn5K7z (ledger sk known)
You can use the address ledger_<...> for further commands to setup the baking operations with Ledger.
It is recommended to practice baking on tezos testnet before you acutally start baking on mainnet with real money. You can get more information about baking on testnet at Baking-setup-Tutorial. Here we only give information about changes you have to make in above tutorial to bake with Ledger instead of an auto generated key.
In the tutorial skip the command octez-client gen keys my_baker
and instead use the ledger_<...> in place of my_baker.
Use the following command to store your address in environmental variable MY_BAKER
$ MY_BAKER="$(./octez-client show address ledger_<...> | head -n 1 | cut -d ' ' -f 2)"
You need to run a specific command to authorize a key for baking. Once a key is authorized for baking, the user will not have to approve this command again. If a key is not authorized for baking, signing attestations and block headers with that key will be rejected. This authorization data is persisted across runs of the application, but not across application installations. Only one key can be authorized for baking per Ledger hardware wallet at a time.
In order to authorize a public key for baking, use the APDU for setting up the ledger device to bake:
```
$ octez-client setup ledger to bake for ledger_<...>
```
This only authorizes the key for baking on the Ledger device, but does
not inform the blockchain of your intention to bake. This might
be necessary if you reinstall the app, or if you have a different
paired Ledger device that you are using to bake for the first time.
Note: The ledger device will not sign this operation unless you have already setup the device to bake using the command in the previous section.
In order to bake from the Ledger device account you need to register the key as a delegate. This is formally done by delegating the account to itself. As a non-originated account, an account directly stored on the Ledger device can only delegate to itself.
Open the Tezos Baking Application on the device, and then run this:
$ octez-client register key ledger_<...> as delegate
This command is intended to inform the blockchain itself of your intention to bake with this key.
To sign transactions involving exchange of tez you need tezos-wallet app. You need to stake certain amount of tez to get baking rights. Install Tezos wallet app on the same ledger device and run following command. No setup is needed as we have already setup the address from which we are deducting the amount.
$ octez-client stake <amount> ledger_<...>
The sign operation is for signing block headers and attestations.
Block headers must have monotonically increasing levels; that is, each block must have a higher level than all previous blocks signed with the Ledger device. This is intended to prevent double baking and double attesting at the device level, as a security measure against potential vulnerabilities where the computer might be tricked into double baking. This feature will hopefully be a redundant precaution, but it's implemented at the device level because the point of the Ledger hardware wallet is to not trust the computer. The current High Watermark (HWM) -- the highest level to have been baked so far -- is displayed on the device's screen, and is also persisted between runs of the device.
The sign operation will be sent to the hardware wallet by the baking daemon when configured to bake with a Ledger device key. The Ledger device uses the first byte of the information to be signed -- the magic number -- to tell whether it is a block header (which is verified with the High Watermark), an attestation (which is not), or some other operation (which it will reject, unless it is a self-delegation).
With the exception of self-delegations, as long as the key is configured and the high watermark constraint is followed, there is no user prompting required for signing. Tezos Baking will only ever sign without prompting or reject an attempt at signing; this operation is designed to be used unsupervised. As mentioned, the only exception to this is self-delegation.
The Tezos-Baking app needs to be kept open during baking and ledger is unlocked during that time. To prevent screen burn, the baking app goes into blank screen when it starts signing blocks/attestation as baker. But the app remains unlocked. One can not sign any transaction operation using baking app, therefore there is no need of any concern. But to exit the baking app, one needs to enter PIN. This restriction is in place to avoid misuse of physical ledger device when its kept unattended during baking process.
When updating the version of Tezos Baking you are using or if you are switching baking to a new ledger device, we recommend setting the HWM to the current head block level of the blockchain. This can be accomplished with the reset command. The following command requires an explicit confirmation from the user:
$ octez-client set ledger high watermark for "ledger://<tz...>/" to <HWM>
<HWM>
indicates the new high watermark to reset to. Both the main and test chain HWMs will be
simultaneously changed to this value.
If you would like to know the current high watermark of the ledger device, you can run:
$ octez-client get ledger high watermark for "ledger://<tz...>/"
While the ledger device's UI displays the HWM of the main chain it is signing on, it will not display the HWM of a test chain it may be signing on during the 3rd period of the Tezos Amendment Process. Running this command will return both HWMs as well as the chain ID of the main chain.
When you want to upgrade to a new version, whether you built it yourself from source
or whether it's a new release of the app.hex
files, use the same commands as you did
to originally install it. As the keys are generated from the device's seeds and the
derivation paths, you will have the same keys with every version of this Ledger hardware wallet app,
so there is no need to re-import the keys with octez-client
. You may need to run command octez-client setup ledger to bake for ...
again as HWM and chain information would be erased after reinstalling the app.
If you've already been baking on an old version of Tezos Baking, the new version will not remember which key you are baking with nor the High Watermark. You will have to re-run this command to remind the hardware wallet what key you intend to authorize for baking. As shown, it can also set the HWM:
$ octez-client setup ledger to bake for ledger_<...> --main-hwm <HWM>
Alternatively, you can also set the High Watermark to the level of the most recently baked block with a separate command:
$ octez-client set ledger high watermark for "ledger://<tz...>/" to <HWM>
The latter will require the correct URL for the Ledger device acquired from:
$ octez-client list connected ledgers
The time taken to sign attestations/pre-attestations for baking app can depend on the device used, derivation type etc.
To benchmark signing time on a ledger device, run following commands: (assuming you have completed all the steps in section Loading the app on device and Testing.)
(env)$ pip install ragger[all_backends] # Requirement for testing with device.
Now run either of the following commands
(env)$ python3 -m pytest test --device nanos --backend ledgercomm -k "test_benchmark_attestation_time"
or
(env)$ python3 -m pytest test --device nanos --backend ledgerwallet -k "test_benchmark_attestation_time"
The result will be printed in Avg_time_for_100_attestations.txt
.
Following is a sample of measurements obtained with this app (Tezos Baking app v2.4.7, Ledger devices - Nanos, Nanos+, System : Ubunut 22.04)
Device | Derivation Type | Avg time/signature(milliseconds) |
---|---|---|
Flex | SECP256K1_tz2 | 214 |
Flex | SECP256R1_tz3 | 215 |
Flex | ED25519_tz1 | 456 |
Flex | BIP32_ED25519_tz1 | 783 |
Nanos+ | SECP256K1_tz2 | 229 |
Nanos+ | SECP256R1_tz3 | 226 |
Nanos+ | ED25519_tz1 | 465 |
Nanos+ | BIP32_ED25519_tz1 | 787 |
Nanos | SECP256K1_tz2 | 876 |
Nanos | SECP256R1_tz3 | 670 |
Nanos | ED25519_tz1 | 670 |
Nanos | BIP32_ED25519_tz1 | 878 |
To debug the application you need to compile the application with DEBUG=1
You currently cannot directly import a fundraiser account to the Ledger device. Instead, you'll first need to import your fundraiser account to a non-hardware wallet address from which you can send the funds to an address on the ledger. You can do so with wallet providers such as Galleon or TezBox.
Two Ledger devices with the same seed should not ever be plugged in at the same time. This confuses
octez-client
and other client programs. Instead, you should plug only one of a set of paired
ledgers at a time. Two Ledger devices of different seeds are fine and are fully supported,
and the computer will automatically determine which one to send information to.
If you have one running the baking app, it is bad for security to also have the wallet app plugged in simultaneously. Plug the wallet application in as-needed, removing the baking app, at a time when you are not going to be needed for attestation or baking. Alternatively, use a different computer for wallet transactions.
$ octez-client list connected ledgers
Fatal error: Header.check: unexpected seq num
This means you do not have the Tezos application open on your device.
$ octez-client list connected ledgers
No device found.
Make sure a Ledger device is connected and in the Tezos Wallet app.
In addition to the possibilities listed in the error message, this could also mean that your udev rules are not set up correctly.
If you see an Unrecognized command
error, it might be because there is no node for octez-client
to connect to. Please ensure that you are running a node. ps aux | grep tezos-node
should display
the process information for the current node. If it displays nothing, or just displays a grep
command, then there is no node running on your machine.
If octez-client
on macOS intermittently fails with an error that looks like
client.signer.ledger: APDU level error: Unexpected sequence number (expected 0, got 191)
then your installation of octez-client
was built with an older version of HIDAPI that doesn't work well with macOS (see #30).
To fix this you need to get the yet-unreleased fixes from the HIDAPI library and rebuild octez-client
.
If you got HIDAPI from Homebrew, you can update to the master
branch of HIDAPI like this:
$ brew install hidapi --HEAD
Then start a full rebuild of octez-client
with HIDAPI's master
branch:
$ brew unlink hidapi # remove the current one
$ brew install autoconf automake libtool # Just keep installing stuff until the following command succeeds:
$ brew install hidapi --HEAD
Finally, rebuild ocaml-hidapi
with Tezos. In the tezos
repository:
$ opam reinstall hidapi
$ make all build-test
$ ./octez-client list connected ledgers # should now work consistently
Note that you may still see warnings similar to Unexpected sequence number (expected 0, got 191)
even after this update. The reason is that there is a separate, more cosmetic, issue in octez-client
itself which has already been fixed but may not be in your branch yet (see the merge request).
If you install a Ledger application, such as Tezos Wallet or Tezos Baking, outside of Ledger Live you will see the message "This app is not genuine" followed by an Indentifier when opening the app. This message is generated by the device firmware as a warning to the user whenever an application is installed outside Ledger Live. Ledger signs the applications available in Ledger Live to verify their authenticity, but the same applications available elsewhere, such as from this repo, are not signed by Ledger. As a result, the user is warned that the app is not "genuine", i.e. signed by Ledger. This helps protect users who may have accidentally downloaded an app from a malicious client without knowing it. Note that the application available from this repo's releases page is otherwise no different from the one downloaded from Ledger Live.
To give feedback and report an error, create an issue on github repository Trillitech-App-Tezos.