Skip to content

Track transparent completeness before PIR-protecting Ironwood transactions #19

Description

@p0mvn

Problem

Compact scanning currently treats a transaction as eligible for private Ironwood enhancement when it has Ironwood actions and all represented Sapling, Orchard, vin, and vout fields are empty.

That predicate does not prove that the full transaction is Ironwood-only. CompactTx.vin and CompactTx.vout are optional compact metadata, and the default GetBlockRange request uses an empty poolTypes list. A conforming server therefore returns shielded data without transparent inputs or outputs.

These full transactions can consequently have the same compact representation:

  • Ironwood-only transaction.
  • Mixed Ironwood/transparent transaction whose transparent fields were omitted.

Ironwood action counts, commitment-tree positions, and the current PIR records cannot distinguish them. A transparent component does not alter the number of Ironwood actions, and the PIR record only contains Ironwood encrypted-note fields.

Consequence

An incorrectly classified mixed transaction is protected from ordinary transaction-ID enhancement. When PIR work completes, the transaction's ordinary enhancement request can be retired without the wallet ever receiving the full transaction.

The most important failure case is:

wallet transparent UTXO -> wallet Ironwood note

Compact scanning discovers the Ironwood note, but if the transparent input was omitted and full-transaction enhancement is suppressed, the wallet may never mark the transparent UTXO spent. The transparent balance can remain overstated and later coin selection can attempt to spend an already-spent outpoint.

Other effects include incomplete restored history, missing short-lived transparent receipts, and unavailable full-transaction or fee details. Transactions created locally are less exposed because their raw transaction is already known; seed restoration removes that protection.

The existing address-UTXO refresh is not a complete substitute. It discovers current unspent outputs but does not identify the spending transaction or infer spentness from an output disappearing, and outputs received and spent between queries can be missed.

Options

  1. In PIR mode, request TRANSPARENT, SAPLING, ORCHARD, and IRONWOOD in the existing GetBlockRange call. This requires no additional RPC, but includes transparent-only transactions and increases compact-sync bandwidth.
  2. Add a required, versioned Unknown | NoTransparentBundle | HasTransparentBundle classification to the controlled PIR dataset. This has negligible bandwidth cost but trusts the PIR snapshot producer for classification.
  3. Keep ordinary transaction-ID enhancement for compact transactions whose transparent completeness is unknown. This preserves correctness but leaks the transaction ID.
  4. Explicitly accept incomplete transparent state as a documented limitation. This should not be the silent default.

Adding a new optional field to CompactTx is not sufficient because public RPC servers are not controlled by this project and older producers would omit it.

Required invariant

Empty vin and vout may be interpreted as "no transparent bundle" only when the block source has established complete transparent coverage. Unknown or legacy sources must fail closed to ordinary transaction-ID enhancement. Coinbase transactions must also be excluded because their null transparent input is deliberately omitted.

Acceptance criteria

  • The scanner does not infer transparent absence from empty optional fields without completeness provenance.
  • Custom and cached block sources cannot accidentally claim completeness by default.
  • Unsupported or legacy sources retain standard enhancement instead of failing wallet sync.
  • Tests cover a mixed Ironwood/transparent transaction with omitted vin/vout, unknown source completeness, complete source data, and coinbase handling.
  • Documentation states the bandwidth, privacy, compatibility, and trust tradeoffs of the chosen solution.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions