Commit Graph

20 Commits

Author SHA1 Message Date
teor f09f2a9022
Check remaining transaction value & make value balance signs match the spec (#2566)
* Make Amount arithmetic more generic

To modify generated amounts, we need some extra operations on `Amount`.

We also need to extend existing operations to both `NonNegative` and
`NegativeAllowed` amounts.

* Add a constrain method for ValueBalance

* Derive Eq for ValueBalance

* impl Neg for ValueBalance

* Make some Amount arithmetic expectations explicit

* Explain why we use i128 for multiplication

And expand the overflow error details.

* Expand Amount::sum error details

* Make amount::Error field order consistent

* Rename an amount::Error variant to Constraint, so it's clearer

* Add specific pool variants to ValueBalanceError

* Update coinbase remaining value consensus rule comment

This consensus rule was updated recently to include coinbase transactions,
but Zebra doesn't check block subsidy or miner fees yet.

* Add test methods for modifying transparent values and shielded value balances

* Temporarily set values and value balances to zero in proptests

In both generated chains and proptests that construct their own transactions.

Using zero values reduces value calculation and value check test coverage.
A future change will use non-zero values, and fix them so the check passes.

* Add extra fields to remaining transaction value errors

* Swap the transparent value balance sign to match shielded value balances

This makes the signs of all the chain value pools consistent.

* Use a NonNegative constraint for transparent values

This fix:
* makes the type signature match the consensus rules
* avoids having to write code to handle negative values

* Allocate total generated transaction input value to outputs

If there isn't enough input value for an output, set it to zero.

Temporarily reduce all generated values to avoid overflow.
(We'll remove this workaround when we calculate chain value balances.)

* Consistently use ValueBalanceError for ValueBalances

* Make the value balance signs match the spec

And rename and document methods so their signs are clearer.

* Convert amount::Errors to specific pool ValueBalanceErrors

* Move some error changes to the next PR

* Add extra info to remaining transaction value errors (#2585)

* Distinguish between overflow and negative remaining transaction value errors

And make some error types cloneable.

* Add methods for updating chain value pools (#2586)

* Move amount::test to amount::tests:vectors

* Make ValueBalance traits more consistent with Amount

- implement Add and Sub variants with Result and Assign
- derive Hash

* Clarify some comments and expects

* Create ValueBalance update methods for blocks and transactions

Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-09 14:22:26 -03:00
teor bfc3e4a46c
Add an OrderedUtxo type for transparent spend validation (#2502)
* Add an OrderedUtxo type for validation of spends within a block

This change allows us to check that transparent spends use outputs from
earlier in their block. (But we don't actually do that check yet.)

We need to keep the order of UTXOs when we're contextually verifying
each new block that is added to a chain. But the block order is
irrelevant for UTXOs stored in the state.

* Take ownership in utxos_from_ordered_utxos

* Delete a confusing comment
2021-07-19 10:52:32 -03:00
Alfredo Garcia f7026d728f
move `Utxo` type to zebra-chain (#2481) 2021-07-12 12:49:33 +10:00
Conrado Gouvea 40e350c342
Always compute sighash with librustzcash (#2469)
* Always use librustzcash for sighash and remove old sighash code

Also added ZIP-143 test vectors

* Remove librustzcash_sighash test that is no longer needed
2021-07-09 09:55:08 +10:00
Conrado Gouvea fdfa3cbdc6
Add ZIP-244 signature hash support (#2165)
* ZIP-244 sighash implementation using librustzcash

* ZIP-244: fix sighash test; add roundtrip test; update vectors

* Improvements from review; renamed sighash::Hash to SigHash
2021-07-07 08:27:10 +10:00
Janito Vaqueiro Ferreira Filho f5bc5279ca
Validate V5 transactions with Sapling shielded data (#2437)
* Make `verify_sapling_shielded_data` more generic

Prepare to support V5 transactions which have a shared anchor.

* Verify Sapling shielded data in V5 transactions

Call the `verify_sapling_shielded_data` method and add the respective
asynchronous checks to the set of V5 checks.

* Fix expect message in V4 transaction test

It was using the same message as the previous test, even though the test
searches with different criteria.

* Test V5 transaction with Sapling spends

Create a fake V5 transaction that has Sapling spends and check that the
verifier accepts the transaction.

* Ignore rejected V5 transaction test for now

Because now it needs the `sighash` implementation for V5 to be ready.

* Reference V5 `sighash` PR in comment

So that it is easier to check if it's possible to remove the
`should_panic` or not.

Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>

* Remove `sapling shielded pool` TODO

V5 transactions now have Sapling shielded pool properly validated.

* Link to some extra issues in TODO comment

Some other issues are also necessary for full V5 validation.

* Add a TODO in the main code to fix the tests

Some tests are blocked due to missing features required for full V5
validation. Once those features are implemented, they should be updated
to remove the `#[should_panic]` attribute so that they actually run and
check the code correctly.

Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-07-02 13:48:53 -03:00
Alfredo Garcia e4ab01dde0
ZIP-211: Validate Disabling Addition of New Value to the Sprout Value Pool (#2399)
* add disabled sprout pool check

* change method name

* change error name

* fix typo

* make the success test case in other tx than the coinbase

* use new `height` method instead of deriving `PartialOrd` in `NetworkUpgrade`

* move check of network upgrade into function, rename, docs

* increase test coverage

* fix comment
2021-07-02 09:03:34 +10:00
Janito Vaqueiro Ferreira Filho 76fca5f32f
Refactor validation of Sapling shielded data in `transaction::Verifier` (#2419)
* Refactor to create `verify_sapling_shielded_data`

Move the code to verify Sapling shielded data into a new helper method
that returns `AsyncChecks`.

* Test verifying a Sapling transaction with spends

Use the test vectors to find a transaction that has Sapling spends and
test if it the verifier considers it valid.

* Create a helper method to list test transactions

Transforms the block test vectors into a list of transactions and block
heights for each transaction.

* Use new helper function in V4 Sapling spend test

Also use the block height for that transaction as specified in the test
vector.

* Test V4 tx. with Sapling outputs but no spends

Find a transaction V4 vector that has Sapling outputs but no spends, and
check that the verifier accepts it.
2021-07-01 12:17:37 +10:00
Janito Vaqueiro Ferreira Filho f33923f12f
Create a shared Tokio runtime for tests (#2397)
* Add a `zebra_test::RUNTIME` shared runtime

Create a lazily instantiated Tokio runtime that can be shared by tests.

* Split tests that require a shared runtime

Split two tests that were previously in one because of the need to share
a single Tokio runtime. With the `zebra_test::RUNTIME`, they can now
share the runtime without having to be a single test.
2021-07-01 10:30:31 +10:00
teor 7c44ee2ebe
Release Blocker: Stop trying to verify coinbase inputs using the script verifier (#2404)
* Stop trying to verify coinbase inputs using the script verifier

And create tests to catch similar bugs earier.

* Use Testnet in NU5 tests that temporarily should_panic

We've marked these tests as should_panic until there is a NU5 activation
height. But Testnet will have an activation height first, so we should
prefer it in the tests. (Or use both networks.)
2021-06-29 10:49:40 +10:00
Alfredo Garcia c06cd19239
Update `has_inputs_and_outputs()` for new consensus rules (#2398)
* update the has_inputs_and_outputs() to new rules

* apply clippy suggestions

* add some TODOs
2021-06-29 08:28:49 +10:00
Janito Vaqueiro Ferreira Filho fdeb6d5ec8
Refactor Sprout Join Split validation by transaction verifier (#2371)
* Refactor to create `verify_sprout_shielded_data`

Move the join split verification code into a new
`verify_sprout_shielded_data` helper method that returns an
`AsyncChecks` set.

* Test if signed V4 tx. join splits are accepted

Create a fake V4 transaction with a dummy join split, and sign it
appropriately. Check if the transaction verifier accepts the
transaction.

* Test if unsigned V4 tx. joinsplit data is rejected

Create a fake V4 transaction with a dummy join split. Do NOT sign this
transaction's join split data, and check that the verifier rejects the
transaction.

* Join tests to share Tokio runtime

Otherwise one of the tests might fail incorrectly because of a
limitation in the test environment. `Batch` services spawn a task in the
Tokio runtime, but separate tests can have separate runtimes, so sharing
a `Batch` service can lead to the worker task only being available for
one of the tests.
2021-06-25 00:47:39 +00:00
Janito Vaqueiro Ferreira Filho 8ed50e578d
Validate transparent inputs and outputs in V5 transactions (#2302)
* Add missing documentation

Document methods to describe what they do and why.

* Create an `AsyncChecks` type alias

Make it simpler to write the `FuturesUnordered` type with boxed futures.
This will also end up being used more when refactoring to return the
checks so that the `call` method can wait on them.

* Create `verify_transparent_inputs_and_outputs`

Refactors the verification of the transparent inputs and outputs into a
separate method.

* Refactor transparent checks to use `call_all`

Instead of pushing the verifications into a stream of unordered futures,
use the `ServiceExt::call_all` method to build an equivalent stream
after building a stream of requests.

* Replace `CallAll` with `FuturesUnordered`

Make it more consistent with the rest of the code, and make sure that
the `len()` method is available to use for tracing.

Co-authored-by: teor <teor@riseup.net>

* Refactor to move wait for checks into a new method

Allow the code snipped to be reused by other transaction
version-specific check methods.

* Verify transparent inputs in V5 transactions

Use the script verifier to check the transparent inputs in a V5
transaction.

* Check `has_inputs_and_outputs` for all versions

Check if a transaction has inputs and outputs, independently of the
transaction version.

* Wait for checks in `call` method

Refactor to move the repeated code into the `call` method. Now the
validation methods return the set of asynchronous checks to wait for.

* Add helper function to mock transparent transfers

Creates a fake source UTXO, and then the input and output that represent
spending that UTXO. The initial UTXO can be configured to have a script
that either accepts or rejects any spend attempt.

* Test if transparent V4 transaction is accepted

Create a fake V4 transaction that includes a fake transparent transfer
of funds. The transfer uses a script to allow any UTXO to spend it.

* Test transaction V4 rejection based on script

Create a fake transparent transfer where the source UTXO has a script
that rejects spending. The script verifier should not accept this
transaction.

* Test if transparent V5 transaction is accepted

Create a mock V5 transaction that includes a transparent transfer of
funds. The transaction should be accepted by the verifier.

* Test transaction V5 rejection based on script

Create a fake transparent transfer where the source UTXO has a script
that rejects spending. The script verifier should not accept this
transaction.

* Update `Request::upgrade` getter documentation

Simplify it so that it won't become updated when #1683 is fixed.

Co-authored-by: teor <teor@riseup.net>
2021-06-23 11:54:00 +10:00
Janito Vaqueiro Ferreira Filho 0e89236405
Reject V5 transactions before NU5 activation (#2285)
* Add a `Transaction::version` getter

Returns the version of the transaction as a `u32`.

* Add `Transaction::is_overwintered` helper method

Returns if the `fOverwintered` flag should be set for the transaction's
version.

* Use new helpers to serialize transaction version

Reduce the repeated code and make it less error-prone with future
changes.

* Add getter methods to `transaction::Request` type

Refactor to move the type deconstruction code into the `Request` type.
The main objective is to make it easier to split the call handler into
methods that receive the request directly.

* Refactor to create `verify_v4_transaction` helper

Split the code specific to V4 transactions into a separate helper
method.

* Create `verify_v5_transaction` helper method

Prepare a separate method to have the validation code.

* Add `UnsupportedByNetworkUpgrade` error variant

An error for when a transaction's version isn't supported by the network
upgrade of the block it's included or for the current network upgrade if
the transaction is for the mempool.

* Verify a V5 transaction's network upgrade

For now, only NU5 supports V5 transactions.

* Test that V5 transaction is rejected on Canopy

Create a fake V5 transaction and try to verify it using a block height
from Canopy's activation. The verifier should reject the transaction
with an error saying that the network upgrade does not support that
transaction version.

* Test if V5 tx. is accepted after NU5 activation

Create a fake V5 transaction and pretend it is placed in a block that
has a height after the NU5 activation. The test should succeed, but
since the NU5 activation height has not been specified yet (neither for
the testnet nor the mainnet), for now this test is marked as
`should_panic`.

* Add `TODO` comment to the code

Add more detail to what's left to do, and link to the appropriate PRs.

* Use `u32` to store transaction version

Use a type consistent with how the version is specified.

Co-authored-by: teor <teor@riseup.net>

Co-authored-by: teor <teor@riseup.net>
2021-06-15 10:15:59 +10:00
teor 8ebb415e7c Clippy: remove needless borrows 2021-06-07 18:33:58 -04:00
Janito Vaqueiro Ferreira Filho 2e0318878a
Further test new transaction consensus rules (#2246)
* Add a `at_least_one!` macro for testing

Similar to the `vec!` macro, but doesn't allow creating an empty list.

* Test if `has_inputs_and_outputs` considers actions

Create a dummy transaction with no inputs and no outputs, and add a
dummy Orchard action to it. The `check::has_inputs_and_outputs`
should succeed, because the consensus rule considers having Orchard
actions as having inputs and/or outputs.

* Refactor to create helper function

Move the code to create a fake Orchard shielded data instance to a
helper function in `zebra_chain::transaction::arbitrary`, so that other
tests can also use it.

* Test coinbase V5 transaction with enable spends

A V5 coinbase transaction that has Orchard shielded data MUST NOT have
the enable spends flag set.

* Test if coinbase without enable spends is valid

A coinbase transaction with Orchard shielded data and without the enable
spends flag set should be valid.

* Add a security comment about the `at_least_one!` macro

This macro must not be used outside tests, because it allows memory denial
of service.

Co-authored-by: teor <teor@riseup.net>
2021-06-07 12:02:18 +10:00
Janito Vaqueiro Ferreira Filho b44d81669f
Move the check in `transaction::check::sapling_balances_match` to `V4` deserialization (#2234)
* Implement `PartialEq<i64>` for `Amount`

Allows to compare an `Amount` instance directly to an integer.

* Add `SerializationError::BadTransactionBalance`

Error variant representing deserialization of a transaction that doesn't
conform to the Sapling consensus rule where the balance MUST be zero if
there aren't any shielded spends and outputs.

* Validate consensus rule when deserializing

Return an error if the deserialized V4 transaction has a non-zero value
balance but doesn't have any Sapling shielded spends nor outputs.

* Add consensus rule link to field documentation

Describe how the consensus rule is validated structurally by
`ShieldedData`.

* Clarify that `value_balance` is zero

Make the description more concise and objective.

Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>

* Update field documentation

Include information about how the consensus rule is guaranteed during
serialization.

Co-authored-by: teor <teor@riseup.net>

* Remove `check::sapling_balances_match` function

The check is redundant because the respective consensus rule is
validated structurally by `ShieldedData`.

* Test deserialization of invalid V4 transaction

A transaction with no Sapling shielded spends and no outputs but with a
non-zero balance value should fail to deserialize.

* Change least-significant byte of the value balance

State how the byte index is calculated, and change the least
significant-byte to be non-zero.

Co-authored-by: teor <teor@riseup.net>
2021-06-04 08:53:00 +10:00
Janito Vaqueiro Ferreira Filho db0cdb74ff
Update `has_inputs_and_outputs` to check V5 transactions (#2229)
* Fix documentation comment

Was missing a slash to become documentation.

* Add documentation link to type reference

Just to help navigation a bit.

* Implement `Transaction::orchard_actions()` getter

Returns an iterator to iterator over the actions in the Orchard shielded
data (if there is one, otherwise it returns an empty iterator).

* Add V5 support for `has_inputs_and_outputs`

Checks if the transaction has Orchard actions. If it does, it is
considered to have inputs and outputs.

* Refactor transaction test vectors

Make it easier to reuse the fake V5 transaction converter in other test
vectors.

* Move helper function to `zebra-chain` crate

Place it together with some other helper functions, including the one
that actually creates the fake V5 transaction.

* Test transaction with no inputs

`check::has_inputs_and_outputs` should return an error indicating that
the transaction has no inputs.

* Test transaction with no outputs

`check::has_inputs_and_outputs` should return an error indicating that
the transaction has no outputs.

* Note that transaction is fake in `expect` message

Should make the message easier to find, and also gives emphasis to the
fact that the transaction is a fake conversion to V5.

Co-authored-by: teor <teor@riseup.net>

Co-authored-by: teor <teor@riseup.net>
2021-06-02 11:32:52 +10:00
Alfredo Garcia 29893f2b9b
Validate nConsensusBranchId (#2100)
* validate nConsensusBranchId
* add tests

* fix bug in transaction_to_fake_v5

Co-authored-by: teor <teor@riseup.net>
2021-05-10 01:31:45 +00:00
Alfredo Garcia 75d29aca24
Add V5 transparent and sapling to transaction::check, add missing coinbase PrevOut check (#2070)
* validate sapling v5 tx

* Make itertools dependency optional

We only need itertools when the `proptest-impl` feature is enabled.

* Check if V4 and V5 coinbase transactions contain PrevOut transparent inputs

This is a bugfix on V4 transaction validation. The PrevOut consensus
rule was not explicitly stated in the Zcash spec until April 2021.
(But it was implied by Bitcoin, and partially implemented by Zebra.)

Also do the shielded sapling input check for V5 transactions.

* Add spec and orchard TODOs to has_inputs_and_outputs

Also make the variable names match the spec.

* Sort transaction functions to match v5 data order

* Simplify transaction input and output checks

Move counts or iterators into `Transaction` methods, so we can remove
duplicate code, and make the consensus rule logic clearer.

* Update sapling_balances_match for Transaction v5

- Quote from the spec
- Explain why the function is redunant for v5
- Rename the function so it's clear that it is sapling-specific

Co-authored-by: teor <teor@riseup.net>
2021-04-28 10:43:00 +10:00