- prohibit negative chain value pools [ZIP-209], and
- restrict the creation of new money to a specific number of coins in each coinbase transaction. [Spec Section 3.4](https://zips.z.cash/protocol/protocol.pdf#transactions)
-`transaction value pool` - The unspent *input* value in a transaction. Inputs add value, outputs remove value, and value balances modify value. The pool represents the sum of transparent and shielded inputs, minus the sum of transparent and shielded outputs.
-`value balance` - The change in a transaction's value pool. There is a separate value balance for each transparent and shielded pool.
-`transparent value balance` - The change in the transaction value pool, due to transparent inputs and outputs. The sum of the UTXOs spent by transparent inputs in `tx_in` fields, minus the sum of newly created outputs in `tx_out` fields.
-`sprout value balance` - The change in the transaction value pool, due to sprout JoinSplits. The sum of all `v_sprout_new` fields, minus the sum of all `v_sprout_old` fields.
-`sapling value balance` - The change in the transaction value pool, due to sapling Spends and Outputs. Equal to the `valueBalanceSapling` field.
-`orchard value balance` - The change in the transaction value pool, due to orchard Actions. Equal to the `valueBalanceOrchard` field.
-`remaining transaction value` - The unspent value in the transaction value pool. The sum of the transparent and shielded value balances in each transaction. This value is equal to the `transaction value pool` after we know the values of all the input UTXOs.
-`coinbase transaction` - A transaction which spends newly created value (coinbase), and the remaining value of other transactions in its block (miner fees). Coinbase transactions do not have any other inputs, so they can't spend the outputs of other transactions.
## Chain Value Pools
[definitions-chain]: #definitions-chain
**Note: chain value pools and transaction value balances have opposite signs.**
-`chain value pool balance` - The total value of unspent *outputs* in the chain, for each transparent and shielded pool. The sum of all block chain value pool changes in the chain. Each of the transparent, sprout, sapling, and orchard chain value pool balances must be non-negative.
-`block chain value pool change` - The change in the chain value pools caused by a block. The *negative* sum of all the value balances in each block.
Each of the chain value pools can change its value with every block added to the chain. This is a state feature and Zebra handle this in the `zebra-state` crate. We propose to store the pool values for the finalized tip height on disk.
If any of the "Sprout chain value pool balance", "Sapling chain value pool balance", or "Orchard chain value pool balance" would become negative in the block chain created as a result of accepting a block, then all nodes MUST reject the block as invalid.
Nodes MAY relay transactions even if one or more of them cannot be mined due to the aforementioned restriction.
https://zips.z.cash/zip-0209#specification
### Transparent Transaction Value Pool & Remaining Value
Transparent inputs to a transaction insert value into a transparent transaction value pool associated with the transaction, and transparent outputs remove value from this pool.
In Zebra, the remaining value in non-coinbase transactions is not assigned to any particular pool, until a miner spends it as part of a coinbase output.
`v_sprout_old` takes value from the transparent transaction value pool and `v_sprout_new` adds value to the transparent transaction value pool . As a result, `v_sprout_old` is treated like an output value, whereas `v_sprout_new` is treated like an input value.
As defined in [ZIP-209], the Sprout chain value pool balance for a given block chain is the sum of all `v_sprout_old` field values for transactions in the block chain, minus the sum of all `v_sprout_new` fields values for transactions in the block chain.
If the Sprout chain value pool balance would become negative in the block chain created as a result of accepting a block, then all nodes MUST reject the block as invalid.
A positive Sapling balancing value takes value from the Sapling transaction value pool and adds it to the transparent transaction value pool. A negative Sapling balancing value does the reverse. As a result, positive `vbalanceSapling` is treated like an input to the transparent transaction value pool, whereas negative `vbalanceSapling` is treated like an output from that pool.
As defined in [ZIP-209], the Sapling chain value pool balance for a given block chain is the negation of the sum of all `valueBalanceSapling` field values for transactions in the block chain.
If the Sapling chain value pool balance would become negative in the block chain created as a result of accepting a block, then all nodes MUST reject the block as invalid.
Orchard introduces Action transfers, each of which can optionally perform a spend, and optionally perform an output. Similarly to Sapling, the net value of Orchard spends minus outputs in a transaction is called the Orchard balancing value, measured in zatoshi as a signed integer `vbalanceOrchard`.
`vbalanceOrchard` is encoded in a transaction as the field `valueBalanceOrchard`. If a transaction has no Action descriptions, `vbalanceOrchard` is implicitly zero. Transaction fields are described in § 7.1 ‘Transaction Encoding and Consensus’ on p. 116.
A positive Orchard balancing value takes value from the Orchard transaction value pool and adds it to the transparent transaction value pool. A negative Orchard balancing value does the reverse. As a result, positive `vbalanceOrchard` is treated like an input to the transparent transaction value pool, whereas negative `vbalanceOrchard` is treated like an output from that pool.
Similarly to the Sapling chain value pool balance defined in [ZIP-209], the Orchard chain value pool balance for a given block chain is the negation of the sum of all `valueBalanceOrchard` field values for transactions in the block chain.
If the Orchard chain value pool balance would become negative in the block chain created as a result of accepting a block , then all nodes MUST reject the block as invalid.
Some of these consensus rules are derived from Bitcoin, so they may not be documented in the Zcash Specification.
### Coinbase Transactions
In this design, we assume that all coinbase outputs are valid, to avoid checking the newly created coinbase value, and the miner fees.
The coinbase value and miner fee rules will be checked as part of a future design.
### Exceptions and Edge Cases
Value pools and value balances include the value of all unspent outputs, regardless of whether they can actually be spent.
For example:
* transparent outputs which have unsatisfiable lock scripts
* shielded outputs which have invalid private keys
However, some value is not part of any output:
* if created value or miner fees are not spent in a coinbase transaction, they are destroyed
* since coinbase transaction output values are rounded to the nearest zatoshi, any fractional part of miner-controlled or funding stream outputs is destroyed by rounding
Therefore:
* the total of all chain value pools will always be strictly less than `MAX_MONEY`, and
* the current total of all chain value pools will always be less than or equal to the number of coins created in coinbase transactions.
These properties are implied by other consensus rules, and do not need to be checked separately.
- Code will be located in a new file: `zebra-chain/src/value_balance.rs`.
- Supported operators apply to all the `Amount`s inside the type: `+`, `-`, `+=`, `-=`, `sum()`.
- Implementation of the above operators are similar to the ones implemented for `Amount<C>` in `zebra-chain/src/amount.rs`. In particular, we want to return a `Result` on them so we can error when a constraint is violated.
- We will use `Default` to represent a totally empty `ValueBalance`, this is the state of all pools at the genesis block.
```rust
#[serde(bound = "C: Constraint")]
struct ValueBalance<C=NegativeAllowed> {
transparent: Amount<C>,
sprout: Amount<C>,
sapling: Amount<C>,
orchard: Amount<C>,
}
impl ValueBalance {
/// [Consensus rule]: The remaining value in the transparent transaction value pool MUST be nonnegative.
///
/// This rule applies to Block and Mempool transactions.
.expect("Each block should have at least one coinbase transaction")
}
```
### Check the remaining transaction value consensus rule
- Do the check in `zebra-consensus/src/transaction.rs`
- Make the check part of the [basic checks](https://github.com/ZcashFoundation/zebra/blob/f817df638b1ba8cf8c261c536a30599c805cf04c/zebra-consensus/src/transaction.rs#L168-L177)
```rust
..
// Check the remaining transaction value consensus rule:
- Create a transaction that has a negative remaining value.
- Test that the transaction fails the verification in `Transaction::value_balance()`
- To avoid passing the utxo we can have `0` as the amount of the transparent pool and some negative shielded pool.
### Prop tests
- Create a chain strategy that ends up with a valid value balance for all the pools (transparent, sprout, sapling, orchard)
- Test that the amounts are all added to disk.
- Add new blocks that will make each pool became negative.
- Test for constraint violations in the value balances for each case.
- Failures should be at `update_chain_state_with()`.
- Test consensus rules success and failures in `revert_chain_state_with()`
- TODO: how?
- serialize and deserialize `ValueBalance` using `IntoDisk` and `FromDisk`
### Manual tests
- Zebra must sync up to tip computing all value balances and never breaking the value pool rules.
## Future Work
[future-work]: #future-work
Add an extra state request to verify the speculative chain balance after applying a Mempool transaction. (This is out of scope for our current NU5 and mempool work.)
Note: The chain value pool balance rules apply to Block transactions, but they are optional for Mempool transactions:
> Nodes MAY relay transactions even if one or more of them cannot be mined due to the aforementioned restriction.
https://zips.z.cash/zip-0209#specification
Since Zebra does chain value pool balance validation in the state, we want to skip verifying the speculative chain balance of Mempool transactions.