Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3,279 changes: 2,191 additions & 1,088 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions zcash_client_backend/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ workspace.

## [Unreleased]

### Added
- `zcash_client_backend::data_api::WalletCommitmentTrees::get_pir_orchard_merkle_path`
default trait method (behind `orchard` + `spendability-pir` feature flags) for
retrieving PIR-provided Orchard Merkle authentication paths.
- `spendability-pir` feature flag, enabling PIR-based Orchard note spendability
via witness construction from an external PIR server.

## [0.21.2] - 2026-03-10
- The following APIs no longer crash in certain regtest mode configurations with
fewer NUs active:
Expand Down
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(all(feature = "orchard", feature = "spendability-pir"))]
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(all(feature = "orchard", feature = "spendability-pir"))]
fn get_pir_orchard_merkle_path(
&self,
position: incrementalmerkletree::Position,
) -> Result<Option<PirOrchardWitness>, Self::Error> {
let _ = position;
Ok(None)
}
}
316 changes: 280 additions & 36 deletions zcash_client_backend/src/data_api/wallet.rs

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions zcash_client_backend/src/proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub enum ProposalError {
ShieldingInvalid,
/// No anchor information could be obtained for the specified block height.
AnchorNotFound(BlockHeight),
/// Selected Orchard notes were backed by incompatible PIR witness anchors.
PIRWitnessAnchorMismatch,
/// A reference to the output of a prior step is invalid.
ReferenceError(StepOutput),
/// An attempted double-spend of a prior step output was detected.
Expand Down Expand Up @@ -94,6 +96,10 @@ impl Display for ProposalError {
ProposalError::AnchorNotFound(h) => {
write!(f, "Unable to compute anchor for block height {h:?}")
}
ProposalError::PIRWitnessAnchorMismatch => write!(
f,
"Selected Orchard inputs were backed by incompatible PIR witness anchors."
),
ProposalError::ReferenceError(r) => {
write!(f, "No prior step output found for reference {r:?}")
}
Expand Down
21 changes: 21 additions & 0 deletions zcash_client_sqlite/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ workspace.

## [Unreleased]

### Added
- `spendability-pir` feature flag, enabling PIR (Private Information Retrieval)
for immediate Orchard note spendability. This includes:
- `zcash_client_sqlite::wallet::pir` module for spent-note tracking via
nullifier PIR queries against an external server.
- `zcash_client_sqlite::wallet::pir_witness` module for storing PIR-obtained
Merkle authentication paths, enabling notes to be spent before the wallet
finishes scanning.
- `WalletCommitmentTrees::get_pir_orchard_merkle_path` implementation for
`WalletDb`.
- `pir_spent_notes` and `pir_witness_data` database migrations (unconditional,
not feature-gated) to keep the migration DAG identical across all builds.

### Changed
- When `spendability-pir` is enabled, `get_wallet_summary` and note selection
skip the unscanned-range spendability gate for Orchard notes, and notes with
PIR witnesses are treated as spendable even when their shard is not fully
scanned.
- `truncate_to_height` now unconditionally clears the `pir_spent_notes` and
`pir_witness_data` tables to avoid stale data after reorgs.

## [0.19.5] - 2026-03-10

### Fixed
Expand Down
12 changes: 12 additions & 0 deletions zcash_client_sqlite/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,24 @@ rand.workspace = true
[dev-dependencies]
ambassador.workspace = true
assert_matches.workspace = true
axum = "0.7"
bls12_381.workspace = true
commitment-tree-db = { git = "https://github.com/valargroup/spendability-pir.git", rev = "3b33092a2988cfdd28edd65837b9ad03b0003fd1" }
incrementalmerkletree = { workspace = true, features = ["test-dependencies"] }
incrementalmerkletree-testing.workspace = true
pasta_curves.workspace = true
pir-types = { git = "https://github.com/valargroup/spendability-pir.git", rev = "3b33092a2988cfdd28edd65837b9ad03b0003fd1" }
shardtree = { workspace = true, features = ["legacy-api", "test-dependencies"] }
orchard = { workspace = true, features = ["test-dependencies"] }
proptest.workspace = true
rand_chacha.workspace = true
rand_core.workspace = true
reqwest = { version = "0.12", features = ["json"] }
secp256k1 = { workspace = true, features = ["rand"] }
serde_json.workspace = true
tempfile = "3.5.0"
tokio = { workspace = true, features = ["full"] }
witness-server = { git = "https://github.com/valargroup/spendability-pir.git", rev = "3b33092a2988cfdd28edd65837b9ad03b0003fd1" }
zcash_keys = { workspace = true, features = ["test-dependencies"] }
zcash_note_encryption.workspace = true
zcash_proofs = { workspace = true, features = ["bundled-prover"] }
Expand Down Expand Up @@ -169,6 +176,11 @@ expensive-tests = []
## protocol-specific flags. Test-only.
pczt-tests = ["serde", "zcash_client_backend/pczt"]

## Enables PIR (Private Information Retrieval) for immediate Orchard note spendability:
## spent-note tracking via nullifier PIR queries and Merkle witness fetching for
## spending notes before the wallet finishes scanning.
spendability-pir = ["orchard", "zcash_client_backend/spendability-pir"]

[lib]
bench = false

Expand Down
Loading
Loading