Add `zcash_unstable` compiler flag to fully gate `orchard` functionality

This commit is contained in:
Kris Nuttycombe 2024-01-23 17:12:51 -07:00
parent 20150c32a0
commit 184e3c741f
9 changed files with 41 additions and 9 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

@ -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

@ -635,11 +635,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,
}
}
@ -759,6 +760,7 @@ pub(crate) fn get_received_memo(
)
.optional()?
.flatten(),
#[cfg(zcash_unstable = "orchard")]
_ => {
return Err(SqliteClientError::UnsupportedPoolType(PoolType::Shielded(
note_id.protocol(),

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