Merge pull request #1129 from zcash/wallet/orchard_compiler_flag

Add `zcash_unstable` compiler flag to fully gate `orchard` functionality
This commit is contained in:
str4d 2024-01-25 19:15:53 +00:00 committed by GitHub
commit 610b19bcd2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 79 additions and 25 deletions

View File

@ -17,6 +17,11 @@ jobs:
- orchard
- unstable-nu6
- zfuture
include:
- extra_flags: orchard
rustflags: '--cfg zcash_unstable="orchard"'
env:
RUSTFLAGS: ${{ matrix.rustflags }}
steps:
- uses: actions/checkout@v4

1
.gitignore vendored
View File

@ -1 +1,2 @@
target
.cargo

View File

@ -7,18 +7,42 @@ and this library adheres to Rust's notion of
## [Unreleased]
### Added
- A new `orchard` feature flag has been added to make it possible to
build client code without `orchard` dependendencies. Additions and
changes related to `Orchard` below are introduced under this feature
flag.
- `zcash_client_backend::data_api`:
- `AccountBalance::with_orchard_balance_mut`
- `BlockMetadata::orchard_tree_size`
- `ScannedBlock::orchard`
- `ScannedBlockCommitments::orchard`
- `zcash_client_backend::fees::orchard`
- `zcash_client_backend::fees::ChangeValue::orchard`
- `zcash_client_backend::wallet`:
- `Note::Orchard`
### Changed
- `zcash_client_backend::data_api`:
- Arguments to `BlockMetadata::from_parts` have changed.
- Arguments to `ScannedBlock::from_parts` have changed.
- Changes to the `WalletRead` trait:
- Added `get_orchard_nullifiers`
- `ShieldedProtocol` has a new `Orchard` variant.
- `zcash_client_backend::fees`:
- Arguments to `ChangeStrategy::compute_balance` have changed.
## [0.11.0-pre-release] Unreleased
### Added
- `zcash_client_backend::data_api`:
- `BlockMetadata::orchard_tree_size` (when the `orchard` feature is enabled).
- `InputSource`
- `ScannedBlock::{into_commitments, sapling}`
- `ScannedBlock::orchard` (when the `orchard` feature is enabled.)
- `ScannedBundles`
- `ScannedBlockCommitments`
- `Balance::{add_spendable_value, add_pending_change_value, add_pending_spendable_value}`
- `AccountBalance::{
with_sapling_balance_mut,
with_orchard_balance_mut,
add_unshielded_value
}`
- `WalletSummary::next_sapling_subtree_index`
@ -28,8 +52,8 @@ and this library adheres to Rust's notion of
- `wallet::input_selection::ShieldingSelector` has been
factored out from the `InputSelector` trait to separate out transparent
functionality and move it behind the `transparent-inputs` feature flag.
- `zcash_client_backend::fees::{standard, orchard, sapling}`
- `zcash_client_backend::fees::ChangeValue::{new, orchard}`
- `zcash_client_backend::fees::{standard, sapling}`
- `zcash_client_backend::fees::ChangeValue::new`
- `zcash_client_backend::wallet`:
- `Note`
- `ReceivedNote`
@ -38,7 +62,7 @@ and this library adheres to Rust's notion of
- `zcash_client_backend::zip321::parse::Param::name`
- `zcash_client_backend::proto::`
- `PROPOSAL_SER_V1`
- `ProposalError`
- `ProposalDecodingError`
- `proposal` module, for parsing and serializing transaction proposals.
- `impl Clone for zcash_client_backend::{
zip321::{Payment, TransactionRequest, Zip321Error, parse::Param, parse::IndexedParam},
@ -50,8 +74,6 @@ and this library adheres to Rust's notion of
wallet::{ReceivedSaplingNote, WalletTransparentOutput},
wallet::input_selection::{Proposal, SaplingInputs},
}`
- A new `orchard` feature flag has been added to make it possible to
build client code without `orchard` dependendencies.
### Moved
- `zcash_client_backend::data_api::{PoolType, ShieldedProtocol}` have
@ -64,9 +86,8 @@ and this library adheres to Rust's notion of
### Changed
- `zcash_client_backend::data_api`:
- Arguments to `BlockMetadata::from_parts` have changed to include Orchard.
- `BlockMetadata::sapling_tree_size` now returns an `Option<u32>` instead of
a `u32` for consistency with Orchard.
a `u32` for future consistency with Orchard.
- `WalletShieldedOutput` has an additional type parameter which is used for
key scope. `WalletShieldedOutput::from_parts` now takes an additional
argument of this type.
@ -76,9 +97,6 @@ and this library adheres to Rust's notion of
`WalletTx` change.
- `ScannedBlock::metadata` has been renamed to `to_block_metadata` and now
returns an owned value rather than a reference.
- `ShieldedProtocol` has a new variant for `Orchard`, allowing for better
reporting to callers trying to perform actions using `Orchard` before it is
fully supported.
- Fields of `Balance` and `AccountBalance` have been made private and the values
of these fields have been made available via methods having the same names
as the previously-public fields.
@ -93,6 +111,7 @@ and this library adheres to Rust's notion of
backend-specific note identifier. The related `NoteRef` type parameter has
been removed from `error::Error`.
- A new variant `UnsupportedPoolType` has been added.
- A new variant `NoSupportedReceivers` has been added.
- `wallet::shield_transparent_funds` no longer takes a `memo` argument;
instead, memos to be associated with the shielded outputs should be
specified in the construction of the value of the `input_selector`
@ -131,7 +150,6 @@ and this library adheres to Rust's notion of
arguments. This helps to minimize the set of capabilities that the
`data_api::InputSource` must expose.
- Changes to the `WalletRead` trait:
- Added `get_orchard_nullifiers` (under the `orchard` feature flag.)
- `get_checkpoint_depth` has been removed without replacement. This
is no longer needed given the change to use the stored anchor height for transaction
proposal execution.
@ -202,8 +220,7 @@ and this library adheres to Rust's notion of
- `zcash_client_backend::data_api`
- `zcash_client_backend::data_api::ScannedBlock::from_parts` has been made crate-private.
- `zcash_client_backend::data_api::ScannedBlock::into_sapling_commitments` has been
replaced by `into_commitments` which returns both Sapling and Orchard note commitments
and associated note commitment retention information for the block.
replaced by `into_commitments` which returns a `ScannedBlockCommitments` value.
## [0.10.0] - 2023-09-25

View File

@ -61,6 +61,9 @@ pub enum Error<DataSourceError, CommitmentTreeError, SelectionError, FeeError> {
/// Attempted to create a spend to an unsupported pool type (currently, Orchard).
UnsupportedPoolType(PoolType),
/// Attempted to create a spend to an unsupported Unified Address receiver
NoSupportedReceivers(Vec<u32>),
/// A note being spent does not correspond to either the internal or external
/// full viewing key for an account.
NoteMismatch(NoteId),
@ -117,7 +120,8 @@ where
Error::ScanRequired => write!(f, "Must scan blocks first"),
Error::Builder(e) => write!(f, "An error occurred building the transaction: {}", e),
Error::MemoForbidden => write!(f, "It is not possible to send a memo to a transparent address."),
Error::UnsupportedPoolType(t) => write!(f, "Attempted to create spend to an unsupported pool type: {}", t),
Error::UnsupportedPoolType(t) => write!(f, "Attempted to send to an unsupported pool: {}", t),
Error::NoSupportedReceivers(t) => write!(f, "Unified address contained only unsupported receiver types: {:?}", &t[..]),
Error::NoteMismatch(n) => write!(f, "A note being spent ({:?}) does not correspond to either the internal or external full viewing key for the provided spending key.", n),
#[cfg(feature = "transparent-inputs")]

View File

@ -693,9 +693,9 @@ where
builder.add_transparent_output(taddr, payment.amount)?;
}
} else {
return Err(Error::UnsupportedPoolType(PoolType::Shielded(
ShieldedProtocol::Orchard,
)));
return Err(Error::NoSupportedReceivers(
ua.unknown().iter().map(|(tc, _)| *tc).collect(),
));
}
}
Address::Sapling(addr) => {
@ -738,6 +738,7 @@ where
Some(memo),
))
}
#[cfg(zcash_unstable = "orchard")]
ShieldedProtocol::Orchard => {
#[cfg(not(feature = "orchard"))]
return Err(Error::UnsupportedPoolType(PoolType::Shielded(

View File

@ -453,6 +453,7 @@ impl sapling::OutputView for SaplingPayment {
}
}
#[cfg(feature = "orchard")]
pub(crate) struct OrchardPayment(NonNegativeAmount);
// TODO: introduce this method when it is needed for testing.
@ -522,6 +523,7 @@ where
{
let mut transparent_outputs = vec![];
let mut sapling_outputs = vec![];
#[cfg(feature = "orchard")]
let mut orchard_outputs = vec![];
for payment in transaction_request.payments() {
let mut push_transparent = |taddr: TransparentAddress| {
@ -533,6 +535,7 @@ where
let mut push_sapling = || {
sapling_outputs.push(SaplingPayment(payment.amount));
};
#[cfg(feature = "orchard")]
let mut push_orchard = || {
orchard_outputs.push(OrchardPayment(payment.amount));
};
@ -551,6 +554,7 @@ where
let has_orchard = false;
if has_orchard {
#[cfg(feature = "orchard")]
push_orchard();
} else if addr.sapling().is_some() {
push_sapling();
@ -635,11 +639,16 @@ where
Err(other) => return Err(other.into()),
}
#[cfg(not(zcash_unstable = "orchard"))]
let selectable_pools = &[ShieldedProtocol::Sapling];
#[cfg(zcash_unstable = "orchard")]
let selectable_pools = &[ShieldedProtocol::Sapling, ShieldedProtocol::Orchard];
shielded_inputs = wallet_db
.select_spendable_notes(
account,
amount_required.into(),
&[ShieldedProtocol::Sapling, ShieldedProtocol::Orchard],
selectable_pools,
anchor_height,
&exclude,
)

View File

@ -37,12 +37,18 @@ pub use decrypt::{decrypt_transaction, DecryptedOutput, TransferType};
#[macro_use]
extern crate assert_matches;
#[cfg(all(feature = "orchard", not(zcash_unstable = "orchard")))]
core::compile_error!(
"The `orchard` feature flag requires the `zcash_unstable=\"orchard\"` RUSTFLAG."
);
/// A shielded transfer protocol known to the wallet.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ShieldedProtocol {
/// The Sapling protocol
Sapling,
/// The Orchard protocol
#[cfg(zcash_unstable = "orchard")]
Orchard,
}
@ -60,6 +66,7 @@ impl fmt::Display for PoolType {
match self {
PoolType::Transparent => f.write_str("Transparent"),
PoolType::Shielded(ShieldedProtocol::Sapling) => f.write_str("Sapling"),
#[cfg(zcash_unstable = "orchard")]
PoolType::Shielded(ShieldedProtocol::Orchard) => f.write_str("Orchard"),
}
}

View File

@ -222,7 +222,7 @@ pub enum ProposalDecodingError<DbError> {
/// A transaction identifier string did not decode to a valid transaction ID.
TxIdInvalid(TryFromSliceError),
/// An invalid value pool identifier was encountered.
ValuePoolInvalid(i32),
ValuePoolNotSupported(i32),
/// A failure occurred trying to retrieve an unspent note or UTXO from the wallet database.
InputRetrieval(DbError),
/// The unspent note or UTXO corresponding to a proposal input was not found in the wallet
@ -257,7 +257,7 @@ impl<E: Display> Display for ProposalDecodingError<E> {
ProposalDecodingError::TxIdInvalid(err) => {
write!(f, "Invalid transaction id: {:?}", err)
}
ProposalDecodingError::ValuePoolInvalid(id) => {
ProposalDecodingError::ValuePoolNotSupported(id) => {
write!(f, "Invalid value pool identifier: {:?}", id)
}
ProposalDecodingError::InputRetrieval(err) => write!(
@ -312,8 +312,9 @@ fn pool_type<T>(pool_id: i32) -> Result<PoolType, ProposalDecodingError<T>> {
match proposal::ValuePool::try_from(pool_id) {
Ok(proposal::ValuePool::Transparent) => Ok(PoolType::Transparent),
Ok(proposal::ValuePool::Sapling) => Ok(PoolType::Shielded(ShieldedProtocol::Sapling)),
#[cfg(zcash_unstable = "orchard")]
Ok(proposal::ValuePool::Orchard) => Ok(PoolType::Shielded(ShieldedProtocol::Orchard)),
_ => Err(ProposalDecodingError::ValuePoolInvalid(pool_id)),
_ => Err(ProposalDecodingError::ValuePoolNotSupported(pool_id)),
}
}
@ -337,6 +338,7 @@ impl From<ShieldedProtocol> for proposal::ValuePool {
fn from(value: ShieldedProtocol) -> Self {
match value {
ShieldedProtocol::Sapling => proposal::ValuePool::Sapling,
#[cfg(zcash_unstable = "orchard")]
ShieldedProtocol::Orchard => proposal::ValuePool::Orchard,
}
}
@ -447,7 +449,7 @@ impl proposal::Proposal {
match input.pool_type()? {
PoolType::Transparent => {
#[cfg(not(feature = "transparent-inputs"))]
return Err(ProposalDecodingError::ValuePoolInvalid(1));
return Err(ProposalDecodingError::ValuePoolNotSupported(1));
#[cfg(feature = "transparent-inputs")]
{

View File

@ -132,6 +132,7 @@ pub(crate) fn pool_code(pool_type: PoolType) -> i64 {
match pool_type {
PoolType::Transparent => 0i64,
PoolType::Shielded(ShieldedProtocol::Sapling) => 2i64,
#[cfg(zcash_unstable = "orchard")]
PoolType::Shielded(ShieldedProtocol::Orchard) => 3i64,
}
}
@ -794,6 +795,7 @@ pub(crate) fn get_received_memo(
)
.optional()?
.flatten(),
#[cfg(zcash_unstable = "orchard")]
_ => {
return Err(SqliteClientError::UnsupportedPoolType(PoolType::Shielded(
note_id.protocol(),

View File

@ -14,6 +14,7 @@ The entries below are relative to the `zcash_client_backend` crate as of
- `address`
- `encoding`
- `keys`
- `zcash_keys::address::UnifiedAddress::unknown`:
- `zcash_keys::keys`:
- `AddressGenerationError`
- `UnifiedAddressRequest`

View File

@ -150,6 +150,11 @@ impl UnifiedAddress {
self.transparent.as_ref()
}
/// Returns the set of unknown receivers of the unified address.
pub fn unknown(&self) -> &[(u32, Vec<u8>)] {
&self.unknown
}
fn to_address(&self, net: Network) -> ZcashAddress {
#[cfg(feature = "orchard")]
let orchard_receiver = self