From a6b07bdc3db07a906e6707236f82c846c1d32da7 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 14 Oct 2020 18:38:13 -0700 Subject: [PATCH] client: further work on client RFC Co-authored-by: Deirdre Connolly --- book/src/dev/rfcs/xxxx-zebra-client.md | 184 +++++++++++++++++++------ 1 file changed, 142 insertions(+), 42 deletions(-) diff --git a/book/src/dev/rfcs/xxxx-zebra-client.md b/book/src/dev/rfcs/xxxx-zebra-client.md index 450dd1f60..a52d36ab5 100644 --- a/book/src/dev/rfcs/xxxx-zebra-client.md +++ b/book/src/dev/rfcs/xxxx-zebra-client.md @@ -6,50 +6,136 @@ # Summary [summary]: #summary -Handling blockchain scanning in subtasks via a zebra-client component in zebrad, and -a wallet component in zebra-cli to query that component for wallet balances and to construct -transactions and send them out via zebrad. +The `zebra-client` crate handles *client functionality*. Client functionality +is defined as all functionality related to a particular user's private data, +in contrast to the other full node functionality which handles public chain +state. This includes: + +- note and key management; +- transaction generation; +- a client component for `zebrad` that handles block chain scanning, with +appropriate side-channel protections; +- an RPC endpoint for `zebrad` that allows access to the client component; +- a `zebracli` binary that wraps basic wallet functionality and RPC queries in a command-line interface. + +Client functionality is restricted to transparent and Sapling shielded +transactions; Sprout shielded transactions are not supported. (Users should +migrate to Sapling). # Motivation [motivation]: #motivation -We want to send money via Zebra efficiently and securely. +We want to allow users to efficiently and securely send and receive funds via +Zebra. One challenge unique to Zcash is block chain scanning: because +shielded transactions reveal no metadata about the sender or receiver, users +must scan the block chain for relevant transactions using *viewing keys*. +This means that unlike a transparent blockchain with public transactions, a +full node must have online access to viewing keys to scan the chain. This +creates the risk of a privacy leak, because the node should not reveal which +viewing keys it has access to. + +Block chain scanning requires a mechanism that allows users to manage and +store key material. This mechanism should also provide basic wallet +functionality, so that users can send and receive funds without requiring +third-party software. + +To protect user privacy, this and all secret-dependent functionality should +be strongly isolated from the rest of the node implementation. Care should be +taken to protect against side channels that could reveal information about +viewing keys. To make this isolation easier, all secret-dependent +functionality is provided only by the `zebra-client` crate. # Definitions [definitions]: #definitions +- **client functionality**: all functionality related to a particular user's +private data, in contrast to other full node functionality which handles +public chain state. + +- **block chain scanning**: the process of scanning the block chain for +relevant transactions using a viewing key, as described in [§4.19][ps_scan] +of the protocol specification. + +- **viewing key**: Sapling shielded addresses support *viewing keys*, which +represent the capability to decrypt transactions, as described in +[§3.1][ps_keys] and [§4.2.2][ps_sapk] of the protocol specification. + +- **task**: In this document, *task* refers specifically to a [Tokio +task][tokio-task]. In brief, a task is a light weight, non-blocking unit of +execution (green thread), similar to a Goroutine or Erlang process. Tasks +execute independently and are scheduled co-operatively using explicit yield +points. Tasks are executed on the Tokio runtime, which can either be single- +or multi-threaded. + +[ps_scan]: https://zips.z.cash/protocol/canopy.pdf#saplingscan +[ps_keys]: https://zips.z.cash/protocol/canopy.pdf#addressesandkeys +[ps_sapk]: https://zips.z.cash/protocol/canopy.pdf#saplingkeycomponents +[tokio-task]: https://docs.rs/tokio/0.2.22/tokio/task/index.html # Guide-level explanation [guide-level-explanation]: #guide-level-explanation - +There are two main parts of this functionality. The first is a `Client` +component running as part of `zebrad`, and the second is a `zebracli` +command-line tool. - - - - - +The `Client` component is responsible for blockchain scanning. It maintains +its own distinct `sled` database, which stores the viewing keys it uses to +scan as well as the results of scanning. When a new block is added to the +chain state, the `Client` component is notified asynchronously using a +channel. For each Sapling shielded transaction in the block, the component +attempts to perform trial decryption of that transaction's notes using each +registered viewing key, as described in [§4.19][ps_scan]. If successful, +decrypted notes are saved to the database. - +The [`PING`/`REJECT`][pingreject] attack demonstrates the importance of +decoupling execution of normal node operations from secret-dependent +operations. Zebra's network stack already makes it immune to those particular +attacks, because each peer connection is executed in a different task. +However, to eliminate this entire class of vulnerability, we execute the +`Client` component in its own task, decoupled from the rest of the node +functionality. In fact, each viewing key's scanning is performed +independently, as described in more detail below, with an analysis of +potential side-channels. -zebra-client -- client component -- (does: key access, blockchain scanning) -- (has a whole separate sled DB for ’users’s txs, keys, etc) -- (keeps track of where it’s scanned to) -- (can be executed in its own tokio subtask to isolate from timing) -- (has access to notifs from zebra-state about new blocks etc) -- (lives as a subtask of zebrad) -- zebra-cli talks to this subcomponent which is in a running zebrad -- (the scanning executes independently (but in the same process) of the normal node operation) -- (zebra-client, in side zebrad, runs in its own separate task, in case it crashes, it’s not noticeable) -zebra-cli -- (can use servo/bincode + servo/ipc-channel to communicate with zebrad) -- (separate processes) +[pingreject]: https://eprint.iacr.org/2020/220.pdf + +The second part is the `zebracli` command-line tool, which provides basic +wallet functionality. This tool manages spending keys and addresses, and +communicates with the `Client` component in `zebrad` to provide basic wallet +functionality. Specifically, `zebracli` uses a distinct RPC endpoint to load +viewing keys into `zebrad` and to query the results of block chain scanning. +`zebracli` can then use the results of those queries to generate transactions +and submit them to the network using `zebrad`. + +This design upholds the principle of least authority by separating key +material required for spending funds from the key material required for block +chain scanning. This allows compartmentalization. For instance, a user could +in principle run `zebrad` on a cloud VPS with only their viewing keys and +store their spending keys on a laptop, or a user could run `zebrad` on a +local machine and store their spending keys in a hardware wallet. Both of +these use cases would require some additional tooling support, but are +possible with this design. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation + +zebra-client +- client component + - (keeps track of where it’s scanned to) + - (zebra-client, in side zebrad, runs in its own separate task, in case it crashes, it’s not noticeable) + - (the scanning executes independently (but in the same process) of the normal node operation) +- zebra-cli talks to this subcomponent which is in a running zebrad + - (can use servo/bincode + servo/ipc-channel to communicate with zebrad) + +## Task isolation in Tokio + +- cooperative multitasking is fine, IF you cooperate +- lots of tasks + + + @@ -90,7 +176,10 @@ zebra-client inside zebrad via an RPC method any/or a private IPC layer) -Supporting a wallet assumes risk. +Supporting a wallet assumes risk. Effort required to implement wallet functionality. + +- need to responsibly handle secret key material; +- currently we only handle public data. # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives @@ -99,24 +188,20 @@ Supporting a wallet assumes risk. -> What is the impact of not doing this? -We can't send money with zebra alone. +- why have a separate RPC endpoint? + - extra endpoints are cheap + - allows segmentation by capability + - alternative is error-prone after-the-fact ACLs like Tor control port filters -# Prior art -[prior-art]: #prior-art +- What is the impact of not doing this? + - We can't send money with zebra alone. + - rely on third party wallet software to send funds with zebra + - we need to provide basic functionality within zebra's trust boundary, rather than forcing users to additionally trust 3p software + - there are great 3p wallets, we want to integrate with them, just don't want to rely on them - - - - - - - - - - - -. +- light client protocol + - does not address this use case, has different trust model (private lookup, no scanning) + - # Unresolved questions [unresolved-questions]: #unresolved-questions @@ -125,9 +210,24 @@ We can't send money with zebra alone. +- wait to fill this in until doing the detailed writeup. + # Future possibilities [future-possibilities]: #future-possibilities +- split `Client` component into subprocess + - this helps somewhat but the benefit is reduced by memory safety + - not meaningful without other isolation (need to restrict `zebrad` from accessing viewing keys on disk, etc) + +- hardware wallet integration for `zebracli` + - having `zebracli` allows us to do this + - much higher security ROI than subprocess + - very cool future feature + +- authenticate queries for a particular viewing key by proving knowledge of +the viewing key (requires crypto). this could allow public access to the +client endpoint +