Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V5 transaction rfc #1886

Merged
merged 36 commits into from
Mar 25, 2021
Merged
Changes from 34 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4cba267
propose a v5 transaction rfc
oxarbitrage Mar 11, 2021
c304245
add rfc number, add design pr
oxarbitrage Mar 11, 2021
f456251
Apply suggestions from code review
oxarbitrage Mar 11, 2021
91e3378
define orchard flags
oxarbitrage Mar 13, 2021
717f40f
change some names for consistency
oxarbitrage Mar 13, 2021
239a8df
update orchard stuff
oxarbitrage Mar 13, 2021
e050176
Apply suggestions from code review
oxarbitrage Mar 15, 2021
aee8427
rename file
oxarbitrage Mar 15, 2021
84cfc44
Apply suggestions from code review
oxarbitrage Mar 15, 2021
f14ac65
Update test sections
oxarbitrage Mar 17, 2021
95cc691
Add security section
oxarbitrage Mar 18, 2021
447403c
change design to use enums
oxarbitrage Mar 18, 2021
efcc65b
move some code into sapling and orchard crates, do renames
oxarbitrage Mar 18, 2021
066ae59
Move a comment
teor2345 Mar 19, 2021
356881a
Delete unnecessary security fixes
teor2345 Mar 19, 2021
dbcf972
Fix whitespace
teor2345 Mar 19, 2021
9ff6db1
Move sapling value balance into shielded data
teor2345 Mar 19, 2021
4b47668
Add AuthorizedAction type
teor2345 Mar 19, 2021
40933f1
Improve formatting and consistency
teor2345 Mar 19, 2021
ae3b512
More module structure edits
teor2345 Mar 19, 2021
bf84852
Make enum variants more explicit
teor2345 Mar 19, 2021
dc81896
Make enum variants more explicit again
teor2345 Mar 19, 2021
b5af73d
Delete current code to avoid confusion
teor2345 Mar 19, 2021
6a5724b
Order fields based on last serialized data
teor2345 Mar 19, 2021
98ab9ed
Fix crossref name
teor2345 Mar 19, 2021
cc5d360
Add the proofsOrchard field
teor2345 Mar 19, 2021
884a074
Fix visibility
teor2345 Mar 19, 2021
f2a7ca4
Delete visibility modifiers for readability
teor2345 Mar 19, 2021
e765368
Model anchor variants as generic trait types
teor2345 Mar 19, 2021
2a12990
Minor cleanups
teor2345 Mar 19, 2021
708d15f
Be specific about the network upgrade
teor2345 Mar 19, 2021
c41d1fc
Rewrite guide-level explanation
teor2345 Mar 21, 2021
d973f5b
Tweak the AnchorVariant generic name
teor2345 Mar 21, 2021
8d7ea80
Specify a file for each new type
teor2345 Mar 22, 2021
f7a8c02
Document how the Orchard flags are used
teor2345 Mar 23, 2021
867c1cb
Fix: the proof verifies rules
teor2345 Mar 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
266 changes: 266 additions & 0 deletions book/src/dev/rfcs/0010-v5-transaction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
- Feature Name: `v5_transaction`
- Start Date: 2021-03-11
- Design PR: [ZcashFoundation/zebra#1886](https://github.com/ZcashFoundation/zebra/pull/1886)
- Zebra Issue: [ZcashFoundation/zebra#1863](https://github.com/ZcashFoundation/zebra/issues/1863)

# Summary
[summary]: #summary

Network Upgrade number 5 (`NU5`) introduces a new transaction type (transaction version 5). This document is a proposed design for implementing such a transaction version.

# Motivation
[motivation]: #motivation

The Zebra software wants to be a protocol compatible Zcash implementation. One of the tasks to do this includes the support of the new version 5 transactions that will be implemented in Network Upgrade 5 (NU5).

# Definitions
[definitions]: #definitions

- `NU5` - the 5th Zcash network upgrade, counting from the `Overwinter` upgrade as upgrade zero.
- `Orchard` - a new shielded pool introduced in `NU5`.
- `Sapling` - a new shielded pool introduced in the 1st network upgrade. (`Sapling` is also the name of that network upgrade, but this RFC is focused on the `Sapling` shielded pool.)
- `orchard data` - Data types needed to support orchard transactions.
- `sapling data` - Data types needed to support sapling transactions.
- `orchard transaction version` - Transactions that support orchard data. Currently only V5.
- `sapling transaction version` - Transactions that support sapling data. Currently V4 and V5 but the data is implemented differently in them.

# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation

V5 transactions are described by the protocol in the second table of [Transaction Encoding and Consensus](https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus).

All of the changes proposed in this document are only to the `zebra-chain` crate.

To highlight changes most of the document comments from the code snippets in the [reference section](#reference-level-explanation) were removed.

## Sapling Changes Overview
[sapling-changes-overview]: #sapling-changes-overview

V4 and V5 transactions both support sapling, but the underlying data structures are different. So need to make the sapling data types generic over the V4 and V5 structures.

In V4, anchors are per-spend, but in V5, they are per-transaction.

For consistency, also we move some fields into the `ShieldedData` type, and rename some fields and types.

## Orchard Additions Overview
[orchard-additions-overview]: #orchard-additions-overview

V5 transactions are the only ones that will support orchard transactions with `Orchard` data types.

Orchard uses `Halo2Proof`s with corresponding signature type changes. Each Orchard `Action` contains a spend and an output. Placeholder values are substituted for unused spends and outputs.

## Other Transaction V5 Changes
[other-transaction-v5-changes]: #other-transaction-v5-changes

The order of some of the fields changed from V4 to V5. For example the `lock_time` and `expiry_height` were moved above the transparent inputs and outputs.

Zebra enums and structs put fields in serialized order. Composite fields are ordered based on **last** data deserialized for each field.

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

## Sapling Changes
[sapling-changes]: #sapling-changes

We know by protocol (2nd table of [Transaction Encoding and Consensus](https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus)) that V5 transactions will support sapling data however we also know by protocol that spends ([Spend Description Encoding and Consensus](https://zips.z.cash/protocol/nu5.pdf#spendencodingandconsensus), See †) and outputs ([Output Description Encoding and Consensus](https://zips.z.cash/protocol/nu5.pdf#outputencodingandconsensus), See †) fields change from V4 to V5.

`ShieldedData` is currently defined and implemented in `zebra-chain/src/transaction/shielded_data.rs`. As this is Sapling specific we propose to move this file to `zebra-chain/src/sapling/shielded_data.rs`.

### Changes to V4 Transactions
[changes-to-v4-transactions]: #changes-to-v4-transactions

Here we have the proposed changes for V4 transactions:
* make `sapling_shielded_data` use the `PerSpendAnchor` anchor variant
* rename `shielded_data` to `sapling_shielded_data`
* move `value_balance` into the `sapling::ShieldedData` type
* order fields based on the **last** data deserialized for each field

```rust
enum Transaction::V4 {
inputs: Vec<transparent::Input>,
outputs: Vec<transparent::Output>,
lock_time: LockTime,
expiry_height: block::Height,
joinsplit_data: Option<JoinSplitData<Groth16Proof>>,
sapling_shielded_data: Option<sapling::ShieldedData<PerSpendAnchor>>,
}
```

### Anchor Variants
[anchor-variants]: #anchor-variants

We add an `AnchorVariant` generic type trait, because V4 transactions have a per-`Spend` anchor, but V5 transactions have a shared anchor. This trait can be added to `sapling/shielded_data.rs`:

teor2345 marked this conversation as resolved.
Show resolved Hide resolved
```rust
struct PerSpendAnchor {}
struct SharedAnchor {}

impl AnchorVariant for PerSpendAnchor {
type Shared = ();
type PerSpend = tree::Root;
}

impl AnchorVariant for SharedAnchor {
type Shared = tree::Root;
type PerSpend = ();
}

trait AnchorVariant {
type Shared;
type PerSpend;
}
```

### Changes to Sapling ShieldedData
[changes-to-sapling-shieldeddata]: #changes-to-sapling-shieldeddata

We use `AnchorVariant` in `ShieldedData` to model the anchor differences between V4 and V5:

```rust
struct sapling::ShieldedData<AnchorV: AnchorVariant> {
value_balance: Amount,
anchor: AnchorV::Shared,
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
first: Either<Spend<AnchorV>, Output>,
rest_spends: Vec<Spend<AnchorV>>,
rest_outputs: Vec<Output>,
binding_sig: Signature<Binding>,
}
```

### Adding V5 Sapling Spend
[adding-v5-sapling-spend]: #adding-v5-sapling-spend

Sapling spend code is located at `zebra-chain/src/sapling/spend.rs`. We use `AnchorVariant` to model the anchor differences between V4 and V5:

```rust
struct Spend<AnchorV: AnchorVariant> {
cv: commitment::ValueCommitment,
anchor: AnchorV::PerSpend,
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
nullifier: note::Nullifier,
rk: redjubjub::VerificationKeyBytes<SpendAuth>,
zkproof: Groth16Proof,
spend_auth_sig: redjubjub::Signature<SpendAuth>,
}
```

### No Changes to Sapling Output
[no-changes-to-sapling-output]: #no-changes-to-sapling-output

In Zcash the Sapling output representations are the same for V4 and V5 transactions, so no variants are needed. The output code is located at `zebra-chain/src/sapling/output.rs`:

```rust
struct Output {
cv: commitment::ValueCommitment,
cm_u: jubjub::Fq,
ephemeral_key: keys::EphemeralPublicKey,
enc_ciphertext: note::EncryptedNote,
out_ciphertext: note::WrappedNoteKey,
zkproof: Groth16Proof,
}
```

## Orchard Additions
[orchard-additions]: #orchard-additions

### Adding V5 Transactions
[adding-v5-transactions]: #adding-v5-transactions

Now lets see how the V5 transaction is specified in the protocol, this is the second table of [Transaction Encoding and Consensus](https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus) and how are we going to represent it based in the above changes for Sapling fields and the new Orchard fields.

We propose the following representation for transaction V5 in Zebra:

```rust
enum Transaction::V5 {
lock_time: LockTime,
expiry_height: block::Height,
inputs: Vec<transparent::Input>,
outputs: Vec<transparent::Output>,
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
sapling_shielded_data: Option<sapling::ShieldedData<SharedAnchor>>,
orchard_shielded_data: Option<orchard::ShieldedData>,
}
```

To model the V5 anchor type, `sapling_shielded_data` uses the `SharedAnchor` variant located at `zebra-chain/src/transaction/sapling/shielded_data.rs`.

### Adding Orchard ShieldedData
[adding-orchard-shieldeddata]: #adding-orchard-shieldeddata

The new V5 structure will create a new `orchard::ShieldedData` type. This new type will be defined in a new `zebra-chain/src/orchard/shielded_data.rs` file:

```rust
struct orchard::ShieldedData {
flags: Flags,
value_balance: Amount,
anchor: tree::Root,
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
proof: Halo2Proof,
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
/// An authorized action description.
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
///
/// Storing this separately ensures that it is impossible to construct
/// an invalid `ShieldedData` with no actions.
first: AuthorizedAction,
rest: Vec<AuthorizedAction>,
binding_sig: redpallas::Signature<redpallas::Binding>,
}
oxarbitrage marked this conversation as resolved.
Show resolved Hide resolved
```

teor2345 marked this conversation as resolved.
Show resolved Hide resolved
The fields are ordered based on the **last** data deserialized for each field.

### Adding Orchard AuthorizedAction
[adding-orchard-authorizedaction]: #adding-orchard-authorizedaction

oxarbitrage marked this conversation as resolved.
Show resolved Hide resolved
In `V5` transactions, there is one `SpendAuth` signature for every `Action`. To ensure that this structural rule is followed, we create an `AuthorizedAction` type in `orchard/shielded_data.rs`:

```rust
/// An authorized action description.
///
/// Every authorized Orchard `Action` must have a corresponding `SpendAuth` signature.
struct orchard::AuthorizedAction {
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
action: Action,
spend_auth_sig: redpallas::Signature<redpallas::SpendAuth>,
}
oxarbitrage marked this conversation as resolved.
Show resolved Hide resolved
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
```

Where `Action` is defined as [Action definition](https://github.com/ZcashFoundation/zebra/blob/68c12d045b63ed49dd1963dd2dc22eb991f3998c/zebra-chain/src/orchard/action.rs#L18-L41).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link need to change after #1885 merges.


### Adding Orchard Flags
[adding-orchard-flags]: #adding-orchard-flags

Finally, in the V5 transaction we have a new `orchard::Flags` type. This is a bitfield type defined as:

```rust
bitflags! {
struct orchard::Flags: u8 {
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
const ENABLE_SPENDS = 0b00000001;
const ENABLE_OUTPUTS = 0b00000010;
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
// Reserved, zeros (bits 2 .. 7)
}
}
```

oxarbitrage marked this conversation as resolved.
Show resolved Hide resolved
This type is also defined in `orchard/shielded_data.rs`.

## Test Plan
[test-plan]: #test-plan

- All renamed, modified and new types should serialize and deserialize.
- The full V4 and V5 transactions should serialize and deserialize.
- Prop test strategies for V4 and V5 will be updated and created.
- Before NU5 activation on testnet, test on the following test vectors:
- Hand-crafted Orchard-only, Orchard/Sapling, Orchard/Transparent, and Orchard/Sapling/Transparent transactions based on the spec
- "Fake" Sapling-only and Sapling/Transparent transactions based on the existing test vectors, converted from V4 to V5 format
- We can write a test utility function to automatically do these conversions
- An empty transaction, with no Orchard, Sapling, or Transparent data
- Any available `zcashd` test vectors
- After NU5 activation on testnet:
- Add test vectors using the testnet activation block and 2 more post-activation blocks
- After NU5 activation on mainnet:
- Add test vectors using the mainnet activation block and 2 more post-activation blocks

# Security

To avoid parsing memory exhaustion attacks, we will make the following changes across all `Transaction`, `ShieldedData`, `Spend` and `Output` variants, V1 through to V5:
- Check cardinality consensus rules at parse time, before deserializing any `Vec`s
- In general, Zcash requires that each transaction has at least one Transparent/Sprout/Sapling/Orchard transfer, this rule is not currently encoded in our data structures (it is only checked during semantic verification)
- Stop parsing as soon as the first error is detected

These changes should be made in a later pull request, see [#1917](https://github.com/ZcashFoundation/zebra/issues/1917) for details.