Skip to content

Commit

Permalink
Merge pull request #515 from str4d/update-compact-proto
Browse files Browse the repository at this point in the history
zcash_client_backend: Bring in latest `compact_formats.proto`
  • Loading branch information
str4d committed Feb 18, 2022
2 parents 8ce8c1e + cceae3a commit efe63ad
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 55 deletions.
12 changes: 10 additions & 2 deletions zcash_client_backend/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ and this library adheres to Rust's notion of
of a `zcash_client_backend::zip321::TransactionRequest` value.
This facilitates the implementation of ZIP 321 support in wallets and
provides substantially greater flexibility in transaction creation.
- `zcash_client_backend::proto`:
- `actions` field on `compact_formats::CompactTx`
- `compact_formats::CompactOrchardAction`
- `zcash_client_backend::zip321::TransactionRequest` methods:
- `TransactionRequest::new` for constructing a request from `Vec<Payment>`.
- `TransactionRequest::payments` for accessing the `Payments` that make up a
Expand All @@ -40,12 +43,17 @@ and this library adheres to Rust's notion of
### Changed
- MSRV is now 1.54.0.
- Bumped dependencies to `ff 0.11`, `group 0.11`, `bls12_381 0.6`, `jubjub 0.8`.
- `zcash_client_backend::proto`:
- `compact_formats::CompactSpend` has been renamed to `CompactSaplingSpend`,
and its `epk` field (and associated `set_epk` method) has been renamed to
`ephemeralKey` (and `set_ephemeralKey`).
- `compact_formats::CompactOutput` has been renamed to `CompactSaplingOutput`.
- `epk: jubjub::ExtendedPoint` has been replaced by
`ephemeral_key: zcash_note_encryption::EphemeralKeyBytes` in various places:
- `zcash_client_backend::wallet::WalletShieldedOutput`: the `epk` field has
been replaced by `ephemeral_key`.
- `zcash_client_backend::proto::compact_formats::CompactOutput`: the `epk`
method has been replaced by `ephemeral_key`.
- `zcash_client_backend::proto::compact_formats::CompactSaplingOutput`: the
`epk` method has been replaced by `ephemeral_key`.
- `data_api::wallet::spend_to_address` now takes a `min_confirmations`
parameter, which the caller can provide to specify the minimum number of
confirmations required for notes being selected. A default value of 10
Expand Down
63 changes: 44 additions & 19 deletions zcash_client_backend/proto/compact_formats.proto
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
// Copyright (c) 2019-2021 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .

syntax = "proto3";
package cash.z.wallet.sdk.rpc;
option go_package = "walletrpc";
option swift_prefix = "";

// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value.
// bytes fields of hashes are in canonical little-endian format.
Expand All @@ -10,39 +15,59 @@ option go_package = "walletrpc";
// 2. Detect a spend of your shielded Sapling notes
// 3. Update your witnesses to generate new Sapling spend proofs.
message CompactBlock {
uint32 protoVersion = 1; // the version of this wire format, for storage
uint64 height = 2; // the height of this block
bytes hash = 3;
bytes prevHash = 4;
uint32 time = 5;
bytes header = 6; // (hash, prevHash, and time) OR (full header)
repeated CompactTx vtx = 7; // compact transactions from this block
uint32 protoVersion = 1; // the version of this wire format, for storage
uint64 height = 2; // the height of this block
bytes hash = 3; // the ID (hash) of this block, same as in block explorers
bytes prevHash = 4; // the ID (hash) of this block's predecessor
uint32 time = 5; // Unix epoch time when the block was mined
bytes header = 6; // (hash, prevHash, and time) OR (full header)
repeated CompactTx vtx = 7; // zero or more compact transactions from this block
}

// CompactTx contains the minimum information for a wallet to know if this transaction
// is relevant to it (either pays to it or spends from it) via shielded elements
// only. This message will not encode a transparent-to-transparent transaction.
message CompactTx {
// Index and hash will allow the receiver to call out to chain
// explorers or other data structures to retrieve more information
// about this transaction.
uint64 index = 1;
bytes hash = 2;
uint64 index = 1; // the index within the full block
bytes hash = 2; // the ID (hash) of this transaction, same as in block explorers

// The transaction fee: present if server can provide. In the case of a
// stateless server and a transaction with transparent inputs, this will be
// unset because the calculation requires reference to prior transactions.
// in a pure-Sapling context, the fee will be calculable as:
// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
// If there are no transparent inputs, the fee will be calculable as:
// valueBalanceSapling + valueBalanceOrchard + sum(vPubNew) - sum(vPubOld) - sum(tOut)
uint32 fee = 3;

repeated CompactSpend spends = 4;
repeated CompactOutput outputs = 5;
repeated CompactSaplingSpend spends = 4;
repeated CompactSaplingOutput outputs = 5;
repeated CompactOrchardAction actions = 6;
}

// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash
// protocol specification.
message CompactSaplingSpend {
bytes nf = 1; // nullifier (see the Zcash protocol specification)
}

