zebra/zebra-state/src/service/tests.rs

601 lines
24 KiB
Rust
Raw Normal View History

//! StateService test vectors.
//!
//! TODO: move these tests into tests::vectors and tests::prop modules.
change(state): Write finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5134) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * Use the same check as commit_finalized() for finalized block heights Co-authored-by: Marek <mail@marek.onl> Co-authored-by: Marek <mail@marek.onl>
2022-09-28 09:09:56 -07:00
use std::{env, sync::Arc, time::Duration};
feature(rpc): implement getblock api call (#3707) * feature(rpc): start adding a `getblock` method * fix(rpc): replace oneshot * fix(rpc): replace a panic with error * fix(rpc): fix test * feature(rpc): add hex to response * refactor(rpc): use generic instead of alias * docs(rpc): improve docs for getblock method * test(rpc): add a test for getblock method * deps(rpc): remove non needed tower features Co-authored-by: teor <teor@riseup.net> * docs(rpc): add a note to getblock doc * refactor(rpc): replace alias * fix(rpc): use `zcash_serialize_to_vec()` instead of logging format * tests(rpc): add network argument to `populated_state()` * refactor(rpc): use an error for state service readiness * fix(rpc): add parameter * fix(rpc): clippy * nit(rpc): remove new line from imports * fix(rpc): remove commented code * fix(rpc): simplify error Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * Use a `SerializedBlock` type to help serializing blocks (#3725) * Create a `SerializedBlock` helper type Create a type that can be used as a byte slice, but is guaranteed to represent a valid block. * Use `into_iter` instead of `iter` There's no need to borrow the elements, they can be moved out directly. This will be necessary because `&Arc<T>` doesn't implement `Borrow<T>`, so a `SerializedBlock` can't be built directly from an `&Arc<Block>`. * Use `SerializedBlock` in `GetBlock` Make the type stricter to avoid storing possibly invalid values. The bytes are still serialized as a hexadecimal string, through the usage of `hex`. The `serde::Deserialize` can't be derived because `hex` requires the type to also implement `FromHex`. * feature(rpc): add suggestions from code review Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> * tests(rpc): make sure mempool has no requests in get_block test * fix(rpc): change height argument type in getblock method * fix(rpc): rustfmt * fix(rpc): replace panic * fix(rpc): change getblock response * fix(rpc): fix lightwalletd test * tests(rpc): add a getblock error test * fix(rpc): try another regex Co-authored-by: teor <teor@riseup.net> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com>
2022-03-09 17:12:41 -08:00
use tower::{buffer::Buffer, util::BoxService};
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
use zebra_chain::{
change(state): Write non-finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5257) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * updates comments, renames send_process_queued, other minor cleanup * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * updates comments, renames send_process_queued, other minor cleanup * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * removes duplicate field definitions on StateService that were a result of a bad merge * update NotReadyToBeCommitted error message * Appear rustfmt * Fix doc links * Rename a function to initial_contextual_validity() * Do error tasks on Err, and success tasks on Ok * Simplify parent_error_map truncation * Rewrite best_tip() to use tip() * Rename latest_mem() to latest_non_finalized_state() ```sh fastmod latest_mem latest_non_finalized_state zebra* cargo fmt --all ``` * Simplify latest_non_finalized_state() using a new WatchReceiver API * Expand some error messages * Send the result after updating the channels, and document why * wait for chain_tip_update before cancelling download in mempool_cancel_mined * adds `sent_non_finalized_block_hashes` field to StateService * adds batched sent_hash insertions and checks sent hashes in queue_and_commit_non_finalized before adding a block to the queue * check that the `curr_buf` in SentHashes is not empty before pushing it to the `sent_bufs` * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Fix rustfmt * Check for finalized block heights using zs_contains() * adds known_utxos field to SentHashes * updates comment on SentHashes.add method * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * return early when there's a duplicate hash in QueuedBlocks.queue instead of panicking * Make finalized UTXOs near the final checkpoint available for full block verification * Replace a checkpoint height literal with the actual config * Update mainnet and testnet checkpoints - 7 October 2022 * Fix some state service init arguments * Allow more lookahead in the downloader, but less lookahead in the syncer * Add the latest config to the tests, and fix the latest config check * Increase the number of finalized blocks checked for non-finalized block UTXO spends * fix(log): reduce verbose logs for block commits (#5348) * Remove some verbose block write channel logs * Only warn about tracing endpoint if the address is actually set * Use CloneError instead of formatting a non-cloneable error Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Increase block verify timeout * Work around a known block timeout bug by using a shorter timeout Co-authored-by: teor <teor@riseup.net> Co-authored-by: Marek <mail@marek.onl> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-11 12:25:45 -07:00
block::{self, Block, CountedHeader, Height},
chain_tip::ChainTip,
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
fmt::SummaryDebug,
parameters::{Network, NetworkUpgrade},
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
serialization::{ZcashDeserialize, ZcashDeserializeInto},
transaction, transparent,
value_balance::ValueBalance,
};
use zebra_test::{prelude::*, transcript::Transcript};
use crate::{
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
arbitrary::Prepare,
init_test,
service::{arbitrary::populated_state, chain_tip::TipAction, StateService},
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
tests::setup::{partial_nu5_chain_strategy, transaction_v4_from_coinbase},
BoxError, CheckpointVerifiedBlock, Config, Request, Response, SemanticallyVerifiedBlock,
};
const LAST_BLOCK_HEIGHT: u32 = 10;
async fn test_populated_state_responds_correctly(
mut state: Buffer<BoxService<Request, Response, BoxError>, Request>,
) -> Result<()> {
let blocks: Vec<Arc<Block>> = zebra_test::vectors::MAINNET_BLOCKS
.range(0..=LAST_BLOCK_HEIGHT)
.map(|(_, block_bytes)| block_bytes.zcash_deserialize_into().unwrap())
.collect();
let block_hashes: Vec<block::Hash> = blocks.iter().map(|block| block.hash()).collect();
let block_headers: Vec<CountedHeader> = blocks
.iter()
.map(|block| CountedHeader {
header: block.header.clone(),
})
.collect();
for (ind, block) in blocks.into_iter().enumerate() {
let mut transcript = vec![];
let height = block.coinbase_height().unwrap();
let hash = block.hash();
transcript.push((
Request::Depth(block.hash()),
Ok(Response::Depth(Some(LAST_BLOCK_HEIGHT - height.0))),
));
// these requests don't have any arguments, so we just do them once
if ind == LAST_BLOCK_HEIGHT as usize {
transcript.push((Request::Tip, Ok(Response::Tip(Some((height, hash))))));
let locator_hashes = vec![
block_hashes[LAST_BLOCK_HEIGHT as usize],
block_hashes[(LAST_BLOCK_HEIGHT - 1) as usize],
block_hashes[(LAST_BLOCK_HEIGHT - 2) as usize],
block_hashes[(LAST_BLOCK_HEIGHT - 4) as usize],
block_hashes[(LAST_BLOCK_HEIGHT - 8) as usize],
block_hashes[0],
];
transcript.push((
Request::BlockLocator,
Ok(Response::BlockLocator(locator_hashes)),
));
}
// Spec: transactions in the genesis block are ignored.
if height.0 != 0 {
for transaction in &block.transactions {
let transaction_hash = transaction.hash();
transcript.push((
Request::Transaction(transaction_hash),
Ok(Response::Transaction(Some(transaction.clone()))),
));
}
}
transcript.push((
Request::Block(hash.into()),
Ok(Response::Block(Some(block.clone()))),
));
transcript.push((
Request::Block(height.into()),
Ok(Response::Block(Some(block.clone()))),
));
// Spec: transactions in the genesis block are ignored.
if height.0 != 0 {
for transaction in &block.transactions {
let transaction_hash = transaction.hash();
let from_coinbase = transaction.is_coinbase();
for (index, output) in transaction.outputs().iter().cloned().enumerate() {
let outpoint = transparent::OutPoint::from_usize(transaction_hash, index);
let utxo = transparent::Utxo {
output,
height,
from_coinbase,
};
transcript.push((Request::AwaitUtxo(outpoint), Ok(Response::Utxo(utxo))));
}
}
}
let mut append_locator_transcript = |split_ind| {
let block_hashes = block_hashes.clone();
let (known_hashes, next_hashes) = block_hashes.split_at(split_ind);
let block_headers = block_headers.clone();
let (_, next_headers) = block_headers.split_at(split_ind);
// no stop
transcript.push((
Request::FindBlockHashes {
known_blocks: known_hashes.iter().rev().cloned().collect(),
stop: None,
},
Ok(Response::BlockHashes(next_hashes.to_vec())),
));
transcript.push((
Request::FindBlockHeaders {
known_blocks: known_hashes.iter().rev().cloned().collect(),
stop: None,
},
Ok(Response::BlockHeaders(next_headers.to_vec())),
));
// stop at the next block
transcript.push((
Request::FindBlockHashes {
known_blocks: known_hashes.iter().rev().cloned().collect(),
stop: next_hashes.first().cloned(),
},
Ok(Response::BlockHashes(
next_hashes.first().iter().cloned().cloned().collect(),
)),
));
transcript.push((
Request::FindBlockHeaders {
known_blocks: known_hashes.iter().rev().cloned().collect(),
stop: next_hashes.first().cloned(),
},
Ok(Response::BlockHeaders(
next_headers.first().iter().cloned().cloned().collect(),
)),
));
// stop at a block that isn't actually in the chain
// tests bug #2789
transcript.push((
Request::FindBlockHashes {
known_blocks: known_hashes.iter().rev().cloned().collect(),
stop: Some(block::Hash([0xff; 32])),
},
Ok(Response::BlockHashes(next_hashes.to_vec())),
));
transcript.push((
Request::FindBlockHeaders {
known_blocks: known_hashes.iter().rev().cloned().collect(),
stop: Some(block::Hash([0xff; 32])),
},
Ok(Response::BlockHeaders(next_headers.to_vec())),
));
};
// split before the current block, and locate the current block
append_locator_transcript(ind);
// split after the current block, and locate the next block
append_locator_transcript(ind + 1);
let transcript = Transcript::from(transcript);
transcript.check(&mut state).await?;
}
Ok(())
}
#[tokio::main]
async fn populate_and_check(blocks: Vec<Arc<Block>>) -> Result<()> {
let (state, _, _, _) = populated_state(blocks, Network::Mainnet).await;
test_populated_state_responds_correctly(state).await?;
Ok(())
}
fn out_of_order_committing_strategy() -> BoxedStrategy<Vec<Arc<Block>>> {
let blocks = zebra_test::vectors::MAINNET_BLOCKS
.range(0..=LAST_BLOCK_HEIGHT)
.map(|(_, block_bytes)| block_bytes.zcash_deserialize_into::<Arc<Block>>().unwrap())
.collect::<Vec<_>>();
Just(blocks).prop_shuffle().boxed()
}
#[tokio::test(flavor = "multi_thread")]
async fn empty_state_still_responds_to_requests() -> Result<()> {
let _init_guard = zebra_test::init();
let block =
zebra_test::vectors::BLOCK_MAINNET_419200_BYTES.zcash_deserialize_into::<Arc<Block>>()?;
let iter = vec![
// No checks for SemanticallyVerifiedBlock or CommitCheckpointVerifiedBlock because empty state
// precondition doesn't matter to them
(Request::Depth(block.hash()), Ok(Response::Depth(None))),
(Request::Tip, Ok(Response::Tip(None))),
(Request::BlockLocator, Ok(Response::BlockLocator(vec![]))),
(
Request::Transaction(transaction::Hash([0; 32])),
Ok(Response::Transaction(None)),
),
(
Request::Block(block.hash().into()),
Ok(Response::Block(None)),
),
(
Request::Block(block.coinbase_height().unwrap().into()),
Ok(Response::Block(None)),
),
// No check for AwaitUTXO because it will wait if the UTXO isn't present
(
Request::FindBlockHashes {
known_blocks: vec![block.hash()],
stop: None,
},
Ok(Response::BlockHashes(Vec::new())),
),
(
Request::FindBlockHeaders {
known_blocks: vec![block.hash()],
stop: None,
},
Ok(Response::BlockHeaders(Vec::new())),
),
]
.into_iter();
let transcript = Transcript::from(iter);
let network = Network::Mainnet;
let state = init_test(network);
transcript.check(state).await?;
Ok(())
}
#[test]
fn state_behaves_when_blocks_are_committed_in_order() -> Result<()> {
let _init_guard = zebra_test::init();
let blocks = zebra_test::vectors::MAINNET_BLOCKS
.range(0..=LAST_BLOCK_HEIGHT)
.map(|(_, block_bytes)| block_bytes.zcash_deserialize_into::<Arc<Block>>().unwrap())
.collect();
populate_and_check(blocks)?;
Ok(())
}
const DEFAULT_PARTIAL_CHAIN_PROPTEST_CASES: u32 = 2;
/// The legacy chain limit for tests.
const TEST_LEGACY_CHAIN_LIMIT: usize = 100;
/// Check more blocks than the legacy chain limit.
const OVER_LEGACY_CHAIN_LIMIT: u32 = TEST_LEGACY_CHAIN_LIMIT as u32 + 10;
/// Check fewer blocks than the legacy chain limit.
const UNDER_LEGACY_CHAIN_LIMIT: u32 = TEST_LEGACY_CHAIN_LIMIT as u32 - 10;
proptest! {
#![proptest_config(
proptest::test_runner::Config::with_cases(env::var("PROPTEST_CASES")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(DEFAULT_PARTIAL_CHAIN_PROPTEST_CASES))
)]
/// Test out of order commits of continuous block test vectors from genesis onward.
#[test]
fn state_behaves_when_blocks_are_committed_out_of_order(blocks in out_of_order_committing_strategy()) {
let _init_guard = zebra_test::init();
populate_and_check(blocks).unwrap();
}
/// Test blocks that are less than the NU5 activation height.
#[test]
fn some_block_less_than_network_upgrade(
(network, nu_activation_height, chain) in partial_nu5_chain_strategy(4, true, UNDER_LEGACY_CHAIN_LIMIT, NetworkUpgrade::Canopy)
) {
let response = crate::service::check::legacy_chain(nu_activation_height, chain.into_iter().rev(), network, TEST_LEGACY_CHAIN_LIMIT)
.map_err(|error| error.to_string());
prop_assert_eq!(response, Ok(()));
}
/// Test the maximum amount of blocks to check before chain is declared to be legacy.
#[test]
fn no_transaction_with_network_upgrade(
(network, nu_activation_height, chain) in partial_nu5_chain_strategy(4, true, OVER_LEGACY_CHAIN_LIMIT, NetworkUpgrade::Canopy)
) {
let tip_height = chain
.last()
.expect("chain contains at least one block")
.coinbase_height()
.expect("chain contains valid blocks");
let response = crate::service::check::legacy_chain(nu_activation_height, chain.into_iter().rev(), network, TEST_LEGACY_CHAIN_LIMIT)
.map_err(|error| error.to_string());
prop_assert_eq!(
response,
Err(format!(
"could not find any transactions in recent blocks: checked {TEST_LEGACY_CHAIN_LIMIT} blocks back from {tip_height:?}",
))
);
}
/// Test the `Block.check_transaction_network_upgrade()` error inside the legacy check.
#[test]
fn at_least_one_transaction_with_inconsistent_network_upgrade(
(network, nu_activation_height, chain) in partial_nu5_chain_strategy(5, false, OVER_LEGACY_CHAIN_LIMIT, NetworkUpgrade::Canopy)
) {
// this test requires that an invalid block is encountered
// before a valid block (and before the check gives up),
// but setting `transaction_has_valid_network_upgrade` to false
// sometimes generates blocks with all valid (or missing) network upgrades
// we must check at least one block, and the first checked block must be invalid
let first_checked_block = chain
.iter()
.rev()
.take_while(|block| block.coinbase_height().unwrap() >= nu_activation_height)
.take(100)
.next();
prop_assume!(first_checked_block.is_some());
prop_assume!(
first_checked_block
.unwrap()
.check_transaction_network_upgrade_consistency(network)
.is_err()
);
let response = crate::service::check::legacy_chain(
nu_activation_height,
chain.clone().into_iter().rev(),
network,
TEST_LEGACY_CHAIN_LIMIT,
).map_err(|error| error.to_string());
prop_assert_eq!(
response,
Err("inconsistent network upgrade found in transaction: WrongTransactionConsensusBranchId".into()),
"first: {:?}, last: {:?}",
chain.first().map(|block| block.coinbase_height()),
chain.last().map(|block| block.coinbase_height()),
);
}
/// Test there is at least one transaction with a valid `network_upgrade` in the legacy check.
#[test]
fn at_least_one_transaction_with_valid_network_upgrade(
(network, nu_activation_height, chain) in partial_nu5_chain_strategy(5, true, UNDER_LEGACY_CHAIN_LIMIT, NetworkUpgrade::Canopy)
) {
let response = crate::service::check::legacy_chain(nu_activation_height, chain.into_iter().rev(), network, TEST_LEGACY_CHAIN_LIMIT)
.map_err(|error| error.to_string());
prop_assert_eq!(response, Ok(()));
}
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
/// Test that the value pool is updated accordingly.
///
/// 1. Generate a finalized chain and some non-finalized blocks.
/// 2. Check that initially the value pool is empty.
/// 3. Commit the finalized blocks and check that the value pool is updated accordingly.
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
/// 4. Commit the non-finalized blocks and check that the value pool is also updated
/// accordingly.
#[test]
fn value_pool_is_updated(
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
(network, finalized_blocks, non_finalized_blocks)
in continuous_empty_blocks_from_test_vectors(),
) {
let _init_guard = zebra_test::init();
change(state): Write non-finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5257) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * updates comments, renames send_process_queued, other minor cleanup * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * updates comments, renames send_process_queued, other minor cleanup * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * removes duplicate field definitions on StateService that were a result of a bad merge * update NotReadyToBeCommitted error message * Appear rustfmt * Fix doc links * Rename a function to initial_contextual_validity() * Do error tasks on Err, and success tasks on Ok * Simplify parent_error_map truncation * Rewrite best_tip() to use tip() * Rename latest_mem() to latest_non_finalized_state() ```sh fastmod latest_mem latest_non_finalized_state zebra* cargo fmt --all ``` * Simplify latest_non_finalized_state() using a new WatchReceiver API * Expand some error messages * Send the result after updating the channels, and document why * wait for chain_tip_update before cancelling download in mempool_cancel_mined * adds `sent_non_finalized_block_hashes` field to StateService * adds batched sent_hash insertions and checks sent hashes in queue_and_commit_non_finalized before adding a block to the queue * check that the `curr_buf` in SentHashes is not empty before pushing it to the `sent_bufs` * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Fix rustfmt * Check for finalized block heights using zs_contains() * adds known_utxos field to SentHashes * updates comment on SentHashes.add method * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * return early when there's a duplicate hash in QueuedBlocks.queue instead of panicking * Make finalized UTXOs near the final checkpoint available for full block verification * Replace a checkpoint height literal with the actual config * Update mainnet and testnet checkpoints - 7 October 2022 * Fix some state service init arguments * Allow more lookahead in the downloader, but less lookahead in the syncer * Add the latest config to the tests, and fix the latest config check * Increase the number of finalized blocks checked for non-finalized block UTXO spends * fix(log): reduce verbose logs for block commits (#5348) * Remove some verbose block write channel logs * Only warn about tracing endpoint if the address is actually set * Use CloneError instead of formatting a non-cloneable error Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Increase block verify timeout * Work around a known block timeout bug by using a shorter timeout Co-authored-by: teor <teor@riseup.net> Co-authored-by: Marek <mail@marek.onl> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-11 12:25:45 -07:00
// We're waiting to verify each block here, so we don't need the maximum checkpoint height.
let (mut state_service, _, _, _) = StateService::new(Config::ephemeral(), network, Height::MAX, 0);
change(state): Write non-finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5257) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * updates comments, renames send_process_queued, other minor cleanup * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * updates comments, renames send_process_queued, other minor cleanup * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * removes duplicate field definitions on StateService that were a result of a bad merge * update NotReadyToBeCommitted error message * Appear rustfmt * Fix doc links * Rename a function to initial_contextual_validity() * Do error tasks on Err, and success tasks on Ok * Simplify parent_error_map truncation * Rewrite best_tip() to use tip() * Rename latest_mem() to latest_non_finalized_state() ```sh fastmod latest_mem latest_non_finalized_state zebra* cargo fmt --all ``` * Simplify latest_non_finalized_state() using a new WatchReceiver API * Expand some error messages * Send the result after updating the channels, and document why * wait for chain_tip_update before cancelling download in mempool_cancel_mined * adds `sent_non_finalized_block_hashes` field to StateService * adds batched sent_hash insertions and checks sent hashes in queue_and_commit_non_finalized before adding a block to the queue * check that the `curr_buf` in SentHashes is not empty before pushing it to the `sent_bufs` * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Fix rustfmt * Check for finalized block heights using zs_contains() * adds known_utxos field to SentHashes * updates comment on SentHashes.add method * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * return early when there's a duplicate hash in QueuedBlocks.queue instead of panicking * Make finalized UTXOs near the final checkpoint available for full block verification * Replace a checkpoint height literal with the actual config * Update mainnet and testnet checkpoints - 7 October 2022 * Fix some state service init arguments * Allow more lookahead in the downloader, but less lookahead in the syncer * Add the latest config to the tests, and fix the latest config check * Increase the number of finalized blocks checked for non-finalized block UTXO spends * fix(log): reduce verbose logs for block commits (#5348) * Remove some verbose block write channel logs * Only warn about tracing endpoint if the address is actually set * Use CloneError instead of formatting a non-cloneable error Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Increase block verify timeout * Work around a known block timeout bug by using a shorter timeout Co-authored-by: teor <teor@riseup.net> Co-authored-by: Marek <mail@marek.onl> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-11 12:25:45 -07:00
prop_assert_eq!(state_service.read_service.db.finalized_value_pool(), ValueBalance::zero());
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
prop_assert_eq!(
change(state): Write non-finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5257) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * updates comments, renames send_process_queued, other minor cleanup * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * updates comments, renames send_process_queued, other minor cleanup * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * removes duplicate field definitions on StateService that were a result of a bad merge * update NotReadyToBeCommitted error message * Appear rustfmt * Fix doc links * Rename a function to initial_contextual_validity() * Do error tasks on Err, and success tasks on Ok * Simplify parent_error_map truncation * Rewrite best_tip() to use tip() * Rename latest_mem() to latest_non_finalized_state() ```sh fastmod latest_mem latest_non_finalized_state zebra* cargo fmt --all ``` * Simplify latest_non_finalized_state() using a new WatchReceiver API * Expand some error messages * Send the result after updating the channels, and document why * wait for chain_tip_update before cancelling download in mempool_cancel_mined * adds `sent_non_finalized_block_hashes` field to StateService * adds batched sent_hash insertions and checks sent hashes in queue_and_commit_non_finalized before adding a block to the queue * check that the `curr_buf` in SentHashes is not empty before pushing it to the `sent_bufs` * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Fix rustfmt * Check for finalized block heights using zs_contains() * adds known_utxos field to SentHashes * updates comment on SentHashes.add method * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * return early when there's a duplicate hash in QueuedBlocks.queue instead of panicking * Make finalized UTXOs near the final checkpoint available for full block verification * Replace a checkpoint height literal with the actual config * Update mainnet and testnet checkpoints - 7 October 2022 * Fix some state service init arguments * Allow more lookahead in the downloader, but less lookahead in the syncer * Add the latest config to the tests, and fix the latest config check * Increase the number of finalized blocks checked for non-finalized block UTXO spends * fix(log): reduce verbose logs for block commits (#5348) * Remove some verbose block write channel logs * Only warn about tracing endpoint if the address is actually set * Use CloneError instead of formatting a non-cloneable error Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Increase block verify timeout * Work around a known block timeout bug by using a shorter timeout Co-authored-by: teor <teor@riseup.net> Co-authored-by: Marek <mail@marek.onl> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-11 12:25:45 -07:00
state_service.read_service.latest_non_finalized_state().best_chain().map(|chain| chain.chain_value_pools).unwrap_or_else(ValueBalance::zero),
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
ValueBalance::zero()
);
// the slow start rate for the first few blocks, as in the spec
const SLOW_START_RATE: i64 = 62500;
// the expected transparent pool value, calculated using the slow start rate
let mut expected_transparent_pool = ValueBalance::zero();
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
let mut expected_finalized_value_pool = Ok(ValueBalance::zero());
for block in finalized_blocks {
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
// the genesis block has a zero-valued transparent output,
// which is not included in the UTXO set
if block.height > block::Height(0) {
let utxos = &block.new_outputs.iter().map(|(k, ordered_utxo)| (*k, ordered_utxo.utxo.clone())).collect();
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
let block_value_pool = &block.block.chain_value_pool_change(utxos)?;
expected_finalized_value_pool += *block_value_pool;
}
rename(state): do additional renaming for clarification purposes (#6967) * do renames by script ``` git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/CommitFinalized/CommitCheckpointVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/commit_finalized_block/commit_checkpoint_verified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/drain_queue_and_commit_finalized/drain_finalized_queue_and_commit/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queue_and_commit_finalized/queue_and_commit_to_finalized_state/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued_finalized_blocks/finalized_state_queued_blocks/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/max_queued_finalized_height/max_finalized_queue_height/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/send_finalized_block_error/send_checkpoint_verified_block_error/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/QueuedFinalized/QueuedCheckpointVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queue_and_commit_non_finalized/queue_and_commit_to_non_finalized_state/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued_non_finalized_blocks/non_finalized_state_queued_blocks/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/send_non_finalized_block_error/send_semantically_verified_block_error/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/QueuedNonFinalized/QueuedSemanticallyVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/last_sent_finalized_block_hash/finalized_block_write_last_sent_hash/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/sent_non_finalized_block_hashes/non_finalized_block_write_sent_hashes/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/invalid_block_reset_receiver/invalid_block_write_reset_receiver/g' cargo fmt --all ``` * add missing log renames by script ``` git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued finalized block/finalized state queue block/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued non-finalized block/non-finalized state queue block/g' cargo fmt --all ```
2023-06-14 22:12:45 -07:00
let result_receiver = state_service.queue_and_commit_to_finalized_state(block.clone());
change(state): Write finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5134) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * Use the same check as commit_finalized() for finalized block heights Co-authored-by: Marek <mail@marek.onl> Co-authored-by: Marek <mail@marek.onl>
2022-09-28 09:09:56 -07:00
let result = result_receiver.blocking_recv();
prop_assert!(result.is_ok(), "unexpected failed finalized block commit: {:?}", result);
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
prop_assert_eq!(
change(state): Write non-finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5257) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * updates comments, renames send_process_queued, other minor cleanup * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * updates comments, renames send_process_queued, other minor cleanup * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * removes duplicate field definitions on StateService that were a result of a bad merge * update NotReadyToBeCommitted error message * Appear rustfmt * Fix doc links * Rename a function to initial_contextual_validity() * Do error tasks on Err, and success tasks on Ok * Simplify parent_error_map truncation * Rewrite best_tip() to use tip() * Rename latest_mem() to latest_non_finalized_state() ```sh fastmod latest_mem latest_non_finalized_state zebra* cargo fmt --all ``` * Simplify latest_non_finalized_state() using a new WatchReceiver API * Expand some error messages * Send the result after updating the channels, and document why * wait for chain_tip_update before cancelling download in mempool_cancel_mined * adds `sent_non_finalized_block_hashes` field to StateService * adds batched sent_hash insertions and checks sent hashes in queue_and_commit_non_finalized before adding a block to the queue * check that the `curr_buf` in SentHashes is not empty before pushing it to the `sent_bufs` * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Fix rustfmt * Check for finalized block heights using zs_contains() * adds known_utxos field to SentHashes * updates comment on SentHashes.add method * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * return early when there's a duplicate hash in QueuedBlocks.queue instead of panicking * Make finalized UTXOs near the final checkpoint available for full block verification * Replace a checkpoint height literal with the actual config * Update mainnet and testnet checkpoints - 7 October 2022 * Fix some state service init arguments * Allow more lookahead in the downloader, but less lookahead in the syncer * Add the latest config to the tests, and fix the latest config check * Increase the number of finalized blocks checked for non-finalized block UTXO spends * fix(log): reduce verbose logs for block commits (#5348) * Remove some verbose block write channel logs * Only warn about tracing endpoint if the address is actually set * Use CloneError instead of formatting a non-cloneable error Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Increase block verify timeout * Work around a known block timeout bug by using a shorter timeout Co-authored-by: teor <teor@riseup.net> Co-authored-by: Marek <mail@marek.onl> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-11 12:25:45 -07:00
state_service.read_service.db.finalized_value_pool(),
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
expected_finalized_value_pool.clone()?.constrain()?
);
let transparent_value = SLOW_START_RATE * i64::from(block.height.0);
let transparent_value = transparent_value.try_into().unwrap();
let transparent_value = ValueBalance::from_transparent_amount(transparent_value);
expected_transparent_pool = (expected_transparent_pool + transparent_value).unwrap();
prop_assert_eq!(
change(state): Write non-finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5257) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * updates comments, renames send_process_queued, other minor cleanup * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * updates comments, renames send_process_queued, other minor cleanup * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * removes duplicate field definitions on StateService that were a result of a bad merge * update NotReadyToBeCommitted error message * Appear rustfmt * Fix doc links * Rename a function to initial_contextual_validity() * Do error tasks on Err, and success tasks on Ok * Simplify parent_error_map truncation * Rewrite best_tip() to use tip() * Rename latest_mem() to latest_non_finalized_state() ```sh fastmod latest_mem latest_non_finalized_state zebra* cargo fmt --all ``` * Simplify latest_non_finalized_state() using a new WatchReceiver API * Expand some error messages * Send the result after updating the channels, and document why * wait for chain_tip_update before cancelling download in mempool_cancel_mined * adds `sent_non_finalized_block_hashes` field to StateService * adds batched sent_hash insertions and checks sent hashes in queue_and_commit_non_finalized before adding a block to the queue * check that the `curr_buf` in SentHashes is not empty before pushing it to the `sent_bufs` * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Fix rustfmt * Check for finalized block heights using zs_contains() * adds known_utxos field to SentHashes * updates comment on SentHashes.add method * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * return early when there's a duplicate hash in QueuedBlocks.queue instead of panicking * Make finalized UTXOs near the final checkpoint available for full block verification * Replace a checkpoint height literal with the actual config * Update mainnet and testnet checkpoints - 7 October 2022 * Fix some state service init arguments * Allow more lookahead in the downloader, but less lookahead in the syncer * Add the latest config to the tests, and fix the latest config check * Increase the number of finalized blocks checked for non-finalized block UTXO spends * fix(log): reduce verbose logs for block commits (#5348) * Remove some verbose block write channel logs * Only warn about tracing endpoint if the address is actually set * Use CloneError instead of formatting a non-cloneable error Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Increase block verify timeout * Work around a known block timeout bug by using a shorter timeout Co-authored-by: teor <teor@riseup.net> Co-authored-by: Marek <mail@marek.onl> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-11 12:25:45 -07:00
state_service.read_service.db.finalized_value_pool(),
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
expected_transparent_pool
);
}
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
let mut expected_non_finalized_value_pool = Ok(expected_finalized_value_pool?);
for block in non_finalized_blocks {
let utxos = block.new_outputs.clone();
let block_value_pool = &block.block.chain_value_pool_change(&transparent::utxos_from_ordered_utxos(utxos))?;
expected_non_finalized_value_pool += *block_value_pool;
rename(state): do additional renaming for clarification purposes (#6967) * do renames by script ``` git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/CommitFinalized/CommitCheckpointVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/commit_finalized_block/commit_checkpoint_verified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/drain_queue_and_commit_finalized/drain_finalized_queue_and_commit/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queue_and_commit_finalized/queue_and_commit_to_finalized_state/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued_finalized_blocks/finalized_state_queued_blocks/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/max_queued_finalized_height/max_finalized_queue_height/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/send_finalized_block_error/send_checkpoint_verified_block_error/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/QueuedFinalized/QueuedCheckpointVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queue_and_commit_non_finalized/queue_and_commit_to_non_finalized_state/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued_non_finalized_blocks/non_finalized_state_queued_blocks/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/send_non_finalized_block_error/send_semantically_verified_block_error/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/QueuedNonFinalized/QueuedSemanticallyVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/last_sent_finalized_block_hash/finalized_block_write_last_sent_hash/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/sent_non_finalized_block_hashes/non_finalized_block_write_sent_hashes/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/invalid_block_reset_receiver/invalid_block_write_reset_receiver/g' cargo fmt --all ``` * add missing log renames by script ``` git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued finalized block/finalized state queue block/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued non-finalized block/non-finalized state queue block/g' cargo fmt --all ```
2023-06-14 22:12:45 -07:00
let result_receiver = state_service.queue_and_commit_to_non_finalized_state(block.clone());
change(state): Write finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5134) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * Use the same check as commit_finalized() for finalized block heights Co-authored-by: Marek <mail@marek.onl> Co-authored-by: Marek <mail@marek.onl>
2022-09-28 09:09:56 -07:00
let result = result_receiver.blocking_recv();
prop_assert!(result.is_ok(), "unexpected failed non-finalized block commit: {:?}", result);
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
prop_assert_eq!(
change(state): Write non-finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5257) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * updates comments, renames send_process_queued, other minor cleanup * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * updates comments, renames send_process_queued, other minor cleanup * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * removes duplicate field definitions on StateService that were a result of a bad merge * update NotReadyToBeCommitted error message * Appear rustfmt * Fix doc links * Rename a function to initial_contextual_validity() * Do error tasks on Err, and success tasks on Ok * Simplify parent_error_map truncation * Rewrite best_tip() to use tip() * Rename latest_mem() to latest_non_finalized_state() ```sh fastmod latest_mem latest_non_finalized_state zebra* cargo fmt --all ``` * Simplify latest_non_finalized_state() using a new WatchReceiver API * Expand some error messages * Send the result after updating the channels, and document why * wait for chain_tip_update before cancelling download in mempool_cancel_mined * adds `sent_non_finalized_block_hashes` field to StateService * adds batched sent_hash insertions and checks sent hashes in queue_and_commit_non_finalized before adding a block to the queue * check that the `curr_buf` in SentHashes is not empty before pushing it to the `sent_bufs` * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Fix rustfmt * Check for finalized block heights using zs_contains() * adds known_utxos field to SentHashes * updates comment on SentHashes.add method * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * return early when there's a duplicate hash in QueuedBlocks.queue instead of panicking * Make finalized UTXOs near the final checkpoint available for full block verification * Replace a checkpoint height literal with the actual config * Update mainnet and testnet checkpoints - 7 October 2022 * Fix some state service init arguments * Allow more lookahead in the downloader, but less lookahead in the syncer * Add the latest config to the tests, and fix the latest config check * Increase the number of finalized blocks checked for non-finalized block UTXO spends * fix(log): reduce verbose logs for block commits (#5348) * Remove some verbose block write channel logs * Only warn about tracing endpoint if the address is actually set * Use CloneError instead of formatting a non-cloneable error Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Increase block verify timeout * Work around a known block timeout bug by using a shorter timeout Co-authored-by: teor <teor@riseup.net> Co-authored-by: Marek <mail@marek.onl> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-11 12:25:45 -07:00
state_service.read_service.latest_non_finalized_state().best_chain().unwrap().chain_value_pools,
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
expected_non_finalized_value_pool.clone()?.constrain()?
);
let transparent_value = SLOW_START_RATE * i64::from(block.height.0);
let transparent_value = transparent_value.try_into().unwrap();
let transparent_value = ValueBalance::from_transparent_amount(transparent_value);
expected_transparent_pool = (expected_transparent_pool + transparent_value).unwrap();
prop_assert_eq!(
change(state): Write non-finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5257) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * updates comments, renames send_process_queued, other minor cleanup * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * updates comments, renames send_process_queued, other minor cleanup * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * removes duplicate field definitions on StateService that were a result of a bad merge * update NotReadyToBeCommitted error message * Appear rustfmt * Fix doc links * Rename a function to initial_contextual_validity() * Do error tasks on Err, and success tasks on Ok * Simplify parent_error_map truncation * Rewrite best_tip() to use tip() * Rename latest_mem() to latest_non_finalized_state() ```sh fastmod latest_mem latest_non_finalized_state zebra* cargo fmt --all ``` * Simplify latest_non_finalized_state() using a new WatchReceiver API * Expand some error messages * Send the result after updating the channels, and document why * wait for chain_tip_update before cancelling download in mempool_cancel_mined * adds `sent_non_finalized_block_hashes` field to StateService * adds batched sent_hash insertions and checks sent hashes in queue_and_commit_non_finalized before adding a block to the queue * check that the `curr_buf` in SentHashes is not empty before pushing it to the `sent_bufs` * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Fix rustfmt * Check for finalized block heights using zs_contains() * adds known_utxos field to SentHashes * updates comment on SentHashes.add method * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * return early when there's a duplicate hash in QueuedBlocks.queue instead of panicking * Make finalized UTXOs near the final checkpoint available for full block verification * Replace a checkpoint height literal with the actual config * Update mainnet and testnet checkpoints - 7 October 2022 * Fix some state service init arguments * Allow more lookahead in the downloader, but less lookahead in the syncer * Add the latest config to the tests, and fix the latest config check * Increase the number of finalized blocks checked for non-finalized block UTXO spends * fix(log): reduce verbose logs for block commits (#5348) * Remove some verbose block write channel logs * Only warn about tracing endpoint if the address is actually set * Use CloneError instead of formatting a non-cloneable error Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Increase block verify timeout * Work around a known block timeout bug by using a shorter timeout Co-authored-by: teor <teor@riseup.net> Co-authored-by: Marek <mail@marek.onl> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-11 12:25:45 -07:00
state_service.read_service.latest_non_finalized_state().best_chain().unwrap().chain_value_pools,
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
expected_transparent_pool
);
}
}
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
}
change(state): Write finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5134) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * Use the same check as commit_finalized() for finalized block heights Co-authored-by: Marek <mail@marek.onl> Co-authored-by: Marek <mail@marek.onl>
2022-09-28 09:09:56 -07:00
// This test sleeps for every block, so we only ever want to run it once
proptest! {
#![proptest_config(
proptest::test_runner::Config::with_cases(1)
)]
/// Test that the best tip height is updated accordingly.
///
/// 1. Generate a finalized chain and some non-finalized blocks.
/// 2. Check that initially the best tip height is empty.
/// 3. Commit the finalized blocks and check that the best tip height is updated accordingly.
/// 4. Commit the non-finalized blocks and check that the best tip height is also updated
/// accordingly.
#[test]
fn chain_tip_sender_is_updated(
(network, finalized_blocks, non_finalized_blocks)
in continuous_empty_blocks_from_test_vectors(),
) {
let _init_guard = zebra_test::init();
change(state): Write non-finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5257) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * updates comments, renames send_process_queued, other minor cleanup * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * sends non-finalized blocks to the block write task * passes ZebraDb to commit_new_chain, commit_block, and no_duplicates_in_finalized_chain instead of FinalizedState * updates comments, renames send_process_queued, other minor cleanup * Update zebra-state/src/service/write.rs Co-authored-by: teor <teor@riseup.net> * update assert_block_can_be_validated comment * removes `mem` field from StateService * removes `disk` field from StateService and updates block_iter to use `ZebraDb` instead of the finalized state * updates tests that use the disk to use read_service.db instead * moves best_tip to a read fn and returns finalized & non-finalized states from setup instead of the state service * changes `contextual_validity` to get the network from the finalized_state instead of another param * swaps out StateService with FinalizedState and NonFinalizedState in tests * adds NotReadyToBeCommitted error and returns it from validate_and_commit when a blocks parent hash is not in any chain * removes NonFinalizedWriteCmd and calls, moves update_latest_channels above rsp_tx.send * makes parent_errors_map an indexmap * clears non-finalized block queue when the receiver is dropped and when the StateService is being dropped * removes duplicate field definitions on StateService that were a result of a bad merge * update NotReadyToBeCommitted error message * Appear rustfmt * Fix doc links * Rename a function to initial_contextual_validity() * Do error tasks on Err, and success tasks on Ok * Simplify parent_error_map truncation * Rewrite best_tip() to use tip() * Rename latest_mem() to latest_non_finalized_state() ```sh fastmod latest_mem latest_non_finalized_state zebra* cargo fmt --all ``` * Simplify latest_non_finalized_state() using a new WatchReceiver API * Expand some error messages * Send the result after updating the channels, and document why * wait for chain_tip_update before cancelling download in mempool_cancel_mined * adds `sent_non_finalized_block_hashes` field to StateService * adds batched sent_hash insertions and checks sent hashes in queue_and_commit_non_finalized before adding a block to the queue * check that the `curr_buf` in SentHashes is not empty before pushing it to the `sent_bufs` * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * Fix rustfmt * Check for finalized block heights using zs_contains() * adds known_utxos field to SentHashes * updates comment on SentHashes.add method * Apply suggestions from code review Co-authored-by: teor <teor@riseup.net> * return early when there's a duplicate hash in QueuedBlocks.queue instead of panicking * Make finalized UTXOs near the final checkpoint available for full block verification * Replace a checkpoint height literal with the actual config * Update mainnet and testnet checkpoints - 7 October 2022 * Fix some state service init arguments * Allow more lookahead in the downloader, but less lookahead in the syncer * Add the latest config to the tests, and fix the latest config check * Increase the number of finalized blocks checked for non-finalized block UTXO spends * fix(log): reduce verbose logs for block commits (#5348) * Remove some verbose block write channel logs * Only warn about tracing endpoint if the address is actually set * Use CloneError instead of formatting a non-cloneable error Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Increase block verify timeout * Work around a known block timeout bug by using a shorter timeout Co-authored-by: teor <teor@riseup.net> Co-authored-by: Marek <mail@marek.onl> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
2022-10-11 12:25:45 -07:00
// We're waiting to verify each block here, so we don't need the maximum checkpoint height.
let (mut state_service, _read_only_state_service, latest_chain_tip, mut chain_tip_change) = StateService::new(Config::ephemeral(), network, Height::MAX, 0);
change(state): Write finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5134) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * Use the same check as commit_finalized() for finalized block heights Co-authored-by: Marek <mail@marek.onl> Co-authored-by: Marek <mail@marek.onl>
2022-09-28 09:09:56 -07:00
prop_assert_eq!(latest_chain_tip.best_tip_height(), None);
prop_assert_eq!(chain_tip_change.last_tip_change(), None);
for block in finalized_blocks {
let expected_block = block.clone();
let expected_action = if expected_block.height <= block::Height(1) {
// 0: reset by both initialization and the Genesis network upgrade
// 1: reset by the BeforeOverwinter network upgrade
TipAction::reset_with(expected_block.clone().into())
} else {
TipAction::grow_with(expected_block.clone().into())
};
rename(state): do additional renaming for clarification purposes (#6967) * do renames by script ``` git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/CommitFinalized/CommitCheckpointVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/commit_finalized_block/commit_checkpoint_verified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/drain_queue_and_commit_finalized/drain_finalized_queue_and_commit/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queue_and_commit_finalized/queue_and_commit_to_finalized_state/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued_finalized_blocks/finalized_state_queued_blocks/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/max_queued_finalized_height/max_finalized_queue_height/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/send_finalized_block_error/send_checkpoint_verified_block_error/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/QueuedFinalized/QueuedCheckpointVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queue_and_commit_non_finalized/queue_and_commit_to_non_finalized_state/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued_non_finalized_blocks/non_finalized_state_queued_blocks/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/send_non_finalized_block_error/send_semantically_verified_block_error/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/QueuedNonFinalized/QueuedSemanticallyVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/last_sent_finalized_block_hash/finalized_block_write_last_sent_hash/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/sent_non_finalized_block_hashes/non_finalized_block_write_sent_hashes/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/invalid_block_reset_receiver/invalid_block_write_reset_receiver/g' cargo fmt --all ``` * add missing log renames by script ``` git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued finalized block/finalized state queue block/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued non-finalized block/non-finalized state queue block/g' cargo fmt --all ```
2023-06-14 22:12:45 -07:00
let result_receiver = state_service.queue_and_commit_to_finalized_state(block);
change(state): Write finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5134) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * Use the same check as commit_finalized() for finalized block heights Co-authored-by: Marek <mail@marek.onl> Co-authored-by: Marek <mail@marek.onl>
2022-09-28 09:09:56 -07:00
let result = result_receiver.blocking_recv();
prop_assert!(result.is_ok(), "unexpected failed finalized block commit: {:?}", result);
// Wait for the channels to be updated by the block commit task.
// TODO: add a blocking method on ChainTipChange
std::thread::sleep(Duration::from_secs(1));
prop_assert_eq!(latest_chain_tip.best_tip_height(), Some(expected_block.height));
prop_assert_eq!(chain_tip_change.last_tip_change(), Some(expected_action));
}
for block in non_finalized_blocks {
let expected_block = block.clone();
let expected_action = if expected_block.height == block::Height(1) {
// 1: reset by the BeforeOverwinter network upgrade
TipAction::reset_with(expected_block.clone().into())
} else {
TipAction::grow_with(expected_block.clone().into())
};
rename(state): do additional renaming for clarification purposes (#6967) * do renames by script ``` git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/CommitFinalized/CommitCheckpointVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/commit_finalized_block/commit_checkpoint_verified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/drain_queue_and_commit_finalized/drain_finalized_queue_and_commit/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queue_and_commit_finalized/queue_and_commit_to_finalized_state/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued_finalized_blocks/finalized_state_queued_blocks/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/max_queued_finalized_height/max_finalized_queue_height/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/send_finalized_block_error/send_checkpoint_verified_block_error/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/QueuedFinalized/QueuedCheckpointVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queue_and_commit_non_finalized/queue_and_commit_to_non_finalized_state/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued_non_finalized_blocks/non_finalized_state_queued_blocks/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/send_non_finalized_block_error/send_semantically_verified_block_error/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/QueuedNonFinalized/QueuedSemanticallyVerified/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/last_sent_finalized_block_hash/finalized_block_write_last_sent_hash/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/sent_non_finalized_block_hashes/non_finalized_block_write_sent_hashes/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/invalid_block_reset_receiver/invalid_block_write_reset_receiver/g' cargo fmt --all ``` * add missing log renames by script ``` git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued finalized block/finalized state queue block/g' git ls-tree --full-tree -r --name-only HEAD | \ grep -v 'book' | grep -v 'CHANGELOG.md' | \ xargs sed -i 's/queued non-finalized block/non-finalized state queue block/g' cargo fmt --all ```
2023-06-14 22:12:45 -07:00
let result_receiver = state_service.queue_and_commit_to_non_finalized_state(block);
change(state): Write finalized blocks to the state in a separate thread, to avoid network and RPC hangs (#5134) * Add a new block commit task and channels, that don't do anything yet * Add last_block_hash_sent to the state service, to avoid database accesses * Update last_block_hash_sent regardless of commit errors * Rename a field to StateService.max_queued_finalized_height * Commit finalized blocks to the state in a separate task * Check for panics in the block write task * Wait for the block commit task in tests, and check for errors * Always run a proptest that sleeps once * Add extra debugging to state shutdowns * Work around a RocksDB shutdown bug * Close the finalized block channel when we're finished with it * Only reset state queue once per error * Update some TODOs * Add a module doc comment * Drop channels and check for closed channels in the block commit task * Close state channels and tasks on drop * Remove some duplicate fields across StateService and ReadStateService * Try tweaking the shutdown steps * Update and clarify some comments * Clarify another comment * Don't try to cancel RocksDB background work on drop * Fix up some comments * Remove some duplicate code * Remove redundant workarounds for shutdown issues * Remode a redundant channel close in the block commit task * Remove a mistaken `!force` shutdown condition * Remove duplicate force-shutdown code and explain it better * Improve RPC error logging * Wait for chain tip updates in the RPC tests * Wait 2 seconds for chain tip updates before skipping them * Remove an unnecessary block_in_place() * Fix some test error messages that were changed by earlier fixes * Expand some comments, fix typos Co-authored-by: Marek <mail@marek.onl> * Actually drop children of failed blocks * Explain why we drop descendants of failed blocks * Clarify a comment * Wait for chain tip updates in a failing test on macOS * Clean duplicate finalized blocks when the non-finalized state activates * Send an error when receiving a duplicate finalized block * Update checkpoint block behaviour, document its consensus rule * Wait for chain tip changes in inbound_block_height_lookahead_limit test * Wait for the genesis block to commit in the fake peer set mempool tests * Disable unreliable mempool verification check in the send transaction test * Appease rustfmt * Use clear_finalized_block_queue() everywhere that blocks are dropped * Document how Finalized and NonFinalized clones are different * Use the same check as commit_finalized() for finalized block heights Co-authored-by: Marek <mail@marek.onl> Co-authored-by: Marek <mail@marek.onl>
2022-09-28 09:09:56 -07:00
let result = result_receiver.blocking_recv();
prop_assert!(result.is_ok(), "unexpected failed non-finalized block commit: {:?}", result);
// Wait for the channels to be updated by the block commit task.
// TODO: add a blocking method on ChainTipChange
std::thread::sleep(Duration::from_secs(1));
prop_assert_eq!(latest_chain_tip.best_tip_height(), Some(expected_block.height));
prop_assert_eq!(chain_tip_change.last_tip_change(), Some(expected_action));
}
}
}
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
/// Test strategy to generate a chain split in two from the test vectors.
///
/// Selects either the mainnet or testnet chain test vector and randomly splits the chain in two
/// lists of blocks. The first containing the blocks to be finalized (which always includes at
/// least the genesis block) and the blocks to be stored in the non-finalized state.
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
fn continuous_empty_blocks_from_test_vectors() -> impl Strategy<
Value = (
Network,
SummaryDebug<Vec<CheckpointVerifiedBlock>>,
SummaryDebug<Vec<SemanticallyVerifiedBlock>>,
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
),
> {
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
any::<Network>()
.prop_flat_map(|network| {
// Select the test vector based on the network
let raw_blocks = network.blockchain_map();
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
// Transform the test vector's block bytes into a vector of `SemanticallyVerifiedBlock`s.
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
let blocks: Vec<_> = raw_blocks
.iter()
.map(|(_height, &block_bytes)| {
let mut block_reader: &[u8] = block_bytes;
let mut block = Block::zcash_deserialize(&mut block_reader)
.expect("Failed to deserialize block from test vector");
let coinbase = transaction_v4_from_coinbase(&block.transactions[0]);
block.transactions = vec![Arc::new(coinbase)];
Arc::new(block).prepare()
})
.collect();
// Always finalize the genesis block
let finalized_blocks_count = 1..=blocks.len();
(Just(network), Just(blocks), finalized_blocks_count)
})
.prop_map(|(network, mut blocks, finalized_blocks_count)| {
let non_finalized_blocks = blocks.split_off(finalized_blocks_count);
let finalized_blocks: Vec<_> = blocks
.into_iter()
.map(|prepared_block| CheckpointVerifiedBlock::from(prepared_block.block))
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
.collect();
Add value pool/balances to non-finalized state (#2656) * add value balances to non finalized state * fix 2 tests * fix remaining constrain issues in tests * extend value pool test to non finalized * WIP: fix tests after adding value pools to non-finalized state (#2647) * Update Chain::eq_internal_state with Chain.value_balance Also increase the number of cases in its tests, because they didn't detect this bug. * Calculate the chain value pool change before `Chain::push` Code - store the chain value pool change in `ContextuallyValidBlock` - convert `PreparedBlock` to `ContextuallyValidBlock` using `with_block_and_spent_utxos` (rather than `from` or `into`) - replace `block_utxos` with `new_outputs` in `PreparedBlock` - replace `block_utxos` with `chain_value_pool_change` in `ContextuallyValidBlock` Tests - create test methods for `PreparedBlock` and `ContextuallyValidBlock` - use `test_with_zero_chain_pool_change` or `test_with_zero_spent_utxos` to make tests pass * fix conflicts * build `set_current_value_pool()` only for tests * remove redundant cfgs * change cfg of set_current_value_pool() * Clarify some chain field documentation * Fix bugs in the non-finalized chain value pool calculations 1. Only revert the chain value pool balances when the tip is popped. Don't modify them when the root is finalized. 2. Only update or revert the chain value pool balances once per block. (Previously, the block changes were multiplied by the number of *transactions*.) And make corresponding changes to method names and documentation. * Add extra proptests to try to identify value balance failures * Simplify some transaction generation code * Add extra debugging info to value balance errors * Actually update non-finalized chain value pools in `UpdateWith` Previously, we were dropping the updated value pools in the `Ok` result. So the initial (finalized) chain value pool balances were never modified. * Rename and document value balance add methods The names and documentation of these methods were confusing. * Create genesis-based proptests that check chain value pools * Increase coverage for some test vectors * Test each chain value balance calculation for blocks 0-10 * Make continuous blockchain test errors easier to debug * Test the exact transparent pool values for the first few blocks Co-authored-by: Alfredo Garcia <oxarbitrage@gmail.com>
2021-08-25 06:57:07 -07:00
(
network,
finalized_blocks.into(),
non_finalized_blocks.into(),
)
Reject connections from outdated peers (#2519) * Simplify state service initialization in test Use the test helper function to remove redundant code. * Create `BestTipHeight` helper type This type abstracts away the calculation of the best tip height based on the finalized block height and the best non-finalized chain's tip. * Add `best_tip_height` field to `StateService` The receiver endpoint is currently ignored. * Return receiver endpoint from service constructor Make it available so that the best tip height can be watched. * Update finalized height after finalizing blocks After blocks from the queue are finalized and committed to disk, update the finalized block height. * Update best non-finalized height after validation Update the value of the best non-finalized chain tip block height after a new block is committed to the non-finalized state. * Update finalized height after loading from disk When `FinalizedState` is first created, it loads the state from persistent storage, and the finalized tip height is updated. Therefore, the `best_tip_height` must be notified of the initial value. * Update the finalized height on checkpoint commit When a checkpointed block is commited, it bypasses the non-finalized state, so there's an extra place where the finalized height has to be updated. * Add `best_tip_height` to `Handshake` service It can be configured using the `Builder::with_best_tip_height`. It's currently not used, but it will be used to determine if a connection to a remote peer should be rejected or not based on that peer's protocol version. * Require best tip height to init. `zebra_network` Without it the handshake service can't properly enforce the minimum network protocol version from peers. Zebrad obtains the best tip height endpoint from `zebra_state`, and the test vectors simply use a dummy endpoint that's fixed at the genesis height. * Pass `best_tip_height` to proto. ver. negotiation The protocol version negotiation code will reject connections to peers if they are using an old protocol version. An old version is determined based on the current known best chain tip height. * Handle an optional height in `Version` Fallback to the genesis height in `None` is specified. * Reject connections to peers on old proto. versions Avoid connecting to peers that are on protocol versions that don't recognize a network update. * Document why peers on old versions are rejected Describe why it's a security issue above the check. * Test if `BestTipHeight` starts with `None` Check if initially there is no best tip height. * Test if best tip height is max. of latest values After applying a list of random updates where each one either sets the finalized height or the non-finalized height, check that the best tip height is the maximum of the most recently set finalized height and the most recently set non-finalized height. * Add `queue_and_commit_finalized` method A small refactor to make testing easier. The handling of requests for committing non-finalized and finalized blocks is now more consistent. * Add `assert_block_can_be_validated` helper Refactor to move into a separate method some assertions that are done before a block is validated. This is to allow moving these assertions more easily to simplify testing. * Remove redundant PoW block assertion It's also checked in `zebra_state::service::check::block_is_contextually_valid`, and it was getting in the way of tests that received a gossiped block before finalizing enough blocks. * Create a test strategy for test vector chain Splits a chain loaded from the test vectors in two parts, containing the blocks to finalize and the blocks to keep in the non-finalized state. * Test committing blocks update best tip height Create a mock blockchain state, with a chain of finalized blocks and a chain of non-finalized blocks. Commit all the blocks appropriately, and verify that the best tip height is updated. Co-authored-by: teor <teor@riseup.net>
2021-08-08 16:52:52 -07:00
})
}