How to use Signatory with a Tezos Baker
A Tezos node can be installed from binaries, or run with docker, or built from sources (for details see here) . In each case a baker is set up with a network and a vault, but each vault has unique requirements. This diagram shows the range of configurations supported by Signatory. There are 3x3x6=54
variations shown, and more are possible. This article will introduce baking and test networks but will focus on the configration details required for baking with each supported vault type.
Bakers on Tezos Networks
Things you will need to know:
- a working octez-client instance
- the host_address for a Tezos Node`
- in this example we will host a node locally at
http://localhost:8732
- in this example we will host a node locally at
- a public_key_hash to be the baker
- e.g.
tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU
- e.g.
- the protocol running on the network used
- e.g.
PtMumbai
- e.g.
Verify the node:
curl ${host_address}/chains/main/is_bootstrapped
List known addresses :
./octez-client list known addresses
alice: tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU (unencrypted sk known)
Show the baker address and secret key:
./octez-client show address -S alice
Hash: tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU
Public Key: edpktmKfj5reMbPmgwh2BNw5EHYpHEZZceMWfffcEpfPTn6pXgoRwF
Secret Key: unencrypted:edsk2hf8Y9oYMQ9MiEAH9pbs3H7tpcBbyxjcWuRjJCrGPB81bDHC7s
Ensure minimum required balance for baking rights. To get funds, use the faucets. This has to wait util bootstrapping is complete.
./octez-client get balance for alice
Register the implict account as a delegate. We can use a consensus key as well:
./octez-client register key alice as delegate
./octez-client register alice as delegate with consensus key bob
Check for baking rights. Depending on the network used this can take days. You will need to guess at the cycle parameter.
./octez-client rpc get /chains/main/blocks/head/helpers/baking_rights?cycle=<cycle>&delegate=${public_key_hash}
To start the baker :
./octez-baker-alpha run with local node ~/.tezos-node --liquidity-baking-toggle-vote pass
Signatory
Clone Signatory from its Github repository or run with docker .
git clone <https://github.com/daily-co/signatory.git>
Build Signatory:
cd signatory
make signatory
make signatory-cli
1. Local Secret
This is not a secure method of key storage but it is the simplest example. Create a file /etc/secret.json and populate it with the PKH and secret key for the baker
[
{
"name": "tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU",
"value": "unencrypted:edsk2hf8Y9oYMQ9MiEAH9pbs3H7tpcBbyxjcWuRjJCrGPB81bDHC7s"
}
]
Create a local_secret.yaml
file with the following content.
server:
address: :6732
utility_address: :9583
vaults:
local_secret:
driver: file
config:
file: /etc/secret.json
tezos:
tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU:
log_payloads: true
allowed_operations:
- generic
- block
- endorsement
- preendorsement
allowed_kinds:
- reveal
- delegation
Start Signatory :
./signatory serve -c ./signatory.yaml
Test that Signatory is working :
curl localhost:6732/keys/tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU
{"public_key":"edpktmKfj5reMbPmgwh2BNw5EHYpHEZZceMWfffcEpfPTn6pXgoRwF"}
./signatory-cli list -c local_secret.yaml
INFO[0000] Initializing vault vault=file vault_name=local_secret
Public Key Hash: tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU
Vault: File
ID: tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU
Active: false
Import the key Signatory provides into octez-client, overriding the key alice created earlier.
./octez-client import secret key alice http://localhost:6732/tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU --force
Check the tezos node secret key file:
cat ~/.tezos-client/secret_keys
[{ "name": "alice",
"value": "http://localhost:6732/tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU"
}]
Do a tezos transfer operation:
./octez-client transfer 10 from alice to bob
and check the signatory logs
INFO[0006] Requesting signing operation ops="map[transaction:1]" ops_total=1 pkh=tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU request=generic vault=File vault_name=local_secret
INFO[0006] About to sign raw bytes ops="map[transaction:1]" ops_total=1 pkh=tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU raw=034266bedbf77c4e104790c8c3e7ca81cef9aa2f63770ae27d9032c670902f03e76c00fa8d929d0a3eb3a509e16bd6aec74e6c18783432e102fd13e9070080ade20400005cf5b8fb0209b20765b88233de1700896d4d084a00 request=generic vault=File vault_name=local_secret
INFO[0006] Signed generic successfully ops="map[transaction:1]" ops_total=1 pkh=tz1iUqDimrzPmYuWbmLgWwX73YF7dBcaJryU request=generic vault=File vault_name=local_secret
2. Ledger Devices
Make sure that the ledger device is able to work with your linux system and is enabled through udev rules. Some examples can be found here
Make sure that tezos client can access the ledger:
./octez-client list connected ledgers
## Ledger `elated-beaver-unusual-nightingale`
Found a Tezos Baking 2.3.2 (git-description: "") application running on
Ledger Nano S at [0001:0029:00].
To use keys at BIP32 path m/44'/1729'/0'/0' (default Tezos key path), use one
of:
octez-client import secret key ledger_michael "ledger://elated-beaver-unusual-nightingale/bip25519/0h/0h"
octez-client import secret key ledger_michael "ledger://elated-beaver-unusual-nightingale/ed25519/0h/0h"
octez-client import secret key ledger_michael "ledger://elated-beaver-unusual-nightingale/secp256k1/0h/0h"
octez-client import secret key ledger_michael "ledger://elated-beaver-unusual-nightingale/P-256/0h/0h"
Use the appropriate import command for the elliptic curve you plan to use to get the ledger keys into octez-client
./octez-client import secret key ledger_michael "ledger://elated-beaver-unusual-nightingale/bip25519/0h/0h"
Please validate (and write down) the public key hash displayed on the Ledger,
it should be equal
to `tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt`:
Tezos address added: tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt
Review the Request on the ledger device and approve it.
Ensure the implicit account used has funds for a baking stake. (Use the faucet)
Set up ledger for baking
./signatory-cli ledger setup-baking bip25519/0h/0h -c signatory.yaml
INFO[0000] Initializing vault
vault=ledger vault_name=ledger
Authorized baking for address: tz1Kiak7gwhv6fvcpq9Q9ghjKNuFNYDtUJUG
Determine the ID of the ledger device.
./signatory-cli ledger list -c signatory.yaml
Path: 0001:0029:00
ID: elated-beaver-unusual-nightingale / 00f24232
Version: TezBake 2.3.2
The ID is used by the signatory.yaml file to identify the ledger
Set up the Signatory configuration file like this, and save it a ledger.yaml
:
server:
address: :6732
utility_address: :9583
vaults:
ledger:
driver: ledger
config:
id: 00f24232
keys:
- "bip32-ed25519/0'/0'"
- "secp256k1/0'/1'"
close_after: 600800s
tezos:
tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt:
log_payloads: true
allow:
generic:
- transaction
- endorsement
- proposals
block:
endorsement:
preendorsement:
where we have added the Ledger ID and the ledger's public key hash that we imported to octez-client.
Start signatory from the CLI or with Docker:
./signatory-cli ledger setup-baking ed25519/0h/0h -c sig-ledger.yaml --base-dir .
Review and permit the request on the ledger device.
Get the public key hash from the ledger device
```bash!
./signatory-cli list -c ledger.yaml
INFO[0000] Initializing vault vault=ledger vault_name=ledger
Public Key Hash: tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt
Vault: Ledger
ID: bip32-ed25519/44'/1729'/0'/0'
Active: true
Allowed Requests: [block endorsement generic preendorsement]
Allowed Operations: [endorsement proposals transaction]
Check the logs for the baker to see that endorsing is working
Mar 22 12:09:44.815 - 016-PtMumbai.baker.actions: injected preendorsement op8Pj4ot1oZ3YmmUhxeTKiH83SUazCVDVgZzqgKb1DKj68vr8a1
Mar 22 12:09:44.815 - 016-PtMumbai.baker.actions: for blueledger (tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt)
Mar 22 12:09:46.596 - 016-PtMumbai.baker.actions: injected endorsement ooee4W7k4oNSLRZu62aZQwhkahmWRngbEnJZ5CopsXGantGemzd for
Mar 22 12:09:46.596 - 016-PtMumbai.baker.actions: blueledger (tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt)
See the endorsing in the Signatory logs:
INFO[1910525] Requesting signing operation chain_id=NetXQw6nWSnrJ5t lvl=457542 pkh=tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt request=preendorsement vault=Ledger vault_name=00f24232
INFO[1910525] About to sign raw bytes chain_id=NetXQw6nWSnrJ5t lvl=457542 pkh=tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt raw=122f6cbd6119f3a10704d101a5d13334809adce2e9d3011c6cead4b975a8d39f91c87273e714001e0006fb4600000082c6194912098ea5a9a7d52a593e4783afb36f3965780b242eb1e271c1159cc946 request=preendorsement vault=Ledger vault_name=00f24232
INFO[1910527] Signed preendorsement successfully chain_id=NetXQw6nWSnrJ5t lvl=457542 pkh=tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt request=preendorsement vault=Ledger vault_name=00f24232
INFO[1910527] POST /keys/tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt duration=1.772184564s hostname="localhost:6732" method=POST path=/keys/tz1bQYMFieZHomNPjJvpp2g7PuhxRPDxpnFt start_time="2023-03-08T10:26:30-08:00" status=200
3. Yubi HSM
Follow the Signatory Vault installation instructions for Yubi HSM at https://signatory.io/docs/yubihsm
Signatory will expose the key in the vault to the baker. The set up of keys and bakers is the same as for the simpler examples above. The baker needs to be setup for baking with the key as supplied by Signatory.
server:
address: localhost:6732
utility_address: localhost:9583
vaults:
yubi:
driver: yubihsm
config:
address: localhost:12345 # Address for the yubihsm-connector
password: password
auth_key_id: 1
tezos:
tz3fK7rVYSg2HTEAmUYdfjJWSDGfsKrxH3xQ:
log_payloads: true
allow:
block:
endorsement:
preendorsement:
generic:
- transaction
With Baker, Signatory and Yubi set up you should see in the yubi logs:
INFO[0668] handled request Content-Length=13 Content-Type=application/octet-stream Method=POST RemoteAddr="127.0.0.1:38524" StatusCode=200 URI=/connector/api User-Agent=Go-http-client/1.1 X-Real-IP=127.0.0.1 X-Request-ID=74d3cc1b-6f8b-4e73-afdd-25af90054a32 latency=10.879542ms
DEBU[0668] usb device already open Correlation-ID=e08fb56a-deac-4d28-8069-39b41b7f6892
DEBU[0668] usb endpoint write Correlation-ID=e08fb56a-deac-4d28-8069-39b41b7f6892 buf="[4 0 17 2 199 78 161 173 85 75 86 143 162 70 155 208 62 14 98 48]" err="<nil>" len=20 n=20
DEBU[0668] usb endpoint read Correlation-ID=e08fb56a-deac-4d28-8069-39b41b7f6892 buf="[132 0 0]" err="<nil>" len=3 n=3
4. AWS KMS
Follow the Signatory Vault installation instructions for AWS KMS at https://signatory.io/docs/aws_kms
- AWS KMS needs programmatic access
Signatory will expose the key in the vault to the baker. The set up of keys and bakers is the same as for the simpler examples above. The baker needs to be setup for baking with the key that was created using the cryptographic curve histed by AWS KMS. Signatory will expose this key and apply policy to operations.
server:
address: :6732
utility_address: :9583
vaults:
aws:
driver: awskms
config:
user_name: <iam_username>
access_key_id: <aws_access_key_id>
secret_access_key: <aws_secret_access_key>
region: <aws_region>
tezos:
tz2KtieusLufPkLEEocrr2etP4rb1QR3k8ri:
log_payloads: true
allow:
block:
endorsement:
preendorsement:
generic:
- transaction
Here tz2KtieusLufPkLEEocrr2etP4rb1QR3k8ri
is the key returned by Signatory when you run ./signatory-cli list -c awskms.yaml
.
The vault should be active when listed:
./signatory-cli list -c awskms.yaml
INFO[0000] Initializing vault vault=awskms vault_name=aws
Public Key Hash: tz2KtieusLufPkLEEocrr2etP4rb1QR3k8ri
Vault: AWSKMS
ID: arn:aws:kms:us-east-1:757500755852:key/60d6c5f2-1824-4ee8-af3d-5bbc462e1875
Active: true
Allowed Requests: [block endorsement generic preendorsement]
Allowed Operations: [endorsement proposals transaction]
To manage baking with this key using octez-client you can import the key:
./octez-client import secret key awskms http://localhost:6732/tz2KtieusLufPkLEEocrr2etP4rb1QR3k8ri
5. GCPKeyManagement
Follow the Signatory Vault installation instructions for GCPKeyManagement at https://signatory.io/docs/gcp_kms
Signatory will expose the key in the vault to the baker. The set up of keys and bakers is the same as for the simpler examples above. The baker needs to be setup for baking with the key as supplied by Signatory.
server:
address: :6732
utility_address: :9583
vaults:
gcp:
driver: cloudkms
config:
project: <gcp_project>
location: <gcp_region>
key_ring: <key_ring_name>
application_credentials: <credentials_file_path>
tezos:
tz2PgBeeL6ddBuejPDs26iYExRchEn3K6ZXp:
log_payloads: true
allow:
block:
endorsement:
preendorsement:
generic:
- transaction
Here tz2PgBeeL6ddBuejPDs26iYExRchEn3K6ZXp
is the key returned by Signatory when you run ./signatory-cli list -c google.yaml
.
The vault should be active when listed:
./signatory-cli list -c google.yaml
INFO[0000] Initializing vault vault=cloudkms vault_name=gcp
Public Key Hash: tz2PgBeeL6ddBuejPDs26iYExRchEn3K6ZXp
Vault: CloudKMS
ID: projects/signatory-testing/locations/northamerica-northeast2/keyRings/googlebaker/cryptoKeys/baker/cryptoKeyVersions/1
Active: true
Allowed Requests: [block endorsement generic preendorsement]
Allowed Operations: [transaction]
To manage baking with this key using octez-client you can import the key:
./octez-client import secret key gcpkms http://localhost:6732/tz2PgBeeL6ddBuejPDs26iYExRchEn3K6ZXp
6. Azure Key Vault
Follow the Signatory Vault installation instructions for Azure Key Vault at https://signatory.io/docs/azure_kms
Signatory will expose the key in the vault to the baker. The set up of keys and bakers is the same as for the simpler examples above. The baker needs to be setup for baking with the key as supplied by Signatory.
server:
address: :6732
utility_address: :9583
vaults:
azure:
driver: azure
config:
vault: https://sigy.vault.azure.net/
tenant_id: 50a7adf11-1a9a-4b76-b468-1acdb03a8f69e
client_id: b673iu8cc5-98c9-44ac-a688-7cafcdb9b9bcb4
client_private_key: service-principal.key
client_certificate_thumbprint: 643F14403B695090D8ABDC34ABBE7EF2423497352
subscription_id: be223726da0-6dc1-4cdc-ab26-15a082bdaaa908
resource_group: sigy
tezos:
tz3d6nYmR1LmSDsgJ463Kgd8EbH53pYnuv8S:
log_payloads: true
allow:
block:
endorsement:
preendorsement:
generic:
- transaction
- reveal
- delegation