book: add Zcash chapter (#505)

* book: add Zcash chapter

* Update book/src/zcash.md

Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com>

---------

Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com>
This commit is contained in:
Conrado Gouvea 2023-09-07 10:25:58 -03:00 committed by GitHub
parent 4ee0d32867
commit fcb25b2888
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 381 additions and 0 deletions

View File

@ -8,6 +8,9 @@
- [Signing](tutorial/signing.md)
- [Distributed Key Generation](tutorial/dkg.md)
- [User Documentation](user.md)
- [FROST with Zcash](zcash.md)
- [Technical Details](zcash/technical-details.md)
- [Ywallet Demo](zcash/ywallet-demo.md)
- [Terminology](terminology.md)
- [Developer Documentation](dev.md)
- [List of Dependencies for Audit](dev/frost-dependencies-for-audit.md)

View File

@ -0,0 +1 @@
# Technical Details

36
book/src/zcash.md Normal file
View File

@ -0,0 +1,36 @@
# FROST with Zcash
FROST can be used with the [Zcash](https://z.cash/) cryptocurrency, allowing
the creation of a wallet shared between multiple participants where multiple
participants must authorize a transaction before it can go through.
In a regular Zcash wallet, the spending key (commonly derived from a seed
phrase) allows freely spending from the wallet. If the key is lost or gets
hacked, then the wallet owner will lose access to their funds forever.
With FROST, only shares of the related spend authorization key will exist, between multiple
participants. During wallet creation, a threshold is set, and only that number of
participants (or more) can jointly create a transaction that spends funds from the wallet.
Some possible applications are:
- Creating a wallet that is shared between members of a organization that
manages certain funds. For example, a 3-of-5 wallet can be created which
will require 3 members to authorize spending the funds.
- Shared custody services can be created so that users can have their own wallet
and can spend their funds with the help of the service, and will not lose
access to the funds in case they lose the device with their key share. For
example, a 2-of-3 wallet where the user keeps one share, the service keeps
another, and the third share is backed up in the user's cloud.
FROST thus helps addressing one of the biggest challenges in cryptocurrencies,
which is the protecting the wallet key from either being accidentally lost or
being hacked. Before, users needed to choose to either manage their own funds
will puts a huge amount of responsibility on them and is well known to work
greatly in practice, or to leave their funds to be managed by some custody
service which is also known to be a risk. With FROST, users can share the
responsibility between multiple entities or persons (or even multiple devices
they own).
This section describes in more details how FROST can be used with Zcash.

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

View File

@ -0,0 +1,124 @@
# Technical Details
FROST only works with Schnorr signatures. Zcash transaprent transactions use
ECDSA, therefore FROST does not work with Zcash transaparent addresses. (This
could change if the Taproot upgrade from Bitcoin is ported to Zcash, but it
seems unlikely.)
Zcash supports three shielded pools: Sprout, Sapling and Orchard. Sprout
is being deprecated so we only need to care about Sapling and Orchard.
Sapling and Orchard keys are commonly derived from a single spending key (which
in turn is commonly derived from a seed phrase). This is shown in the figure
below, taken from the [Zcash
protocol](https://zips.z.cash/protocol/protocol.pdf#addressesandkeys):
![Sapling and Orchard key trees](key-trees.png)
To use FROST with Zcash, the key that needs to be split is the **Spend
Authorizing Key** or `ask`. This is the key that signs transactions and allow
they to go through.
## Key Derivation and DKG Support
As shown in the figure, the `ask` is commonly derived from the **Spending Key**
`sk`. At first, this could indicate that it is impossible to use Distributed Key
Generation (DKG) in this scenario, since the key it creates is unpredictable.
However, the protocol does not *require* `ask` to be derived from `sk`.
This would allow creating key shares using DKG, which will also output
`ak` (which is simply the public key matching `ask`). Thus:
- With Sapling, the rest of the keys can be derived from that `ak` and either:
- An `sk` which is used to derive only `nsk` and `ovk`;
- Or generating `nsk` and `ovk` by themselves (or generating them from a
random `sk` which is thrown away).
- With Orchard, the rest of the keys can be derived from that `ak` and either:
- An `sk` which is used to derive only `nk` and `rivk`;
- Or generating `nk` and `rivk` by themselves (or generating them from a
random `sk` which is thrown away).
Arguably this should be done even if Trusted Dealer Key Generation is used: the
goal of FROST is requiring multiple entities to authorize a transaction, not
having a seed phrase that allows recreating the `ask` ensures that property.
## Backing Up Key Shares
Zcash users are familiar with the concept of seed phrases and with how they
can always recover their wallet with it.
However, FROST wallets need more information to be restored:
- FROST-related:
- Key share
- Verifying shares of all participants
- Public keys and identifiers of all participants if online communication is
being used
- Zcash-related:
- Sapling: `sk`, or both Proof authorizing key (`ak` and `nsk`) and Outgoing
viewing key (`ovk`)
- Orchard: `sk`, or Full viewing key (`ak`, `nk`, `rivk`). The upside of using
the Full viewing key is that there is already a format for encoding it.
Thus, even if a `sk` derived from a seed phrase is used, that is not enough to
restore a FROST wallet. In fact it would be probably confusing to use a seed
phrase since users wouldn't be able to tell if it's a regular Zcash seed phrase
or a FROST seed phrase which needs additional information to be restored.
For this reason it seems impossible to easily encode a FROST wallet, so using
something like a JSON file with all this information is advisable.
Of course, unlike regular Zcash wallets, a user losing their FROST wallet is
not catastrophical. Users can recover their key share with the help of other
participants, and would only need to remember their identifier (and other
participants can probably help with that).
```admonish note
Orchard is simpler to handle, so it may be a good idea to just
support it with FROST.
```
```admonish note
The only secret information is the key share. So another possibility
is to just ask the user to backup it (using a seed phrase format, or other
string encoding) and get the remaining information from the other participants
when recovering a wallet.
```
## Communications
The biggest challenge in using FROST with Zcash is allowing participants to
communicate securely with each other, which is required to run the FROST
protocol. Since wallets don't currently need to communication to each other, a
whole new mechanism will need to be implemented.
For this to happen, two things are required:
- Allowing wallets to actually communicate with each other (regardless of
security). This is challenging because users are usually behind NATs and
firewalls, so they can't simply open TCP connections with each other. So
some kind of signaling server may be needed.
- Making the communication secure. This is actually fairly solvable while not
trivial and we're planning on working on a library to address it. It needs to
provide authentication and confidentiality, for example using the Noise
protocol. Also needs to provide a [broadcast
channel](https://frost.zfnd.org/terminology.html#broadcast-channel) on top of
it.
- Managing public keys. Another challenging part. Users need to be able to
create a key pair of keys used for the secure communication, and exporting
public keys to each other. This is similar to contact management that some
wallets have, so a possibility is to expand on that (instead of storing
just name and address, also store identifier and public key).
```info
One long-term idea is to extend the Zcash protocol to allow P2P messaging.
This has been discussed in the context of sending encrypted notes via the network
instead of publishing them on the blockchain.
```
```info
Another idea is to extend lightwalletd servers to support messaging, since
wallets are all already connected to a server (not the same one, so inter-server
communications would be also needed)
```

View File

@ -0,0 +1,217 @@
# Ywallet Demo Tutorial
This tutorial explaing how to run the FROST demo using Ywallet that was
[presented during Zcon4](https://www.youtube.com/watch?v=xvzESdDtczo).
Ywallet supports [offline
signing](https://ywallet.app/advanced/offline_signature/), which allows having a
view-only account that can generate a transaction plan, which can be signed by
a offline wallet also running Ywallet. The demo uses this mechanism but signs
the transaction plan with a command line tool, using FROST.
This tutorial assumes familiarity with the command line.
## Setting up
Install `cargo` and `git`.
[Install Ywallet](https://ywallet.app/installation/).
Clone the repositories:
```
git clone --branch add-redpallas https://github.com/ZcashFoundation/frost-zcash-demo.git
git clone --branch frost-demo https://github.com/ZcashFoundation/zwallet.git
```
## Generating FROST key shares
First we will generate the FROST key shares. For simplicity we'll use trusted
dealer, DKG will be described later.
Run the following (it will take a bit to compile):
```
cd frost-zcash-demo/
cargo run --bin trusted-dealer --features redpallas
```
Answer the prompts with `2` (minimum number of signers), `3`
(maximum) and empty, pressing enter to submit each.
A bunch of information will be printed. Copy and paste them somewhere to use
them later, or leave the terminal open.
```admonish info
If you want to use DKG instead of Trusted Dealer, instead of the command above,
run this for each participant, in separate terminals for each:
`cargo run --bin dkg --features redpallas`
and follow the instructions. (There will be a considerable amount of
copy&pasting!)
```
## Generating the Full Viewing Key for the wallet
In a new terminal, switch to the folder of the signer tool:
```
cd zwallet/native/zcash-sync/
```
Before running it, you will need to create a seed phrase which is used to
generate the Sapling address. This wouldn't be needed since the demo only works
with an Orchard address, but due to current limitations in the underlying
crates, we also need to generate a Sapling address which won't be used in the
demo. Generate a fresh 24-word seed phrase, for example using [this
site](https://iancoleman.io/bip39/) (reminder: don't use random sites to
generate seed phrases unless for testing purposes!), then write to a file called
`.env` in the signer folder in the following format, putting the seed phrase
inside the quotes:
```
KEY="seed phrase"
```
We can finally generate a new wallet. Run the following command; it will
take a bit to compile. It will show a bunch of warnings which is normal.
```
cargo build --release --bin sign --features dotenv -- -g
```
When prompted for the `ak`, paste the `group_public` value that was printed in
the previous part, inside the Public Key Package. For example, in the following
package
```
Public key package:
{"signer_pubkeys": ...snip... ,"group_public":"d2bf40ca860fb97e9d6d15d7d25e4f17d2e8ba5dd7069188cbf30b023910a71b","ciphersuite":"FROST(Pallas, BLAKE2b-512)"}
```
you would need to use
`d2bf40ca860fb97e9d6d15d7d25e4f17d2e8ba5dd7069188cbf30b023910a71b`. Press
enter to submit.
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 Ywallet
Open Ywallet and click "New account". Check "Restore an account" and
paste the Unified Full Viewing Key created in the previous step. Click
"Import".
In the "Rescan from..." window, pick today's date (since the wallet was just
created) and press OK. The wallet should open.
You will need to change some of Ywallet configurations. Click the three dots
at the top right and go to Settings. Switch to Advanced mode and click
OK. Go back to the Settings and uncheck "Use QR for offline signing".
## Funding the wallet
Now you will need to fund this wallet with some ZEC. Use the Orchard address
printed by the signer (see warning below). Send ZEC to that address using
another account (or try [ZecFaucet](https://zecfaucet.com/)). Wait until the
funds become spendable (this may take ~10 minutes). You can check if the funds
are spendable by clicking the arrow button and checking "Spendable Balance"
```admonish warning
The address being show by Ywallet is an unified address that includes both
an Orchard and Sapling address. For the demo to work, you need to receive funds
in you Orchard address. Whether that will happens depend on multiple factors
so it's probably easier to just use the Orchard-only address printed by the
signer.
```
## Creating the transaction
Now you will create the transaction that you wish to sign with FROST. Click
the arrow button and paste the destination address (send it to yourself if
you don't know where to send it). Type the amount you want to send and
click "Send".
The wallet will show the transaction plan. Click "Send". It won't actually
send - it will prompt you for where to save the transaction plan. Save it
somewhere.
## Signing the transaction
Go back to the signer terminal and run (adjust paths accordingly. The "tx.json"
input parameters must point to the file you save in the previous step, and the
"tx.raw" output parameter is where the signed transaction will be written).
```
cargo run --release --bin sign --features dotenv -- -t ~/Downloads/tx.json -o ~/Downloads/tx.raw
```
When prompted, paste the UFVK generated previously.
The program will print a SIGHASH and a Randomizer.
Now you will need to simulate two participants and a Coordinator to sign the
transaction. It's probably easier to open three terminals.
In the first one, the Coordinator, run (in the same folder where key
generation was run):
```
cargo run --bin coordinator --features redpallas
```
And then:
- Paste the JSON public key package generate during key generation (it's a single
line with a JSON object.
- Type `2` for the number of participants.
- Paste the identifier of the first participant, you can see it in the Secret
Share printed during key generation. If you used trusted dealer key
generation, it will be
`0100000000000000000000000000000000000000000000000000000000000000`.
- Paste the second identifier, e.g.
`0200000000000000000000000000000000000000000000000000000000000000`.
- When prompted for the message to be signed, paste the SIGHASH printed by the
signer above (just the hex value, e.g.
``4d065453cfa4cfb4f98dbc9cff60c4a3904ed91c523b8ef8d67d28bea7f12ea3``).
Create a new terminal, for participant 1, and run:
```
cargo run --bin participant --features redpallas
```
And then:
- Paste the Secret Share printed during key generation (or Key Package if you
used DKG).
- Copy the SigningCommitments line and paste into the Coordinator CLI.
Do the same for participant 2.
You should be at the Coordinator CLI. Paste the Randomizer generated by the
signer before and copy the Signing Package line that it was printed by the
Coordinator CLI before the Randomizer prompt.
Switch to participant 1 and:
- Paste the Signing Package
- Paste the Randomizer printed by the signer before.
- Copy the SignatureShare line and paste it into the Coordinator CLI.
Do the same for participant 2.
You should be at the Coordinator CLI. It has just printed 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 raw signed
transaction to the file you specified.
## Broadcasting the transaction
Go back to Ywallet and return to its main screen. In the menu, select "Advanced"
and "Broadcast". Select the raw signed transaction file you have just generated.
That's it! You just sent a FROST-signed Zcash transaction.