Commit Graph

74 Commits

Author SHA1 Message Date
Conrado Gouvea dff25473aa
refactor: document coinbase rules, refactor to ease understanding (#4056)
* refactor: document coinbase rules, refactor to ease understanding

* Update zebra-consensus/src/block/check.rs

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

* remove no longer used contains_prevout_input()

* remove unused CoinbaseHasPrevOutInput

* update coinbase description in documentation

Co-authored-by: teor <teor@riseup.net>
2022-04-20 09:31:12 +00:00
Marek 683b88c819
Support large block heights (#3401)
* Support large block heights

* Document consensus rules referring to expiry heights

* Refactor the docs

* Apply suggestions from code review

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

* Fix the formatting of an error message

* refactor: Simplify coinbase expiry code so the consensus rule is clear (#3408)

* Fix some outdated TODO comments

* refactor(coinbase expiry): Simplify the code so consensus rule is clear

* Fix the formatting of an error message

* Remove a redundant comment

Co-authored-by: Marek <mail@marek.onl>

Co-authored-by: Marek <mail@marek.onl>

* Check the max expiry height at parse time

* Test that 2^31 - 1 is the last valid height

* Add tests for nExpiryHeight

* Add tests for expiry heights of V4 transactions

* Add tests for V5 transactions

Co-authored-by: teor <teor@riseup.net>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-02-11 00:32:57 +00:00
Alfredo Garcia 2f46d698dd
Validate non coinbase expiration height (#3103)
* validate non coinbase expiration height

* change var name

* move checks to transaction verifier

* Add variants and debug fields to transaction expiry errors

* Fix a failing existing test

Co-authored-by: teor <teor@riseup.net>
2021-11-26 00:37:24 +00:00
Alfredo Garcia a61eae0065
Validate miner transaction fees (#3067)
* validate consensus rule: negative fee not allowed

* fix a test TODO

* fix imports

* move import back

* fix panic text

* join consensus rule check code

* match assertion better in tests

* fix test

* fix consensus rule validation

* remove panics

* Delete a TODO

Co-authored-by: teor <teor@riseup.net>
2021-11-24 03:36:17 +00:00
teor 8e49663e31
Sum transaction miner fees in the block verifier (#3093)
Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-11-23 12:31:56 -03:00
Janito Vaqueiro Ferreira Filho ec2c980bb1
Validate transaction lock times (#3060)
* Create a `LockTime::unlocked` helper constructor

Returns a `LockTime` that is unlocked at the genesis block.

* Return `Option<LockTime>` from `lock_time` method

Prepare to return `None` for when a transaction has its lock time
disabled.

* Return `None` instead of zero `LockTime`

Because a zero lock time means that the transaction was unlocked at the
genesis block, so it was never actually locked.

* Rephrase zero lock time check comment

Clarify that the check is not redundant, and is necessary for the
genesis transaction.

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

* Add a `transparent::Input::sequence` getter method

Retrieve a transparent input's sequence number.

* Check if lock time is enabled by a sequence number

Validate the consensus rule that the lock time is only enabled if at
least one transparent input has a value different from `u32::MAX` as its
sequence number.

* Add more Zcash specific details to comment

Explain the Zcash specific lock time behaviors.

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

* Add `time` field to `Request::Block` variant

The block time to use to check if the transaction was unlocked and
allowed to be included in the block.

* Add `Request::block_time` getter

Returns the block time for the block that owns the transaction being
validated or the current time plus a tolerance for mempool transactions.

* Validate transaction lock times

If they are enabled by a transaction's transparent input sequence
numbers, make sure that they are in the past.

* Add comments with consensus rule parts

Make it easier to map what part of the consensus rule each match arm is
responsible for.

Co-authored-by: teor <teor@riseup.net>
2021-11-23 05:53:53 +00:00
Alfredo Garcia dbd49a3f00
Validate coinbase expiration height (#3082)
* add testnet test blocks around nu5

* validate coinbase expiration height

* change const name and doc

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

* change commit location

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

* use pre Nu5 rules when there is no activation height

* add sapling final root to nu5 test vectors

* fix tests

Co-authored-by: teor <teor@riseup.net>
2021-11-23 05:17:05 +00:00
teor 1df3bdb089
Check MAX_BLOCK_SIGOPS in the block verifier (#3049)
* Cleanup a function that calls zcash_script

* Remove zebra_test::prelude macros that conflict with the Rust prelude

* Add sigops count support to zebra-script

* Check MAX_BLOCK_SIGOPS in the block verifier

* Test MAX_BLOCK_SIGOPS on generated and historic blocks

* Add SAFETY comments for all unsafe zebra-script code

* Explain where the consensus rule comes from

* Remove unused pretty_assertions dependency

* Allow large test block generation functions with the proptest-impl feature

* Replace `as` with `try_into` for integer conversions in unsafe code

* Expand SAFETY comments
2021-11-15 20:55:32 +00:00
Conrado Gouvea 6570ebeeb8
ZIP 212: validate Sapling and Orchard output of coinbase transactions (#3029)
* Part of ZIP 212: validate Sapling and Orchard output of coinbase transactions

* Add Orchard test vector

* Revert accidentally deleted link

* Apply suggestions from code review

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

* Use height from loop

* Apply suggestions from code review

Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>

* Fix formatting

Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>
2021-11-11 22:18:37 +00:00
Janito Vaqueiro Ferreira Filho 0960e4fb0b
Update to Tokio 1.13.0 (#2994)
* Update `tower` to version `0.4.9`

Update to latest version to add support for Tokio version 1.

* Replace usage of `ServiceExt::ready_and`

It was deprecated in favor of `ServiceExt::ready`.

* Update Tokio dependency to version `1.13.0`

This will break the build because the code isn't ready for the update,
but future commits will fix the issues.

* Replace import of `tokio::stream::StreamExt`

Use `futures::stream::StreamExt` instead, because newer versions of
Tokio don't have the `stream` feature.

* Use `IntervalStream` in `zebra-network`

In newer versions of Tokio `Interval` doesn't implement `Stream`, so the
wrapper types from `tokio-stream` have to be used instead.

* Use `IntervalStream` in `inventory_registry`

In newer versions of Tokio the `Interval` type doesn't implement
`Stream`, so `tokio_stream::wrappers::IntervalStream` has to be used
instead.

* Use `BroadcastStream` in `inventory_registry`

In newer versions of Tokio `broadcast::Receiver` doesn't implement
`Stream`, so `tokio_stream::wrappers::BroadcastStream` instead. This
also requires changing the error type that is used.

* Handle `Semaphore::acquire` error in `tower-batch`

Newer versions of Tokio can return an error if the semaphore is closed.
This shouldn't happen in `tower-batch` because the semaphore is never
closed.

* Handle `Semaphore::acquire` error in `zebrad` test

On newer versions of Tokio `Semaphore::acquire` can return an error if
the semaphore is closed. This shouldn't happen in the test because the
semaphore is never closed.

* Update some `zebra-network` dependencies

Use versions compatible with Tokio version 1.

* Upgrade Hyper to version 0.14

Use a version that supports Tokio version 1.

* Update `metrics` dependency to version 0.17

And also update the `metrics-exporter-prometheus` to version 0.6.1.
These updates are to make sure Tokio 1 is supported.

* Use `f64` as the histogram data type

`u64` isn't supported as the histogram data type in newer versions of
`metrics`.

* Update the initialization of the metrics component

Make it compatible with the new version of `metrics`.

* Simplify build version counter

Remove all constants and use the new `metrics::incement_counter!` macro.

* Change metrics output line to match on

The snapshot string isn't included in the newer version of
`metrics-exporter-prometheus`.

* Update `sentry` to version 0.23.0

Use a version compatible with Tokio version 1.

* Remove usage of `TracingIntegration`

This seems to not be available from `sentry-tracing` anymore, so it
needs to be replaced.

* Add sentry layer to tracing initialization

This seems like the replacement for `TracingIntegration`.

* Remove unnecessary conversion

Suggested by a Clippy lint.

* Update Cargo lock file

Apply all of the updates to dependencies.

* Ban duplicate tokio dependencies

Also ban git sources for tokio dependencies.

* Stop allowing sentry-tracing git repository in `deny.toml`

* Allow remaining duplicates after the tokio upgrade

* Use C: drive for CI build output on Windows

GitHub Actions uses a Windows image with two disk drives, and the
default D: drive is smaller than the C: drive. Zebra currently uses a
lot of space to build, so it has to use the C: drive to avoid CI build
failures because of insufficient space.

Co-authored-by: teor <teor@riseup.net>
2021-11-02 18:46:57 +00:00
Conrado Gouvea 84f2c07fbc
Ignore AlreadyInChain error in the syncer (#2890)
* Ignore AlreadyInChain error in the syncer

* Split Cancelled errors; add them to should_restart_sync exceptions

* Also filter 'block is already comitted'; try to detect a wrong downcast
2021-10-20 11:07:19 +10:00
teor f4118dadda
Make block metrics more accurate (#2835)
* Check for state errors before updating metrics

Previously, the metrics would be updated for some rejected blocks.

* Clarify and expand block verification metrics

Rename checkpoint-specific metrics to clarify their purpose.

Add metrics for:
- finalized blocks on disk
- blocks verified using the full block verifier
  (this metric was previously incorrectly called `zcash_chain_verified_block_height`)

* Update dashboard metric names

Also:
- add some extra block height metrics
- fix a dashboard name

* Add exact block heights to Grafana dashboards

* Add a missing comment

* grafana: use 0 decimals for metrics

Co-authored-by: Conrado Gouvea <conrado@zfnd.org>

* grafana: show the entire height instead of abbreviated

Co-authored-by: Conrado Gouvea <conrado@zfnd.org>

* grafana: show the entire height instead of abbreviated

Co-authored-by: Conrado Gouvea <conrado@zfnd.org>

* Fix typo in metric name

Co-authored-by: Conrado Gouvea <conrado@zfnd.org>

* Move height gauges to the state, so they are correct

If we update height gauges in futures, they can execute out of order,
so the metrics can be incorrect.

Instead:
- move the height gauges to the state, and update them based on the best tip
- move the verified block counts to the state
- continue to include all verified blocks on all non-finalized chains
  (not just the best chain)

* Show exact checkpoint heights in the dashboard

Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>
Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2021-10-07 13:42:38 +00:00
teor a66ecbc16d
Make chain tip updates and access more efficient (#2695)
* Store precalculated transactions in an `Arc`

Transaction `Hash`es are 32 bytes,
and the minimun transparent transaction size is 54 bytes.
So a full 2MB block can create 1.1MB of transaction hashes.

We use an `Arc` to avoid repeatedly cloning that much data.

* Remove the unused `Block` from `ChainTipBlock`

This drops the block as soon as it isn't needed any more.

Previously, it would stick around until every `ChainTipReceiver`
dropped their `ChainTipBlock`, even if they didn't use the `Block`
at all.
2021-08-30 15:42:07 -03:00
teor ace7aec933
Return a transaction verifier from `zebra_consensus::init` (#2665)
* Return a transaction verifier from `zebra_consensus::init`

This verifier is temporarily created separately from the block verifier's
transaction verifier.

* Return the same transaction verifier used by the block verifier

* Clarify that the mempool verifier is the transaction verifier

Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>

Co-authored-by: Deirdre Connolly <deirdre@zfnd.org>
Co-authored-by: Conrado Gouvea <conrado@zfnd.org>
2021-08-25 15:07:26 +00:00
Alfredo Garcia d2e417cf48
Add value pools to FinalizedState (#2599)
* add value pools to the database

* remove redundant genesis block check

* use update_with_chain_value_pool_change()

* remove constrains

* remove height from the database

* remove calls to chain_value_pool_change

* clippy

* use the "correct" value balances

* bump the database format

* remove everything that is not finalized state

* clippy

* rustfmt

* use all spent utxos

* add new_outputs utxos to all_utxos_spent_by_block

* remove panic

* add finalized state value pool test

* clippy

* clippy 2

* move import

* fix import

* rustfmt

Co-authored-by: teor <teor@riseup.net>
2021-08-19 13:55:36 -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
teor d4cc867132
Combine near-duplicate Utxo creation functions (#2467)
* Combine near-duplicate Utxo creation functions

* rustfmt
2021-07-09 12:40:39 +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
Jack Grigg e51f33a4b9 Use interoperable names for common metrics
These names match the equivalent metrics in zcashd, enabling common
metrics to be collected across both node types.
2021-03-17 09:38:07 +10:00
teor c1a910942d Re-use some block checks in the CheckpointVerifier 2021-03-12 08:55:29 +10:00
Henry de Valence 4fd9203785 consensus: check Merkle root immediately after difficulty 2020-12-01 10:14:44 +10:00
Henry de Valence 7c08c0c315 consensus: check Merkle roots
As a side effect of computing Merkle roots, we build a list of
transaction hashes.  Instead of discarding these, add them to
PreparedBlock and FinalizedBlock so that they can be reused rather than
recomputed.

This commit adds Merkle root validation to:

1. the block verifier;
2. the checkpoint verifier.

In the first case, Bitcoin Merkle tree malleability has no effect,
because only a single Merkle tree in each malleablity set is valid (the
others have duplicate transactions).

In the second case, we need to check that the Merkle tree does not contain any
duplicate transactions.

Closes #1385
Closes #906
2020-12-01 10:14:44 +10:00
Henry de Valence 61b3286085 consensus: add NU plumbing to block,tx,script verifiers
Closes #1367 by propagating the network upgrade through the service
requests.
2020-11-25 08:53:07 +10:00
Henry de Valence 342eb166ff state: track UTXO provenance
This commit changes the state system and database format to track the
provenance of UTXOs, in addition to the outputs themselves.
Specifically, it tracks the following additional metadata:

- the height at which the UTXO was created;
- whether or not the UTXO was created from a coinbase transaction or
  not.

This metadata will allow us to:

- check the coinbase maturity consensus rule;
- check the coinbase inputs => no transparent outputs rule;
- implement lookup of transactions by utxo (using the height to find the
  block and then scanning the block) for a future RPC mechanism.

Closes #1342
2020-11-23 22:18:43 -08:00
Henry de Valence e0817d1747 state: introduce PreparedBlock, FinalizedBlock
This change introduces two new types:

- `PreparedBlock`, representing a block which has undergone semantic
  validation and has been prepared for contextual validation;
- `FinalizedBlock`, representing a block which is ready to be finalized
  immediately;

and changes the `Request::CommitBlock`,`Request::CommitFinalizedBlock`
variants to use these types instead of their previous fields.

This change solves the problem of passing data between semantic
validation and contextual validation, and cleans up the state code by
allowing it to pass around a bundle of data.  Previously, the state code
just passed around an `Arc<Block>`, which forced it to needlessly
recompute block hashes and other data, and was incompatible with the
already-known but not-yet-implemented data transfer requirements, namely
passing in the Sprout and Sapling anchors computed during contextual
validation.

This commit propagates the `PreparedBlock` and `FinalizedBlock` types
through the state code but only uses their data opportunistically, e.g.,
changing .hash() computations to use the precomputed hash.  In the
future, these structures can be extended to pass data through the
verification pipeline for reuse as appropriate.  For instance, these
changes allow the sprout and sapling anchors to be propagated through
the state.
2020-11-23 14:16:39 +10:00
Henry de Valence a2a70e1fc1 consensus: fix same-block utxo lookups
The UTXO query system assumes that a transaction will only request
information about UTXOs created in prior blocks.  But transactions are
allowed to spend UTXOs created by prior transactions in the same block.

This doesn't fit with the existing query model, so instead of trying to
change it, allow the script verifier to take an additional set of known
UTXOs, and propagate this set from the block.
2020-11-23 14:16:39 +10:00
Henry de Valence aa45bf2b58 consensus: add traces to block verifier 2020-11-23 14:16:39 +10:00
Henry de Valence 2e4f4d8e87 consensus: fix span handling in BlockVerifier
The BlockVerifier constructed a tracing span and manually entered it
inside of an async block.  Manually entering spans inside async blocks
can cause problems where the span might not be entered and exited
correctly as the resulting future is polled.  Instead, using the
.instrument creates a wrapper future that handles the bookkeeping.

I changed the span name and contents to be consistent with the spans in
the checkpoint verifier.
2020-11-21 14:09:15 -05:00
Henry de Valence d5d17a9a71 consensus: remove incorrect comment
The ZcashDeserialize implementation for Block doesn't check that blocks
have a coinbase height.
2020-11-17 14:56:27 -08:00
Deirdre Connolly b2df84fc59 Dedupe VerifyTransactionError into TransactionError 2020-10-28 21:44:13 -04:00
teor a141c336ab Actually fix whitespace 2020-10-26 13:49:48 -04:00
teor bbe4aa47ea Fix whitespace for rustfmt 2020-10-26 13:49:48 -04:00
teor 2fa3d8a8f4 Add a comment explaining why block metrics follow validation 2020-10-26 13:49:48 -04:00
teor f5a53d9dae Update block metrics after async transaction verification 2020-10-26 13:49:48 -04:00
Henry de Valence eb43893de0 consensus: minimize API, clean docs
This reduces the API surface to the minimum required for functionality,
and cleans up module documentation.  The stub mempool module is deleted
entirely, since it will need to be redone later anyways.
2020-10-20 11:16:22 -04:00
Jane Lusby 8a64c056fb consensus: integrate block, transaction Verifiers 2020-10-20 11:16:22 -04:00
teor c3a8fd3894 Check PoWLimit for difficulty threshold 2020-10-15 08:31:18 +10:00
teor 4e952a3930 Swap subsidy_is_valid argument order
This change makes the function consistent with the other check::*
functions.
2020-10-13 08:11:11 +10:00
teor 3fad3cf3af Rename functions to subsidy_is_valid*
To match the other check::* functions.

Automated commit, created using the script:

sed -i 's/subsidy_is_correct/subsidy_is_valid/' \
    $(grep -r subsidy_is_correct zebra* | cut -d: -f1 | sort -u)
2020-10-13 08:11:11 +10:00
teor d504232720 Apply error and span suggestions
Co-authored-by: Jane Lusby <jlusby42@gmail.com>
2020-10-13 08:11:11 +10:00
teor 244066f6d9 Add a hash debug-level span for block verification 2020-10-13 08:11:11 +10:00
teor c4630cd1f5 Improve error messages for header.time validation 2020-10-13 08:11:11 +10:00
teor 4953282005 Move difficulty threshold checks into their own function 2020-10-13 08:11:11 +10:00
Alfredo Garcia c93f0b3a2e
Block Subsidy and Founders Reward Amounts (#1051)
* add general and founders reward subsidy modules
* validate founders reward
* Use funding streams after Canopy on testnet
ZIP-1014 only applies to mainnet, where Canopy is at the first halving.
On testnet, Canopy is before the first halving, and the dev fund rules
apply from Canopy. (See ZIP-214.)
Co-authored-by: teor <teor@riseup.net>
Co-authored-by: Jane Lusby <jlusby42@gmail.com>

* pass all test vectors through current subsidy validation
* Add testnet and halving subsidy tests
* add subsidy validation error tests

* rename block validation methods
* add network to block verifier

* add amount operators
* Implement Ord, Eq, and Hash for Amount
* Implement Add<Height> for Height
And make the existing Height operators do range checks.
* Apply operator suggestions
Co-authored-by: Jane Lusby <jlusby42@gmail.com>
2020-10-13 06:54:48 +10:00
Deirdre Connolly 2d9198628c
Use ok_or instead of ok_or_else with unnecessary closure (#1106)
https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations
2020-09-28 21:10:51 -04:00
Alfredo Garcia c616c7ffd2
Move consensus verification errors (#1070)
* refactor block and tx validation errors

* rename errors module to error

* move NoTransactions to BlockError

* clarify some errors, use dbg format for hash in error

* mnake is_coinbase_first return BlockError

* add new error types for each consensus Service

Co-authored-by: Jane Lusby <jane@zfnd.org>
2020-09-21 11:54:06 -07:00
Henry de Valence 0d6303a56f consensus: avoid tower::ServiceExt::oneshot()
This is a really nice function but there might be a bug in its future
implementation: https://github.com/tower-rs/tower/issues/469

This bug may have already been fixed for the 0.4.0 release, so we could change
back then.
2020-09-11 13:37:49 -07:00
Henry de Valence 6dd7c6495b consensus: make ChainVerifier a router
Instead of conditionally parsing the hardcoded checkpoint list and
optionally making a CheckpointVerifier, make one unconditionally, and
use the config settings to decide whether to route responses to it.

Then, fix up all of the places needed to make it compile and remove all
of the dead code.
2020-09-11 13:37:49 -07:00
Henry de Valence 93cc6957b1 consensus: partially update to new state API
This disables one test that can't be easily fixed at the moment, because
it tests the wrong thing: the checkpoint and block verifiers will
produce different transcripts.

It also disables the initial_tip logic for now, pending simplification
of the ChainVerifier logic.
2020-09-11 13:37:49 -07:00