message CompactSpend {
bytes nf = 1;
// output encodes the `cmu` field, `ephemeralKey` field, and a 52-byte prefix of the
// `encCiphertext` field of a Sapling Output Description. These fields are described in
// section 7.4 of the Zcash protocol spec:
// https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus
// Total size is 116 bytes.
message CompactSaplingOutput {
bytes cmu = 1; // note commitment u-coordinate
bytes ephemeralKey = 2; // ephemeral public key
bytes ciphertext = 3; // first 52 bytes of ciphertext
}

message CompactOutput {
bytes cmu = 1;
bytes epk = 2;
bytes ciphertext = 3;
// https://github.com/zcash/zips/blob/main/zip-0225.rst#orchard-action-description-orchardaction
// (but not all fields are needed)
message CompactOrchardAction {
bytes nullifier = 1; // [32] The nullifier of the input note
bytes cmx = 2; // [32] The x-coordinate of the note commitment for the output note
bytes ephemeralKey = 3; // [32] An encoding of an ephemeral Pallas public key
bytes ciphertext = 4; // [52] The first 52 bytes of the encCiphertext field
}
27 changes: 13 additions & 14 deletions zcash_client_backend/src/proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ use zcash_primitives::{
block::{BlockHash, BlockHeader},
consensus::BlockHeight,
sapling::Nullifier,
transaction::{
components::sapling::{self, CompactOutputDescription, OutputDescription},
TxId,
},
transaction::{components::sapling, TxId},
};

use zcash_note_encryption::{EphemeralKeyBytes, COMPACT_NOTE_SIZE};
Expand Down Expand Up @@ -85,7 +82,7 @@ impl compact_formats::CompactTx {
}
}

impl compact_formats::CompactOutput {
impl compact_formats::CompactSaplingOutput {
/// Returns the note commitment for this output.
///
/// A convenience method that parses [`CompactOutput.cmu`].
Expand All @@ -103,36 +100,38 @@ impl compact_formats::CompactOutput {
///
/// [`CompactOutput.epk`]: #structfield.epk
pub fn ephemeral_key(&self) -> Result<EphemeralKeyBytes, ()> {
self.epk[..]
self.ephemeralKey[..]
.try_into()
.map(EphemeralKeyBytes)
.map_err(|_| ())
}
}

impl<A: sapling::Authorization> From<OutputDescription<A>> for compact_formats::CompactOutput {
fn from(out: OutputDescription<A>) -> compact_formats::CompactOutput {
let mut result = compact_formats::CompactOutput::new();
impl<A: sapling::Authorization> From<sapling::OutputDescription<A>>
for compact_formats::CompactSaplingOutput
{
fn from(out: sapling::OutputDescription<A>) -> compact_formats::CompactSaplingOutput {
let mut result = compact_formats::CompactSaplingOutput::new();
result.set_cmu(out.cmu.to_repr().to_vec());
result.set_epk(out.ephemeral_key.as_ref().to_vec());
result.set_ephemeralKey(out.ephemeral_key.as_ref().to_vec());
result.set_ciphertext(out.enc_ciphertext[..COMPACT_NOTE_SIZE].to_vec());
result
}
}

impl TryFrom<compact_formats::CompactOutput> for CompactOutputDescription {
impl TryFrom<compact_formats::CompactSaplingOutput> for sapling::CompactOutputDescription {
type Error = ();

fn try_from(value: compact_formats::CompactOutput) -> Result<Self, Self::Error> {
Ok(CompactOutputDescription {
fn try_from(value: compact_formats::CompactSaplingOutput) -> Result<Self, Self::Error> {
Ok(sapling::CompactOutputDescription {
cmu: value.cmu()?,
ephemeral_key: value.ephemeral_key()?,
enc_ciphertext: value.ciphertext.try_into().map_err(|_| ())?,
})
}
}

impl compact_formats::CompactSpend {
impl compact_formats::CompactSaplingSpend {
pub fn nf(&self) -> Result<Nullifier, ()> {
Nullifier::from_slice(&self.nf).map_err(|_| ())
}
Expand Down
26 changes: 14 additions & 12 deletions zcash_client_backend/src/welding_rig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ use zcash_primitives::{
zip32::{AccountId, ExtendedFullViewingKey},
};

use crate::proto::compact_formats::{CompactBlock, CompactOutput};
use crate::proto::compact_formats::{CompactBlock, CompactSaplingOutput};
use crate::wallet::{WalletShieldedOutput, WalletShieldedSpend, WalletTx};

/// Scans a [`CompactOutput`] with a set of [`ScanningKey`]s.
/// Scans a [`CompactSaplingOutput`] with a set of [`ScanningKey`]s.
///
/// Returns a [`WalletShieldedOutput`] and corresponding [`IncrementalWitness`] if this
/// output belongs to any of the given [`ScanningKey`]s.
Expand All @@ -33,7 +33,7 @@ fn scan_output<P: consensus::Parameters, K: ScanningKey>(
params: &P,
height: BlockHeight,
index: usize,
output: CompactOutput,
output: CompactSaplingOutput,
vks: &[(&AccountId, &K)],
spent_from_accounts: &HashSet<AccountId>,
tree: &mut CommitmentTree<Node>,
Expand Down Expand Up @@ -90,7 +90,7 @@ fn scan_output<P: consensus::Parameters, K: ScanningKey>(
}

/// A key that can be used to perform trial decryption and nullifier
/// computation for a Sapling [`CompactOutput`]
/// computation for a Sapling [`CompactSaplingOutput`]
///
/// The purpose of this trait is to enable [`scan_block`]
/// and related methods to be used with either incoming viewing keys
Expand All @@ -100,7 +100,7 @@ fn scan_output<P: consensus::Parameters, K: ScanningKey>(
/// will be returned; in the case of a full viewing key, the
/// nullifier for the note can also be obtained.
///
/// [`CompactOutput`]: crate::proto::compact_formats::CompactOutput
/// [`CompactSaplingOutput`]: crate::proto::compact_formats::CompactSaplingOutput
/// [`scan_block`]: crate::welding_rig::scan_block
pub trait ScanningKey {
/// The type of nullifier extracted when a note is successfully
Expand Down Expand Up @@ -321,7 +321,9 @@ mod tests {
};

use super::scan_block;
use crate::proto::compact_formats::{CompactBlock, CompactOutput, CompactSpend, CompactTx};
use crate::proto::compact_formats::{
CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
};

fn random_compact_tx(mut rng: impl RngCore) -> CompactTx {
let fake_nf = {
Expand All @@ -340,11 +342,11 @@ mod tests {
let fake_epk = SPENDING_KEY_GENERATOR * fake_esk;
fake_epk.to_bytes().to_vec()
};
let mut cspend = CompactSpend::new();
let mut cspend = CompactSaplingSpend::new();
cspend.set_nf(fake_nf);
let mut cout = CompactOutput::new();
let mut cout = CompactSaplingOutput::new();
cout.set_cmu(fake_cmu);
cout.set_epk(fake_epk);
cout.set_ephemeralKey(fake_epk);
cout.set_ciphertext(vec![0; 52]);
let mut ctx = CompactTx::new();
let mut txid = vec![0; 32];
Expand Down Expand Up @@ -398,11 +400,11 @@ mod tests {
cb.vtx.push(tx);
}

let mut cspend = CompactSpend::new();
let mut cspend = CompactSaplingSpend::new();
cspend.set_nf(nf.0.to_vec());
let mut cout = CompactOutput::new();
let mut cout = CompactSaplingOutput::new();
cout.set_cmu(cmu);
cout.set_epk(epk);
cout.set_ephemeralKey(epk);
cout.set_ciphertext(enc_ciphertext.as_ref()[..52].to_vec());
let mut ctx = CompactTx::new();
let mut txid = vec![0; 32];
Expand Down
18 changes: 10 additions & 8 deletions zcash_client_sqlite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,9 @@ mod tests {

use zcash_client_backend::{
keys::{sapling, UnifiedFullViewingKey},
proto::compact_formats::{CompactBlock, CompactOutput, CompactSpend, CompactTx},
proto::compact_formats::{
CompactBlock, CompactSaplingOutput, CompactSaplingSpend, CompactTx,
},
};

#[cfg(feature = "transparent-inputs")]
Expand Down Expand Up @@ -840,9 +842,9 @@ mod tests {
let enc_ciphertext = encryptor.encrypt_note_plaintext();

// Create a fake CompactBlock containing the note
let mut cout = CompactOutput::new();
let mut cout = CompactSaplingOutput::new();
cout.set_cmu(cmu);
cout.set_epk(epk);
cout.set_ephemeralKey(epk);
cout.set_ciphertext(enc_ciphertext.as_ref()[..52].to_vec());
let mut ctx = CompactTx::new();
let mut txid = vec![0; 32];
Expand Down Expand Up @@ -872,7 +874,7 @@ mod tests {
let rseed = generate_random_rseed(&network(), height, &mut rng);

// Create a fake CompactBlock containing the note
let mut cspend = CompactSpend::new();
let mut cspend = CompactSaplingSpend::new();
cspend.set_nf(nf.to_vec());
let mut ctx = CompactTx::new();
let mut txid = vec![0; 32];
Expand All @@ -899,9 +901,9 @@ mod tests {
let epk = encryptor.epk().to_bytes().to_vec();
let enc_ciphertext = encryptor.encrypt_note_plaintext();

let mut cout = CompactOutput::new();
let mut cout = CompactSaplingOutput::new();
cout.set_cmu(cmu);
cout.set_epk(epk);
cout.set_ephemeralKey(epk);
cout.set_ciphertext(enc_ciphertext.as_ref()[..52].to_vec());
cout
});
Expand All @@ -927,9 +929,9 @@ mod tests {
let epk = encryptor.epk().to_bytes().to_vec();
let enc_ciphertext = encryptor.encrypt_note_plaintext();

let mut cout = CompactOutput::new();
let mut cout = CompactSaplingOutput::new();
cout.set_cmu(cmu);
cout.set_epk(epk);
cout.set_ephemeralKey(epk);
cout.set_ciphertext(enc_ciphertext.as_ref()[..52].to_vec());
cout
});
Expand Down

0 comments on commit efe63ad

Please sign in to comment.