Skip to content
Draft
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
37 changes: 37 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,43 @@ on `PATH` at run time.

PRs MUST NOT introduce new warnings from `cargo +beta clippy --tests --all-features --all-targets`. Preexisting beta clippy warnings need not be resolved, but new ones introduced by a PR will block merging.

## Testing Scope: Unit Tests Only

**This repository does NOT host integration tests or scenario tests.** Those
live in [zcash/integration-tests](https://github.com/zcash/integration-tests),
which drives the whole Z3 stack (`zebrad` + `zainod` + `zallet`) over real RPC
against a regtest chain. Do not add a test here that stands up a chain, mines
blocks, sends a transaction end to end, or otherwise asserts on the behaviour of
the stack as a whole; it belongs there.

What belongs here is unit tests: fast, in-process, no chain, no network, no
fixture wallet seeded by mining. Test the pure logic a function owns, at the
boundary where a decision is actually made:

- Pure derivations and policy decisions (e.g. "a transparent `fromaddress`
yields a spend policy that permits only that address's UTXOs, and no shielded
pool").
- Parsing, validation, and error mapping of RPC parameters.
- Serialization and response shapes.
- Property tests (`proptest`) over the above where the input space is wide.
Prefer a property over a fixture: derive the key material from an arbitrary
seed rather than a hardcoded one, so the property is established for every
input rather than for the one that happened to be written down.

Assert on the whole of a value rather than enumerating its parts, so a test does
not silently stop covering a variant added later. Prefer "the permitted-pool set
is empty" to a loop over today's three pools.

If a piece of logic can only be tested by building a chain, that is usually a
sign it should be extracted into a pure function that CAN be unit-tested, with
the remaining end-to-end behaviour covered in `integration-tests`. Prefer
extracting.

A change to this repository that needs new stack-level coverage should be paired
with a PR to `integration-tests`, referenced from the description, and wired via
a `ZIT-Revision: <branch>` line so this repository's CI exercises it (see the
Cross-Repository CI Integration docs).

## Auditing Dependency Version Bumps

This applies to any change to a pinned dependency version: the `Dockerfile` and `Dockerfile.stagex` apt pins and base-image digests, and by extension any other pinned external artifact.
Expand Down
58 changes: 58 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,51 @@ be considered breaking changes.

### Added

- Three account-based transaction methods. Where `z_sendmany` takes an address as
its source of funds, these take an account UUID together with a `fund_source`
naming where within the account the funds may be drawn from: `"orchard"`,
`"sapling"`, `"any_transparent"`, or an explicit array of transparent addresses.
A source that cannot cover the payment reports insufficient funds rather than
quietly reaching into another pool.
- `z_proposetransaction` proposes a transaction and returns it as a PCZT, along
with the privacy policy required to execute it. Nothing is signed, no proof is
generated, and no spending key is touched, so the caller can inspect what the
transaction would reveal and then decide, instead of having to commit to a
privacy policy up front as `z_sendmany` requires.
- `z_finalizetransaction` signs and broadcasts a PCZT from
`z_proposetransaction`. The privacy policy the caller supplies is held against
the one recorded for that PCZT at proposal time, so a caller cannot acknowledge
a weaker policy than the transaction actually requires.
- `z_sendfromaccount` does both in one shot, returning the txid. Because there is
no proposal to review, the privacy policy is required rather than optional.
- `fund_source: "orchard"` permits the Ironwood pool as well as Orchard. Ironwood
notes are Orchard-shaped, and once NU6.3 activates an account's
Orchard-receiver funds are held there rather than in the legacy Orchard pool,
so restricting the source to Orchard alone would report insufficient funds for
an account whose Orchard money is all in Ironwood.
- `z_sendmany` can now spend transparent funds, making transparent-to-transparent
transfers possible. Previously it passed a shielded-only spend policy to the
proposal builder, so no transparent input could ever be selected, and the
`AllowFullyTransparent` privacy policy was unreachable.
- Transparent funds are spendable only when `fromaddress` names a transparent
address. Input selection then draws on that address's UTXOs alone, so a
shielded send can never silently reach into transparent funds, and the named
address is not linked to the account's other transparent receivers. Every
other source remains shielded-only, unchanged. (`ANY_TADDR` as a source is
still unsupported.)
- Coinbase outputs are not spendable this way: consensus requires them to be
spent to a single shielded output, which remains `z_shieldcoinbase`'s job. A
transparent spend therefore requires a non-coinbase UTXO.
- A transaction that both spends transparent funds and has transparent
recipients or change requires the `AllowFullyTransparent` privacy policy. A
transparent source paying a shielded recipient still only needs
`AllowRevealedSenders`.
- Change on a fully transparent send stays in the transparent pool, at an
internal-scope (BIP 44) change address, and a fresh one is reserved per
transaction so that consecutive sends cannot be linked through a reused
change address. Transparent change is emitted only when the transaction has
no shielded input or output at all; any send with a shielded component
continues to shield its change exactly as before.
- The `zebra` chain backend (and the `zaino` backend's read-state-service mode)
now support regtest. The read-state service builds a Zebra Regtest network
whose network-upgrade activation heights mirror the wallet's configured
Expand Down Expand Up @@ -39,6 +84,19 @@ be considered breaking changes.

### Fixed

- `get_account_for_address` now resolves a bare transparent address to the account
that owns it. It previously compared the address against the account's listed
addresses, which are unified addresses; a transparent receiver never compares
equal to the unified address it belongs to, so passing a `taddr` as a payment
source failed with "Invalid from address, no payment source found for address."
- The wallet database connection now implements
`InputSource::select_spendable_transparent_outputs` and
`WalletWrite::reserve_next_n_internal_addresses`. Both are defaulted in their
traits to an `unimplemented!()`, so omitting them compiled cleanly and instead
panicked the wallet process at run time: the first on selecting any transparent
input, the second on producing transparent change. Nothing reached either while
transparent spending was impossible; both are on the path of any transparent
spend, and of the forthcoming `z_sendfromaccount` and `z_proposetransaction`.
- `steady_state` sync no longer crashes the whole wallet when the backend's best
chain reorgs away a block the wallet had already stored (`BlockConflict`).
Previously this error wasn't recognized as retryable, so it propagated as a
Expand Down
98 changes: 98 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ serde = { version = "1", features = ["serde_derive"] }
semver = "1"
serde_json = { version = "1", features = ["arbitrary_precision", "raw_value"] }
toml = "0.8"
pczt = { version = "0.7", features = ["prover", "signer"] }
zcash_address = "0.13.0-pre.0"

# Randomness
Expand Down Expand Up @@ -169,6 +170,7 @@ tonic = "0.14"
# Do not edit these revs by hand.
equihash = { git = "https://github.com/zcash/librustzcash.git", rev = "29c7fb28889a69df15b44fc9465cf4a464f766e9" }
f4jumble = { git = "https://github.com/zcash/librustzcash.git", rev = "29c7fb28889a69df15b44fc9465cf4a464f766e9" }
pczt = { git = "https://github.com/zcash/librustzcash.git", rev = "29c7fb28889a69df15b44fc9465cf4a464f766e9" }
transparent = { package = "zcash_transparent", git = "https://github.com/zcash/librustzcash.git", rev = "29c7fb28889a69df15b44fc9465cf4a464f766e9" }
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "29c7fb28889a69df15b44fc9465cf4a464f766e9" }
zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "29c7fb28889a69df15b44fc9465cf4a464f766e9" }
Expand Down
Loading
Loading