Skip to content
4 changes: 4 additions & 0 deletions zcash_client_backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ non-standard-fees = ["zcash_primitives/non-standard-fees"]

#! ### Experimental features

## Enables PIR-based Orchard note spendability: nullifier spend detection and
## witness construction via Private Information Retrieval.
spendability-pir = ["orchard"]

## Exposes unstable APIs. Their behaviour may change at any time.
unstable = ["dep:byteorder", "zcash_keys/unstable"]

Expand Down
23 changes: 23 additions & 0 deletions zcash_client_backend/src/data_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3105,6 +3105,14 @@ pub trait WalletWrite: WalletRead {
}
}

/// The result of a PIR Orchard witness lookup: Merkle path, anchor height, and anchor root.
#[cfg(feature = "orchard")]
pub type PirOrchardWitness = (
incrementalmerkletree::MerklePath<orchard::tree::MerkleHashOrchard, 32>,
u64,
[u8; 32],
);

/// This trait describes a capability for manipulating wallet note commitment trees.
#[cfg_attr(feature = "test-dependencies", delegatable_trait)]
pub trait WalletCommitmentTrees {
Expand Down Expand Up @@ -3168,4 +3176,19 @@ pub trait WalletCommitmentTrees {
start_index: u64,
roots: &[CommitmentTreeRoot<orchard::tree::MerkleHashOrchard>],
) -> Result<(), ShardTreeError<Self::Error>>;

/// Retrieves a PIR-provided Orchard Merkle authentication path for the note at the
/// given commitment tree position. Returns the path, anchor height, and anchor root.
///
/// The default implementation returns `Ok(None)`, indicating no PIR witness is
/// available. See `zcash_client_sqlite::WalletDb` for the production implementation
/// backed by the `pir_witness_data` table.
#[cfg(feature = "orchard")]
fn get_pir_orchard_merkle_path(
&self,
position: incrementalmerkletree::Position,
) -> Result<Option<PirOrchardWitness>, Self::Error> {
let _ = position;
Ok(None)
}
}
31 changes: 31 additions & 0 deletions zcash_client_backend/src/data_api/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,8 @@ where
&SpendingKeys::from_unified_spending_key(usk.clone()),
ovk_policy,
&proposal,
#[cfg(feature = "spendability-pir")]
false,
)
}

Expand Down Expand Up @@ -1141,6 +1143,35 @@ where
&SpendingKeys::from_unified_spending_key(usk.clone()),
ovk_policy,
proposal,
#[cfg(feature = "spendability-pir")]
false,
)
}

/// Like [`Self::create_proposed_transactions`] but uses PIR-stored witnesses
/// instead of ShardTree witnesses for Orchard spends.
#[cfg(feature = "spendability-pir")]
#[allow(clippy::type_complexity)]
pub fn create_proposed_transactions_pir<InputsErrT, FeeRuleT, ChangeErrT, N>(
&mut self,
usk: &UnifiedSpendingKey,
ovk_policy: OvkPolicy,
proposal: &Proposal<FeeRuleT, N>,
) -> Result<NonEmpty<TxId>, super::wallet::CreateErrT<DbT, InputsErrT, FeeRuleT, ChangeErrT, N>>
where
FeeRuleT: FeeRule,
{
let prover = LocalTxProver::bundled();
let network = self.network().clone();
create_proposed_transactions(
self.wallet_mut(),
&network,
&prover,
&prover,
&SpendingKeys::from_unified_spending_key(usk.clone()),
ovk_policy,
proposal,
true,
)
}

Expand Down
Loading
Loading