Skip to main content

zebra_chain/
ironwood.rs

1//! Ironwood shielded pool types (NU6.3 onward).
2//!
3//! The Ironwood pool reuses the Orchard Action + Halo2 proof system, so its on-chain data
4//! structures are structurally identical to Orchard's. Rather than duplicating those types, this
5//! module provides thin newtypes over the Orchard types. This keeps the Ironwood pool
6//! *type-distinct* from Orchard — it has its own note commitment tree, nullifier set, and chain
7//! value pool — while reusing all of Orchard's wire-format and proof-verification machinery.
8//!
9//! The Ironwood *state* (nullifier set, note commitment tree, anchors, and chain value pool) is
10//! always present, so the on-disk database format is stable; it simply stays empty until NU6.3
11//! transactions appear on-chain.
12
13use crate::orchard;
14
15#[cfg(any(test, feature = "proptest-impl"))]
16mod arbitrary;
17
18/// An Ironwood nullifier.
19///
20/// Wraps [`orchard::Nullifier`] (Ironwood reuses the Orchard nullifier construction). The Ironwood
21/// and Orchard nullifier sets are *disjoint* even when their bit patterns coincide: they live in
22/// separate column families and are checked separately. Keeping Ironwood nullifiers in their own
23/// type lets the duplicate-nullifier detection distinguish the two pools at the type level.
24#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Deserialize, Serialize)]
25pub struct Nullifier(orchard::Nullifier);
26
27impl From<Nullifier> for [u8; 32] {
28    fn from(nullifier: Nullifier) -> Self {
29        nullifier.0.into()
30    }
31}
32
33impl From<orchard::Nullifier> for Nullifier {
34    fn from(nullifier: orchard::Nullifier) -> Self {
35        Self(nullifier)
36    }
37}
38
39/// Ironwood shielded data: a v6 Orchard-protocol bundle committed to the Ironwood pool.
40///
41/// Wraps [`orchard::ShieldedDataV6`] (the v6 Orchard bundle shape). The Ironwood bundle shares the
42/// exact wire format of the v6 Orchard bundle, but is the only pool that permits the
43/// `enableCrossAddress` flag (bit 2), which the Orchard pool reserves regardless of tx version. This
44/// newtype keeps the two type-distinct so they cannot be accidentally interchanged, and so the
45/// Ironwood bundle can commit into a separate note commitment tree and nullifier set.
46#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
47pub struct ShieldedData(orchard::ShieldedDataV6);
48
49impl ShieldedData {
50    /// Wraps a v6 Orchard-protocol bundle as Ironwood shielded data.
51    pub fn new(shielded_data: orchard::ShieldedDataV6) -> Self {
52        Self(shielded_data)
53    }
54
55    /// Returns the inner Orchard [`ShieldedData`](orchard::ShieldedData) backing this Ironwood
56    /// bundle (the v6 Orchard bundle shape that Ironwood reuses).
57    pub fn data(&self) -> &orchard::ShieldedData {
58        self.0.data()
59    }
60}