zcash-devtool Tutorial

This tutorial explaining how to use FROST to sign a Zcash transaction using zcash-devtool.

Setting up

Install cargo and git.

Install the zcash-devtool:

cargo install --git https://github.com/zcash/zcash-devtool.git --locked

Install the frost-client tool:

cargo install --git https://github.com/ZcashFoundation/frost-zcash-demo.git --locked frost-client

Install the zcash-sign tool:

cargo install --git https://github.com/ZcashFoundation/frost-zcash-demo.git --locked zcash-sign

Switch to an empty folder which will store the files generated in the demo. For example:

mkdir frost-demo
cd frost-demo/

Running the server

This demo uses the ZF FROST server (frostd) to help participants communicate. While in practice users would use an existing online server, for the demo you can run a local server by following these instructions (the "Compiling, Running and Deploying" and "Local Testing" sections).

The rest of the tutorial assumes the server is up and running.

Initializing the users

Run the following command to initialize three users (in practice, each user would run a similar command, but for demo purposes we're assuming you will simulate all of them in the same machine, so run these commands in your machine):

frost-client init -c alice.toml
frost-client init -c bob.toml
frost-client init -c eve.toml

This will create a config file for three users; Alice, Bob and Eve.

Note

If you really want to run the demo in separate machines, then you can omit the -c alice.toml part of the command (i.e. run frost-client init); it will save to a default location in the user's home directory.

Generating FROST key shares

First we will generate the FROST key shares. For simplicity we'll use trusted dealer; if you want to use Distributed Key Generation, skip to the next section.

In a new terminal (in case the previous terminal is running the server), run the following:

frost-client trusted-dealer -d "Alice, Bob and Eve's group" --names Alice,Bob,Eve -c alice.toml -c bob.toml -c eve.toml -C redpallas

This will by default generate a 2-of-3 key shares. The key shares will be written into each participant's config file. You can change the threhsold, number of shares and file names using the command line; append -h to the commend above for the command line help.

Generating FROST key shares using DKG

For real-word usage we commend generating key shares using Distributed Key Generation. If you did the previous section, skip to "Generating the Full Viewing Key for the wallet".

Note

This section assumes each participant is running the commands in their own machine. If you want to simulate all of them in a single machine, specify the config file for the user (e.g. -c alice.toml) accordingly.

Initializing config files

If they haven't yet, each participant should run:

frost-client init

Sharing contacts

Each participant must now generate a contact string that they will need to share with the other participants. This contact string will include a name, which they can choose when exporting and will be shown to whoever they send the contact to.

Run the following, substituting the name accordingly:

frost-client export --name 'Alice'

The command will print an encoded contact string such as zffrost1qyqq2stvd93k2g84hudcr98zp67a9rnx9v00euw9e5424hjathvre7ymy344fynjdvxmwxfg. Send it to the other participants using some trusted communication channel (instant messaging, etc.).

The other participants will send you their contacts. Import them by running the following command for each contact (replace <contact-string> with the contact string accordingly):

frost-client import <contact-string>

Generating shares

Finally, to generate the shares, one of the participants will need to initiate the process. They will need to public key of each participant, so they need to first list them with the following command:

frost-client contacts

Then run the following command, replacing the <pubkey1> and <pubkey2> hex strings with the public keys of the contacts which will participate (along with the user running the command):

frost-client dkg -d "Alice, Bob and Eve's group" -s localhost:2744 -S <pubkey1>,<pubkey2> -t 2 -C redpallas -c alice.toml

The user should then notify the others that a signing session has started (e.g. via instant messaging again), and also share the threshold number that was used. They should then run the following, replacing the name of the group if they wish and the threshold number with the one given by the first participant.

frost-client dkg -d "Alice, Bob and Eve's group" -s localhost:2744 -t 2 -C redpallas

Note

A future version might not require specifying the threshold and group name.

Generating the Full Viewing Key for the wallet

Next, we will need to generate a Zcash Full Viewing Key from the FROST group material we have just generated; this address will then be imported into a wallet so that we'll be able to create Zcash transactions for it.

Run the following command:

frost-client groups

It will list all groups you're in - at this point it should list the only one you have just created. Copy the Public Key it shows (it will look like e.g. 79d6bcee79c88ad9ba259067772b97f5de12f1435b474d03bc98f255be08a610)

The run the following command, replacing <ak> with the value you copied, and test with main if you're using Mainnet.

zcash-sign generate --net test --ak <ak>

It will print an Orchard address, and a Unified Full Viewing Key. Copy and paste both somewhere to use them later.

Importing the Full Viewing Key into zcash-devtool

In the zcash-devtool folder, run the following, replacing <UFVK> with the UFVK printed in the last step:

zcash-devtool wallet -w ./.frost.view/ init-fvk --name FROST_wallet --fvk <UFVK> --birthday 3720000 -s zecrocks

(Change ./.frost-view or FROST_wallet if you want to change the folder or name of the wallet.)

Funding the wallet

Now you will need to fund this wallet with some ZEC. Send ZEC to that address using another account (or try ZecFaucet).

Creating the transaction

Run the following, replacing <DEST_ADDR> with the address you want to ZEC to, <VALUE> with the value you want to send in Zatoshis, <MEMO> with the memo you want to send:

zcash-devtool pczt -w ./.frost.view/ create  --address <DEST_ADDR> --value <VALUE> --memo <MEMO> > frost_pczt.created

Signing the transaction

Now you will need to simulate two participants and a Coordinator to sign the transaction, and you should still have the FROST server running which will handle communications between them. It's probably easier to open three new terminals.

Go back to the signer terminal and run the following, replacing <pczt_path> with the path to the file you saved in the previous step, and <pczt_signed_path> with the path where you want to write the signed transaction (e.g. frost_pczt.signed).

zcash-sign sign -n test --tx-plan frost_pczt.created  -o frost_pczt.signed

(Replace test with main if you're using Mainnet.)

The program will print a SIGHASH and a Randomizer, and will prompt for a signature. This is what you will get after running FROST, so let's do that; leave the prompt there without typing anything.

Coordinator

In the second terminal, the Coordinator, run (in the same folder where you initialized the users and ran the key generation) the following:

frost-client groups -c alice.toml

This will list the groups Alice is in; it should only list the one you created earlier. You will need to copy some values in the command. Run the following, replacing the value after <group> with the "Public key" listed for the group; replacing <pubkey1> and <pubkey2> with the public keys of Alice and Bob (the hexadecimal values printed next to their names; Alice's name will be empty to indicate it's her own).

frost-client coordinator -c alice.toml --server-url localhost:2744 --group <group> -S <pubkey1>,<pubkey2> -m - -r -

It will prompt you for a message. Paste the SIGHASH generated with the zcash-sign tool and press enter. It will then prompt for a randomizer. Paste the one generated with the zcash-sign tool and press enter.

The tool will connect to the server and wait for the other participants.

Warning

If you prefer to pass the message (SIGHASH) or randomizer as files by using the -m and -r arguments, you will need to convert them to binary format.

Participant 1 (Alice)

In the third terminal, Participant 1, run the following (replacing <group> with the same group public key used in the previous command):

frost-client participant -c alice.toml --server-url localhost:2744 --group <group>

(We are using "Alice" again. There's nothing stopping a Coordinator from being a Partcipant too!)

Participant 2 (Bob)

In the fourth terminal, for Participant 2, run the following (replacing <group> again):

frost-client participant -c bob.toml --server-url localhost:2744 --group <group>

Coordinator

Go back to the Coordinator CLI. The protocol should run and complete successfully. It will print the final FROST-generated signature. Hurrah! Copy it (just the hex value).

Go back to the signer and paste the signature. It will write the signed transaction to the file you specified.

Proving the transaction

You will need to prove the transaction separately:

cargo run -p zcash-sign -- sign -n test --tx-plan frost_pczt.created  -o frost_pczt.signed

And then combine signed and proven into a final transaction:

zcash-devtool pczt combine -i frost_pczt.signed -i frost_pczt.proven > frost_pczt.combined

Broadcasting the transaction

Run:

zcash-devtool pczt -w ./.frost.view/ send -s zecrocks < test_pczt.combined