client: further work on client RFC

Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>
This commit is contained in:
Henry de Valence 2020-10-14 18:38:13 -07:00 committed by Deirdre Connolly
parent 69a8107c86
commit a6b07bdc3d
1 changed files with 142 additions and 42 deletions

View File

@ -6,50 +6,136 @@
# Summary # Summary
[summary]: #summary [summary]: #summary
Handling blockchain scanning in subtasks via a zebra-client component in zebrad, and The `zebra-client` crate handles *client functionality*. Client functionality
a wallet component in zebra-cli to query that component for wallet balances and to construct is defined as all functionality related to a particular user's private data,
transactions and send them out via zebrad. 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]: #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]: #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]: #guide-level-explanation [guide-level-explanation]: #guide-level-explanation
<!-- Explain the proposal as if it was already included in the project and you were teaching it to another Zebra programmer. That generally means: --> 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.
<!-- - Introducing new named concepts. --> The `Client` component is responsible for blockchain scanning. It maintains
<!-- - Explaining the feature largely in terms of examples. --> its own distinct `sled` database, which stores the viewing keys it uses to
<!-- - Explaining how Zebra programmers should *think* about the feature, and how it should impact the way they use Zebra. It should explain the impact as concretely as possible. --> scan as well as the results of scanning. When a new block is added to the
<!-- - If applicable, provide sample error messages, deprecation warnings, migration guidance, or test strategies. --> chain state, the `Client` component is notified asynchronously using a
<!-- - If applicable, describe the differences between teaching this to existing Zebra programmers and new Zebra programmers. --> 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.
<!-- For implementation-oriented RFCs (e.g. for Zebra internals), this section should focus on how Zebra contributors should think about the change, and give examples of its concrete impact. For policy RFCs, this section should provide an example-driven introduction to the policy, and explain its impact in concrete terms. --> 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 [pingreject]: https://eprint.iacr.org/2020/220.pdf
- client component
- (does: key access, blockchain scanning) The second part is the `zebracli` command-line tool, which provides basic
- (has a whole separate sled DB for userss txs, keys, etc) wallet functionality. This tool manages spending keys and addresses, and
- (keeps track of where its scanned to) communicates with the `Client` component in `zebrad` to provide basic wallet
- (can be executed in its own tokio subtask to isolate from timing) functionality. Specifically, `zebracli` uses a distinct RPC endpoint to load
- (has access to notifs from zebra-state about new blocks etc) viewing keys into `zebrad` and to query the results of block chain scanning.
- (lives as a subtask of zebrad) `zebracli` can then use the results of those queries to generate transactions
- zebra-cli talks to this subcomponent which is in a running zebrad and submit them to the network using `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, its not noticeable) This design upholds the principle of least authority by separating key
zebra-cli material required for spending funds from the key material required for block
- (can use servo/bincode + servo/ipc-channel to communicate with zebrad) chain scanning. This allows compartmentalization. For instance, a user could
- (separate processes) 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]: #reference-level-explanation [reference-level-explanation]: #reference-level-explanation
zebra-client
- client component
- (keeps track of where its scanned to)
- (zebra-client, in side zebrad, runs in its own separate task, in case it crashes, its 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
<!-- This is the technical portion of the RFC. Explain the design in sufficient detail that: --> <!-- This is the technical portion of the RFC. Explain the design in sufficient detail that: -->
<!-- - Its interaction with other features is clear. --> <!-- - Its interaction with other features is clear. -->
@ -90,7 +176,10 @@ zebra-client inside zebrad via an RPC method any/or a private IPC layer)
<!-- Why should we *not* do this?--> <!-- Why should we *not* do this?-->
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]: #rationale-and-alternatives [rationale-and-alternatives]: #rationale-and-alternatives
@ -99,24 +188,20 @@ Supporting a wallet assumes risk.
<!-- - Is this design a good basis for later designs or implementations? --> <!-- - Is this design a good basis for later designs or implementations? -->
<!-- - What other designs have been considered and what is the rationale for not choosing them? --> <!-- - What other designs have been considered and what is the rationale for not choosing them? -->
> What is the impact of not doing this? - why have a separate RPC endpoint?
We can't send money with zebra alone. - extra endpoints are cheap
- allows segmentation by capability
- alternative is error-prone after-the-fact ACLs like Tor control port filters
# Prior art - What is the impact of not doing this?
[prior-art]: #prior-art - 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
<!-- Discuss prior art, both the good and the bad, in relation to this proposal. --> - light client protocol
<!-- A few examples of what this can include are: --> - does not address this use case, has different trust model (private lookup, no scanning)
-
<!-- - For community proposals: Is this done by some other community and what were their experiences with it? -->
<!-- - For other teams: What lessons can we learn from what other communities have done here? -->
<!-- - Papers: Are there any published papers or great posts that discuss this? If you have some relevant papers to refer to, this can serve as a more detailed theoretical background. -->
<!-- This section is intended to encourage you as an author to think about the lessons from other projects, to provide readers of your RFC with a fuller picture. -->
<!-- If there is no prior art, that is fine - your ideas are interesting to us whether they are brand new or if they are an adaptation from other projects. -->
<!-- Note that while precedent set by other projects is some motivation, it does not on its own motivate an RFC. -->
<!-- Please also take into consideration that Zebra sometimes intentionally diverges from common Zcash features and designs -->.
# Unresolved questions # Unresolved questions
[unresolved-questions]: #unresolved-questions [unresolved-questions]: #unresolved-questions
@ -125,9 +210,24 @@ We can't send money with zebra alone.
<!-- - What parts of the design do you expect to resolve through the implementation of this feature before stabilization? --> <!-- - What parts of the design do you expect to resolve through the implementation of this feature before stabilization? -->
<!-- - What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC? --> <!-- - What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC? -->
- wait to fill this in until doing the detailed writeup.
# Future possibilities # Future possibilities
[future-possibilities]: #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
<!-- Think about what the natural extension and evolution of your proposal would --> <!-- Think about what the natural extension and evolution of your proposal would -->
<!-- be and how it would affect Zebra and Zcash as a whole. Try to use this --> <!-- be and how it would affect Zebra and Zcash as a whole. Try to use this -->
<!-- section as a tool to more fully consider all possible --> <!-- section as a tool to more fully consider all possible -->