diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 767fb99b..3a4dd1b4 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -9,7 +9,8 @@ edition = "2021" [features] default = [] -proptest-impl = ["proptest", "proptest-derive", "zebra-test", "rand", "rand_chacha", "tokio"] +proptest-impl = ["proptest", "proptest-derive", "zebra-test", "rand", "rand_chacha", "tokio", +"hex/serde"] bench = ["zebra-test"] [dependencies] @@ -76,6 +77,8 @@ itertools = "0.10.3" spandoc = "0.2.1" tracing = "0.1.31" +hex = { version = "0.4.3", features = ["serde"] } + proptest = "0.10.1" proptest-derive = "0.3.0" rand = { version = "0.8.5", package = "rand" } diff --git a/zebra-chain/src/amount.rs b/zebra-chain/src/amount.rs index f44a9f17..c0f432bb 100644 --- a/zebra-chain/src/amount.rs +++ b/zebra-chain/src/amount.rs @@ -28,7 +28,18 @@ type Result = std::result::Result; #[derive(Clone, Copy, Serialize, Deserialize)] #[serde(try_from = "i64")] #[serde(bound = "C: Constraint")] -pub struct Amount(i64, PhantomData); +pub struct Amount( + /// The inner amount value. + i64, + /// Used for [`Constraint`] type inference. + /// + /// # Correctness + /// + /// This internal Zebra marker type is not consensus-critical. + /// And it should be ignored during testing. (And other internal uses.) + #[serde(skip)] + PhantomData, +); impl std::fmt::Debug for Amount { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/zebra-chain/src/block.rs b/zebra-chain/src/block.rs index 351328f6..6b7f176c 100644 --- a/zebra-chain/src/block.rs +++ b/zebra-chain/src/block.rs @@ -14,7 +14,7 @@ pub mod arbitrary; #[cfg(any(test, feature = "bench", feature = "proptest-impl"))] pub mod tests; -use std::{collections::HashMap, convert::TryInto, fmt, ops::Neg}; +use std::{collections::HashMap, fmt, ops::Neg}; pub use commitment::{ ChainHistoryBlockTxAuthCommitmentHash, ChainHistoryMmrRootHash, Commitment, CommitmentError, @@ -27,8 +27,6 @@ pub use serialize::{SerializedBlock, MAX_BLOCK_BYTES}; #[cfg(any(test, feature = "proptest-impl"))] pub use arbitrary::LedgerState; -use serde::{Deserialize, Serialize}; - use crate::{ amount::NegativeAllowed, block::merkle::AuthDataRoot, @@ -44,7 +42,8 @@ use crate::{ }; /// A Zcash block, containing a header and a list of transactions. -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(any(test, feature = "proptest-impl"), derive(Serialize))] pub struct Block { /// The block header, containing block metadata. pub header: Header, diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 1aeaaa9d..c8b65106 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -1,7 +1,8 @@ //! Transactions and transaction-related structures. +use std::{collections::HashMap, fmt, iter}; + use halo2::pasta::pallas; -use serde::{Deserialize, Serialize}; mod auth_digest; mod hash; @@ -40,8 +41,6 @@ use crate::{ value_balance::{ValueBalance, ValueBalanceError}, }; -use std::{collections::HashMap, fmt, iter}; - /// A Zcash transaction. /// /// A transaction is an encoded data structure that facilitates the transfer of @@ -53,7 +52,8 @@ use std::{collections::HashMap, fmt, iter}; /// Zcash has a number of different transaction formats. They are represented /// internally by different enum variants. Because we checkpoint on Canopy /// activation, we do not validate any pre-Sapling transaction types. -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(any(test, feature = "proptest-impl"), derive(Serialize))] // XXX consider boxing the Optional fields of V4 and V5 txs #[allow(clippy::large_enum_variant)] pub enum Transaction { diff --git a/zebra-chain/src/transparent.rs b/zebra-chain/src/transparent.rs index d95360ea..f2b97b11 100644 --- a/zebra-chain/src/transparent.rs +++ b/zebra-chain/src/transparent.rs @@ -48,7 +48,8 @@ use std::{collections::HashMap, fmt, iter}; pub const MIN_TRANSPARENT_COINBASE_MATURITY: u32 = 100; /// Arbitrary data inserted by miners into a coinbase transaction. -#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Eq, PartialEq)] +#[cfg_attr(any(test, feature = "proptest-impl"), derive(Serialize))] pub struct CoinbaseData( /// Invariant: this vec, together with the coinbase height, must be less than /// 100 bytes. We enforce this by only constructing CoinbaseData fields by @@ -92,10 +93,16 @@ impl std::fmt::Debug for CoinbaseData { /// OutPoint /// /// A particular transaction output reference. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] -#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary, Serialize))] pub struct OutPoint { /// References the transaction that contains the UTXO being spent. + /// + /// # Correctness + /// + /// Consensus-critical serialization uses [`ZcashSerialize`]. + /// [`serde`]-based hex serialization must only be used for testing. + #[cfg_attr(any(test, feature = "proptest-impl"), serde(with = "hex"))] pub hash: transaction::Hash, /// Identifies which UTXO from that transaction is referenced; the @@ -103,8 +110,25 @@ pub struct OutPoint { pub index: u32, } +impl OutPoint { + /// Returns a new OutPoint from an in-memory output `index`. + /// + /// # Panics + /// + /// If `index` doesn't fit in a [`u32`]. + pub fn from_usize(hash: transaction::Hash, index: usize) -> OutPoint { + OutPoint { + hash, + index: index + .try_into() + .expect("valid in-memory output indexes fit in a u32"), + } + } +} + /// A transparent input to a transaction. -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(any(test, feature = "proptest-impl"), derive(Serialize))] pub enum Input { /// A reference to an output of a previous transaction. PrevOut { @@ -289,8 +313,8 @@ impl Input { /// I only own one UTXO worth 2 ZEC, I would construct a transaction /// that spends my UTXO and sends 1 ZEC to you and 1 ZEC back to me /// (just like receiving change). -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] -#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary, Serialize))] pub struct Output { /// Transaction value. // At https://en.bitcoin.it/wiki/Protocol_documentation#tx, this is an i64. diff --git a/zebra-chain/src/transparent/script.rs b/zebra-chain/src/transparent/script.rs index 90ef5457..c6e02db1 100644 --- a/zebra-chain/src/transparent/script.rs +++ b/zebra-chain/src/transparent/script.rs @@ -7,12 +7,19 @@ use crate::serialization::{ }; /// An encoding of a Bitcoin script. -#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Hash)] +#[derive(Clone, Eq, PartialEq, Hash)] #[cfg_attr( any(test, feature = "proptest-impl"), - derive(proptest_derive::Arbitrary) + derive(proptest_derive::Arbitrary, serde::Serialize) )] -pub struct Script(Vec); +pub struct Script( + /// # Correctness + /// + /// Consensus-critical serialization uses [`ZcashSerialize`]. + /// [`serde`]-based hex serialization must only be used for testing. + #[cfg_attr(any(test, feature = "proptest-impl"), serde(with = "hex"))] + Vec, +); impl Script { /// Create a new Bitcoin script from its raw bytes. diff --git a/zebra-chain/src/transparent/utxo.rs b/zebra-chain/src/transparent/utxo.rs index e7bfda4a..4f836159 100644 --- a/zebra-chain/src/transparent/utxo.rs +++ b/zebra-chain/src/transparent/utxo.rs @@ -12,7 +12,7 @@ use crate::{ #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr( any(test, feature = "proptest-impl"), - derive(proptest_derive::Arbitrary) + derive(proptest_derive::Arbitrary, serde::Serialize) )] pub struct Utxo { /// The output itself. diff --git a/zebra-state/Cargo.toml b/zebra-state/Cargo.toml index 8e653ee9..0e0e0e63 100644 --- a/zebra-state/Cargo.toml +++ b/zebra-state/Cargo.toml @@ -35,12 +35,15 @@ zebra-test = { path = "../zebra-test/", optional = true } [dev-dependencies] color-eyre = "0.6.0" -once_cell = "1.10.0" -insta = { version = "1.13.0", features = ["ron"] } itertools = "0.10.3" +once_cell = "1.10.0" +spandoc = "0.2.1" + +hex = { version = "0.4.3", features = ["serde"] } +insta = { version = "1.13.0", features = ["ron"] } + proptest = "0.10.1" proptest-derive = "0.3.0" -spandoc = "0.2.1" # TODO: replace w/ crate version when released: https://github.com/ZcashFoundation/zebra/issues/2083 # Note: if updating this, also update the workspace Cargo.toml to match. diff --git a/zebra-state/src/service/finalized_state/disk_format/tests/prop.rs b/zebra-state/src/service/finalized_state/disk_format/tests/prop.rs index 59fb1812..8041ac61 100644 --- a/zebra-state/src/service/finalized_state/disk_format/tests/prop.rs +++ b/zebra-state/src/service/finalized_state/disk_format/tests/prop.rs @@ -10,9 +10,16 @@ use zebra_chain::{ }; use crate::service::finalized_state::{ - arbitrary::assert_value_properties, disk_format::TransactionLocation, + arbitrary::assert_value_properties, + disk_format::{transparent::OutputLocation, TransactionLocation}, }; +#[test] +fn roundtrip_block_height() { + zebra_test::init(); + proptest!(|(val in any::())| assert_value_properties(val)); +} + #[test] fn roundtrip_transaction_location() { zebra_test::init(); @@ -20,15 +27,15 @@ fn roundtrip_transaction_location() { } #[test] -fn roundtrip_block_hash() { +fn roundtrip_output_location() { zebra_test::init(); - proptest!(|(val in any::())| assert_value_properties(val)); + proptest!(|(val in any::())| assert_value_properties(val)); } #[test] -fn roundtrip_block_height() { +fn roundtrip_block_hash() { zebra_test::init(); - proptest!(|(val in any::())| assert_value_properties(val)); + proptest!(|(val in any::())| assert_value_properties(val)); } #[test] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block.rs b/zebra-state/src/service/finalized_state/zebra_db/block.rs index 43d446c9..71c76231 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block.rs +++ b/zebra-state/src/service/finalized_state/zebra_db/block.rs @@ -102,12 +102,17 @@ impl ZebraDb { // Read transaction methods + /// Returns the [`TransactionLocation`] for [`transaction::Hash`], + /// if it exists in the finalized chain. + pub fn transaction_location(&self, hash: transaction::Hash) -> Option { + let tx_by_hash = self.db.cf_handle("tx_by_hash").unwrap(); + self.db.zs_get(tx_by_hash, &hash) + } + /// Returns the [`Transaction`] with [`transaction::Hash`], /// if it exists in the finalized chain. pub fn transaction(&self, hash: transaction::Hash) -> Option> { - let tx_by_hash = self.db.cf_handle("tx_by_hash").unwrap(); - self.db - .zs_get(tx_by_hash, &hash) + self.transaction_location(hash) .map(|TransactionLocation { index, height }| { let block = self .block(height.into()) diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs index 448587a1..97dac92c 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs @@ -29,27 +29,26 @@ //! cargo insta test --review --delete-unreferenced-snapshots //! ``` //! to update the test snapshots, then commit the `test_*.snap` files using git. -//! -//! # TODO -//! -//! Test the rest of the shielded data, -//! and data activated in Overwinter and later network upgrades. use std::sync::Arc; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use zebra_chain::{ - block::{self, Block, Height}, + block::{self, Block, Height, SerializedBlock}, orchard, parameters::Network::{self, *}, sapling, serialization::{ZcashDeserializeInto, ZcashSerialize}, - transaction::Transaction, + transaction::{self, Transaction}, + transparent, }; use crate::{ - service::finalized_state::{disk_format::TransactionLocation, FinalizedState}, + service::finalized_state::{ + disk_format::{block::TransactionIndex, transparent::OutputLocation, TransactionLocation}, + FinalizedState, + }, Config, }; @@ -57,7 +56,7 @@ use crate::{ /// /// This structure snapshots the height and hash on separate lines, /// which looks good for a single entry. -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] struct Tip { height: u32, block_hash: String, @@ -76,28 +75,25 @@ impl From<(Height, block::Hash)> for Tip { /// /// This structure is used to snapshot the height and hash on the same line, /// which looks good for a vector of heights and hashes. -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize)] struct BlockHash(String); /// Block data structure for RON snapshots. /// /// This structure is used to snapshot the height and block data on separate lines, /// which looks good for a vector of heights and block data. -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] struct BlockData { height: u32, - block: String, + #[serde(with = "hex")] + block: SerializedBlock, } impl BlockData { pub fn new(height: Height, block: &Block) -> BlockData { - let block = block - .zcash_serialize_to_vec() - .expect("serialization of stored block succeeds"); - BlockData { height: height.0, - block: hex::encode(block), + block: block.into(), } } } @@ -106,18 +102,19 @@ impl BlockData { /// /// This structure is used to snapshot the location and transaction hash on separate lines, /// which looks good for a vector of locations and transaction hashes. -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] -struct TransactionHash { - loc: TransactionLocation, - hash: String, +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] +struct TransactionHashByLocation { + loc: Option, + #[serde(with = "hex")] + hash: transaction::Hash, } -impl TransactionHash { - pub fn new(loc: TransactionLocation, transaction: &Transaction) -> TransactionHash { - TransactionHash { - loc, - hash: transaction.hash().to_string(), - } +impl TransactionHashByLocation { + pub fn new( + loc: Option, + hash: transaction::Hash, + ) -> TransactionHashByLocation { + TransactionHashByLocation { loc, hash } } } @@ -125,9 +122,12 @@ impl TransactionHash { /// /// This structure is used to snapshot the location and transaction data on separate lines, /// which looks good for a vector of locations and transaction data. -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize)] struct TransactionData { loc: TransactionLocation, + // TODO: after #3145, replace with: + // #[serde(with = "hex")] + // transaction: SerializedTransaction, transaction: String, } @@ -177,6 +177,8 @@ fn test_block_and_transaction_data_with_network(network: Network) { }; // We limit the number of blocks, because the serialized data is a few kilobytes per block. + // + // TODO: Test data activated in Overwinter and later network upgrades. for height in 0..=2 { let block: Arc = blocks .get(&height) @@ -223,10 +225,22 @@ fn snapshot_block_and_transaction_data(state: &FinalizedState) { let mut stored_transaction_hashes = Vec::new(); let mut stored_transactions = Vec::new(); + let mut stored_utxos = Vec::new(); + + let sapling_tree_at_tip = state.sapling_note_commitment_tree(); + let orchard_tree_at_tip = state.orchard_note_commitment_tree(); + + // Test the history tree. + // + // TODO: test non-empty history trees, using Heartwood or later blocks. + // test the rest of the chain data (value balance). + let history_tree_at_tip = state.history_tree(); + for query_height in 0..=max_height.0 { let query_height = Height(query_height); - // Check block height, block hash, and block database queries. + // Check all the block column families, + // using block height, block hash, and block database queries. let stored_block_hash = state .hash(query_height) .expect("heights up to tip have hashes"); @@ -237,14 +251,15 @@ fn snapshot_block_and_transaction_data(state: &FinalizedState) { .block(query_height.into()) .expect("heights up to tip have blocks"); + // Check the sapling and orchard note commitment trees. + // + // TODO: test the rest of the shielded data (anchors, nullifiers, sprout) let sapling_tree_by_height = state .sapling_note_commitment_tree_by_height(&query_height) .expect("heights up to tip have Sapling trees"); let orchard_tree_by_height = state .orchard_note_commitment_tree_by_height(&query_height) .expect("heights up to tip have Orchard trees"); - let sapling_tree_at_tip = state.sapling_note_commitment_tree(); - let orchard_tree_at_tip = state.db.orchard_note_commitment_tree(); // We don't need to snapshot the heights, // because they are fully determined by the tip and block hashes. @@ -257,6 +272,12 @@ fn snapshot_block_and_transaction_data(state: &FinalizedState) { assert_eq!(sapling_tree_at_tip, sapling_tree_by_height); assert_eq!(orchard_tree_at_tip, orchard_tree_by_height); + + // Skip these checks for empty history trees. + if let Some(history_tree_at_tip) = history_tree_at_tip.as_ref() { + assert_eq!(history_tree_at_tip.current_height(), max_height); + assert_eq!(history_tree_at_tip.network(), state.network()); + } } assert_eq!( @@ -277,11 +298,55 @@ fn snapshot_block_and_transaction_data(state: &FinalizedState) { let transaction = &stored_block.transactions[tx_index]; let transaction_location = TransactionLocation::from_usize(query_height, tx_index); - let transaction_hash = TransactionHash::new(transaction_location, transaction); + let transaction_hash = transaction.hash(); let transaction_data = TransactionData::new(transaction_location, transaction); - stored_transaction_hashes.push(transaction_hash); + // Check all the transaction column families, + // using transaction location queries. + let stored_transaction_location = state.transaction_location(transaction_hash); + + // Consensus: the genesis transaction is not indexed. + if query_height.0 > 0 { + assert_eq!(stored_transaction_location, Some(transaction_location)); + } else { + assert_eq!(stored_transaction_location, None); + } + + let stored_transaction_hash = + TransactionHashByLocation::new(stored_transaction_location, transaction_hash); + + stored_transaction_hashes.push(stored_transaction_hash); stored_transactions.push(transaction_data); + + for output_index in 0..stored_block.transactions[tx_index].outputs().len() { + let output = &stored_block.transactions[tx_index].outputs()[output_index]; + let outpoint = + transparent::OutPoint::from_usize(transaction_hash, output_index); + + let output_location = + OutputLocation::from_usize(transaction_hash, output_index); + + let stored_utxo = state.utxo(&outpoint); + + if let Some(stored_utxo) = &stored_utxo { + assert_eq!(&stored_utxo.output, output); + assert_eq!(stored_utxo.height, query_height); + + assert_eq!( + stored_utxo.from_coinbase, + transaction_location.index == TransactionIndex::from_usize(0), + "coinbase transactions must be the first transaction in a block:\n\ + from_coinbase was: {from_coinbase},\n\ + but transaction index was: {tx_index},\n\ + at: {transaction_location:?},\n\ + {output_location:?}", + from_coinbase = stored_utxo.from_coinbase, + ); + } + + // TODO: use output_location in #3151 + stored_utxos.push((outpoint, stored_utxo)); + } } } @@ -291,13 +356,6 @@ fn snapshot_block_and_transaction_data(state: &FinalizedState) { "unsorted: {:?}", stored_block_hashes ); - assert!(is_sorted(&stored_blocks), "unsorted: {:?}", stored_blocks); - - assert!( - is_sorted(&stored_transaction_hashes), - "unsorted: {:?}", - stored_transaction_hashes - ); assert!( is_sorted(&stored_transactions), "unsorted: {:?}", @@ -310,14 +368,19 @@ fn snapshot_block_and_transaction_data(state: &FinalizedState) { insta::assert_ron_snapshot!("block_hashes", stored_block_hashes); insta::assert_ron_snapshot!("blocks", stored_blocks); + insta::assert_ron_snapshot!("transaction_hashes", stored_transaction_hashes); + insta::assert_ron_snapshot!("transactions", stored_transactions); + + insta::assert_ron_snapshot!("utxos", stored_utxos); + // These snapshots will change if the trees do not have cached roots. // But we expect them to always have cached roots, // because those roots are used to populate the anchor column families. insta::assert_ron_snapshot!("sapling_trees", stored_sapling_trees); insta::assert_ron_snapshot!("orchard_trees", stored_orchard_trees); - insta::assert_ron_snapshot!("transaction_hashes", stored_transaction_hashes); - insta::assert_ron_snapshot!("transactions", stored_transactions); + // The zcash_history types used in this tree don't support serde. + insta::assert_debug_snapshot!("history_tree", (max_height, history_tree_at_tip)); } } diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@mainnet_0.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@mainnet_0.snap new file mode 100644 index 00000000..7338a7f7 --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@mainnet_0.snap @@ -0,0 +1,12 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: "(max_height, history_tree_at_tip)" +--- +( + Height( + 0, + ), + HistoryTree( + None, + ), +) diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@mainnet_1.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@mainnet_1.snap new file mode 100644 index 00000000..eac875ed --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@mainnet_1.snap @@ -0,0 +1,12 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: "(max_height, history_tree_at_tip)" +--- +( + Height( + 1, + ), + HistoryTree( + None, + ), +) diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@mainnet_2.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@mainnet_2.snap new file mode 100644 index 00000000..9b3b0f01 --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@mainnet_2.snap @@ -0,0 +1,12 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: "(max_height, history_tree_at_tip)" +--- +( + Height( + 2, + ), + HistoryTree( + None, + ), +) diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@testnet_0.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@testnet_0.snap new file mode 100644 index 00000000..7338a7f7 --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@testnet_0.snap @@ -0,0 +1,12 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: "(max_height, history_tree_at_tip)" +--- +( + Height( + 0, + ), + HistoryTree( + None, + ), +) diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@testnet_1.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@testnet_1.snap new file mode 100644 index 00000000..eac875ed --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@testnet_1.snap @@ -0,0 +1,12 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: "(max_height, history_tree_at_tip)" +--- +( + Height( + 1, + ), + HistoryTree( + None, + ), +) diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@testnet_2.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@testnet_2.snap new file mode 100644 index 00000000..9b3b0f01 --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/history_tree@testnet_2.snap @@ -0,0 +1,12 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: "(max_height, history_tree_at_tip)" +--- +( + Height( + 2, + ), + HistoryTree( + None, + ), +) diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_0.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_0.snap index efa98d76..80e54b74 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_0.snap +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_0.snap @@ -1,15 +1,10 @@ --- source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs -assertion_line: 274 expression: stored_transaction_hashes - --- [ - TransactionHash( - loc: TransactionLocation( - height: Height(0), - index: TransactionIndex(0), - ), + TransactionHashByLocation( + loc: None, hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", ), ] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_1.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_1.snap index eabe89f3..a0549205 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_1.snap +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_1.snap @@ -1,22 +1,17 @@ --- source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs -assertion_line: 274 expression: stored_transaction_hashes - --- [ - TransactionHash( - loc: TransactionLocation( - height: Height(0), - index: TransactionIndex(0), - ), + TransactionHashByLocation( + loc: None, hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", ), - TransactionHash( - loc: TransactionLocation( + TransactionHashByLocation( + loc: Some(TransactionLocation( height: Height(1), index: TransactionIndex(0), - ), + )), hash: "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", ), ] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_2.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_2.snap index a67b01f9..4801bd4f 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_2.snap +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@mainnet_2.snap @@ -1,29 +1,24 @@ --- source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs -assertion_line: 274 expression: stored_transaction_hashes - --- [ - TransactionHash( - loc: TransactionLocation( - height: Height(0), - index: TransactionIndex(0), - ), + TransactionHashByLocation( + loc: None, hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", ), - TransactionHash( - loc: TransactionLocation( + TransactionHashByLocation( + loc: Some(TransactionLocation( height: Height(1), index: TransactionIndex(0), - ), + )), hash: "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", ), - TransactionHash( - loc: TransactionLocation( + TransactionHashByLocation( + loc: Some(TransactionLocation( height: Height(2), index: TransactionIndex(0), - ), + )), hash: "8974d08d1c5f9c860d8b629d582a56659a4a1dcb2b5f98a25a5afcc2a784b0f4", ), ] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_0.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_0.snap index efa98d76..80e54b74 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_0.snap +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_0.snap @@ -1,15 +1,10 @@ --- source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs -assertion_line: 274 expression: stored_transaction_hashes - --- [ - TransactionHash( - loc: TransactionLocation( - height: Height(0), - index: TransactionIndex(0), - ), + TransactionHashByLocation( + loc: None, hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", ), ] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_1.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_1.snap index a4f68136..2007dc6e 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_1.snap +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_1.snap @@ -1,22 +1,17 @@ --- source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs -assertion_line: 274 expression: stored_transaction_hashes - --- [ - TransactionHash( - loc: TransactionLocation( - height: Height(0), - index: TransactionIndex(0), - ), + TransactionHashByLocation( + loc: None, hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", ), - TransactionHash( - loc: TransactionLocation( + TransactionHashByLocation( + loc: Some(TransactionLocation( height: Height(1), index: TransactionIndex(0), - ), + )), hash: "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", ), ] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_2.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_2.snap index bc1851f7..41a8590d 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_2.snap +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/transaction_hashes@testnet_2.snap @@ -1,29 +1,24 @@ --- source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs -assertion_line: 274 expression: stored_transaction_hashes - --- [ - TransactionHash( - loc: TransactionLocation( - height: Height(0), - index: TransactionIndex(0), - ), + TransactionHashByLocation( + loc: None, hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", ), - TransactionHash( - loc: TransactionLocation( + TransactionHashByLocation( + loc: Some(TransactionLocation( height: Height(1), index: TransactionIndex(0), - ), + )), hash: "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", ), - TransactionHash( - loc: TransactionLocation( + TransactionHashByLocation( + loc: Some(TransactionLocation( height: Height(2), index: TransactionIndex(0), - ), + )), hash: "5822c0532da8a008259ac39933d3210e508c17e3ba21d2b2c428785efdccb3d5", ), ] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@mainnet_0.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@mainnet_0.snap new file mode 100644 index 00000000..1b421f4a --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@mainnet_0.snap @@ -0,0 +1,10 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: stored_utxos +--- +[ + (OutPoint( + hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", + index: 0, + ), None), +] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@mainnet_1.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@mainnet_1.snap new file mode 100644 index 00000000..431016c0 --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@mainnet_1.snap @@ -0,0 +1,32 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: stored_utxos +--- +[ + (OutPoint( + hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", + index: 0, + ), None), + (OutPoint( + hash: "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + index: 0, + ), Some(Utxo( + output: Output( + value: Amount(50000), + lock_script: Script("21027a46eb513588b01b37ea24303f4b628afd12cc20df789fede0921e43cad3e875ac"), + ), + height: Height(1), + from_coinbase: true, + ))), + (OutPoint( + hash: "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + index: 1, + ), Some(Utxo( + output: Output( + value: Amount(12500), + lock_script: Script("a9147d46a730d31f97b1930d3368a967c309bd4d136a87"), + ), + height: Height(1), + from_coinbase: true, + ))), +] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@mainnet_2.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@mainnet_2.snap new file mode 100644 index 00000000..4c1e8e41 --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@mainnet_2.snap @@ -0,0 +1,54 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: stored_utxos +--- +[ + (OutPoint( + hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", + index: 0, + ), None), + (OutPoint( + hash: "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + index: 0, + ), Some(Utxo( + output: Output( + value: Amount(50000), + lock_script: Script("21027a46eb513588b01b37ea24303f4b628afd12cc20df789fede0921e43cad3e875ac"), + ), + height: Height(1), + from_coinbase: true, + ))), + (OutPoint( + hash: "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + index: 1, + ), Some(Utxo( + output: Output( + value: Amount(12500), + lock_script: Script("a9147d46a730d31f97b1930d3368a967c309bd4d136a87"), + ), + height: Height(1), + from_coinbase: true, + ))), + (OutPoint( + hash: "8974d08d1c5f9c860d8b629d582a56659a4a1dcb2b5f98a25a5afcc2a784b0f4", + index: 0, + ), Some(Utxo( + output: Output( + value: Amount(100000), + lock_script: Script("21027a46eb513588b01b37ea24303f4b628afd12cc20df789fede0921e43cad3e875ac"), + ), + height: Height(2), + from_coinbase: true, + ))), + (OutPoint( + hash: "8974d08d1c5f9c860d8b629d582a56659a4a1dcb2b5f98a25a5afcc2a784b0f4", + index: 1, + ), Some(Utxo( + output: Output( + value: Amount(25000), + lock_script: Script("a9147d46a730d31f97b1930d3368a967c309bd4d136a87"), + ), + height: Height(2), + from_coinbase: true, + ))), +] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@testnet_0.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@testnet_0.snap new file mode 100644 index 00000000..1b421f4a --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@testnet_0.snap @@ -0,0 +1,10 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: stored_utxos +--- +[ + (OutPoint( + hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", + index: 0, + ), None), +] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@testnet_1.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@testnet_1.snap new file mode 100644 index 00000000..50a4bd7c --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@testnet_1.snap @@ -0,0 +1,32 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: stored_utxos +--- +[ + (OutPoint( + hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", + index: 0, + ), None), + (OutPoint( + hash: "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + index: 0, + ), Some(Utxo( + output: Output( + value: Amount(50000), + lock_script: Script("21025229e1240a21004cf8338db05679fa34753706e84f6aebba086ba04317fd8f99ac"), + ), + height: Height(1), + from_coinbase: true, + ))), + (OutPoint( + hash: "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + index: 1, + ), Some(Utxo( + output: Output( + value: Amount(12500), + lock_script: Script("a914ef775f1f997f122a062fff1a2d7443abd1f9c64287"), + ), + height: Height(1), + from_coinbase: true, + ))), +] diff --git a/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@testnet_2.snap b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@testnet_2.snap new file mode 100644 index 00000000..15aedd05 --- /dev/null +++ b/zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshots/utxos@testnet_2.snap @@ -0,0 +1,54 @@ +--- +source: zebra-state/src/service/finalized_state/zebra_db/block/tests/snapshot.rs +expression: stored_utxos +--- +[ + (OutPoint( + hash: "c4eaa58879081de3c24a7b117ed2b28300e7ec4c4c1dff1d3f1268b7857a4ddb", + index: 0, + ), None), + (OutPoint( + hash: "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + index: 0, + ), Some(Utxo( + output: Output( + value: Amount(50000), + lock_script: Script("21025229e1240a21004cf8338db05679fa34753706e84f6aebba086ba04317fd8f99ac"), + ), + height: Height(1), + from_coinbase: true, + ))), + (OutPoint( + hash: "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + index: 1, + ), Some(Utxo( + output: Output( + value: Amount(12500), + lock_script: Script("a914ef775f1f997f122a062fff1a2d7443abd1f9c64287"), + ), + height: Height(1), + from_coinbase: true, + ))), + (OutPoint( + hash: "5822c0532da8a008259ac39933d3210e508c17e3ba21d2b2c428785efdccb3d5", + index: 0, + ), Some(Utxo( + output: Output( + value: Amount(100000), + lock_script: Script("2102acce9f6c16986c525fd34759d851ef5b4b85b5019a57bd59747be0ef1ba62523ac"), + ), + height: Height(2), + from_coinbase: true, + ))), + (OutPoint( + hash: "5822c0532da8a008259ac39933d3210e508c17e3ba21d2b2c428785efdccb3d5", + index: 1, + ), Some(Utxo( + output: Output( + value: Amount(25000), + lock_script: Script("a914ef775f1f997f122a062fff1a2d7443abd1f9c64287"), + ), + height: Height(2), + from_coinbase: true, + ))), +]