refactor(state): split the database module (#3568)
* refactor(state): split the disk_format module * refactor(ci): add the new disk_db file to the state CI list Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
137ae4e041
commit
92b561dc8a
|
|
@ -163,6 +163,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
/zebra-state/**/disk_format.rs
|
/zebra-state/**/disk_format.rs
|
||||||
|
/zebra-state/**/disk_db.rs
|
||||||
/zebra-state/**/finalized_state.rs
|
/zebra-state/**/finalized_state.rs
|
||||||
/zebra-state/**/constants.rs
|
/zebra-state/**/constants.rs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
//! The primary implementation of the `zebra_state::Service` built upon rocksdb
|
//! The primary implementation of the `zebra_state::Service` built upon rocksdb
|
||||||
|
|
||||||
mod disk_format;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Borrow,
|
borrow::Borrow,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
|
@ -26,11 +21,26 @@ use zebra_chain::{
|
||||||
value_balance::ValueBalance,
|
value_balance::ValueBalance,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{service::check, BoxError, Config, FinalizedBlock, HashOrHeight};
|
use crate::{
|
||||||
|
service::{
|
||||||
|
check,
|
||||||
|
finalized_state::{
|
||||||
|
disk_db::{ReadDisk, WriteDisk},
|
||||||
|
disk_format::{FromDisk, IntoDisk, TransactionLocation},
|
||||||
|
},
|
||||||
|
QueuedFinalized,
|
||||||
|
},
|
||||||
|
BoxError, Config, FinalizedBlock, HashOrHeight,
|
||||||
|
};
|
||||||
|
|
||||||
use self::disk_format::{DiskDeserialize, DiskSerialize, FromDisk, IntoDisk, TransactionLocation};
|
mod disk_db;
|
||||||
|
mod disk_format;
|
||||||
|
|
||||||
use super::QueuedFinalized;
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
|
mod arbitrary;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
/// The finalized part of the chain state, stored in the db.
|
/// The finalized part of the chain state, stored in the db.
|
||||||
pub struct FinalizedState {
|
pub struct FinalizedState {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
//! Arbitrary value generation and test harnesses for the finalized state.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use proptest::prelude::*;
|
||||||
|
|
||||||
|
use zebra_chain::block;
|
||||||
|
|
||||||
|
use crate::service::finalized_state::disk_format::{FromDisk, IntoDisk, TransactionLocation};
|
||||||
|
|
||||||
|
impl Arbitrary for TransactionLocation {
|
||||||
|
type Parameters = ();
|
||||||
|
|
||||||
|
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
|
||||||
|
(any::<block::Height>(), any::<u32>())
|
||||||
|
.prop_map(|(height, index)| Self { height, index })
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Strategy = BoxedStrategy<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn round_trip<T>(input: T) -> T
|
||||||
|
where
|
||||||
|
T: IntoDisk + FromDisk,
|
||||||
|
{
|
||||||
|
let bytes = input.as_bytes();
|
||||||
|
T::from_bytes(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assert_round_trip<T>(input: T)
|
||||||
|
where
|
||||||
|
T: IntoDisk + FromDisk + Clone + PartialEq + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
let before = input.clone();
|
||||||
|
let after = round_trip(input);
|
||||||
|
assert_eq!(before, after);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn round_trip_ref<T>(input: &T) -> T
|
||||||
|
where
|
||||||
|
T: IntoDisk + FromDisk,
|
||||||
|
{
|
||||||
|
let bytes = input.as_bytes();
|
||||||
|
T::from_bytes(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assert_round_trip_ref<T>(input: &T)
|
||||||
|
where
|
||||||
|
T: IntoDisk + FromDisk + Clone + PartialEq + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
let before = input;
|
||||||
|
let after = round_trip_ref(input);
|
||||||
|
assert_eq!(before, &after);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn round_trip_arc<T>(input: Arc<T>) -> T
|
||||||
|
where
|
||||||
|
T: IntoDisk + FromDisk,
|
||||||
|
{
|
||||||
|
let bytes = input.as_bytes();
|
||||||
|
T::from_bytes(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assert_round_trip_arc<T>(input: Arc<T>)
|
||||||
|
where
|
||||||
|
T: IntoDisk + FromDisk + Clone + PartialEq + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
let before = input.clone();
|
||||||
|
let after = round_trip_arc(input);
|
||||||
|
assert_eq!(*before, after);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The round trip test covers types that are used as value field in a rocksdb
|
||||||
|
/// column family. Only these types are ever deserialized, and so they're the only
|
||||||
|
/// ones that implement both `IntoDisk` and `FromDisk`.
|
||||||
|
pub fn assert_value_properties<T>(input: T)
|
||||||
|
where
|
||||||
|
T: IntoDisk + FromDisk + Clone + PartialEq + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
assert_round_trip_ref(&input);
|
||||||
|
assert_round_trip_arc(Arc::new(input.clone()));
|
||||||
|
assert_round_trip(input);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
//! Module defining access to RocksDB via accessor traits.
|
||||||
|
//!
|
||||||
|
//! This module makes sure that:
|
||||||
|
//! - all disk writes happen inside a RocksDB transaction, and
|
||||||
|
//! - format-specific invariants are maintained.
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use crate::service::finalized_state::disk_format::{FromDisk, IntoDisk};
|
||||||
|
|
||||||
|
/// Helper trait for inserting (Key, Value) pairs into rocksdb with a consistently
|
||||||
|
/// defined format
|
||||||
|
pub trait WriteDisk {
|
||||||
|
/// Serialize and insert the given key and value into a rocksdb column family,
|
||||||
|
/// overwriting any existing `value` for `key`.
|
||||||
|
fn zs_insert<K, V>(&mut self, cf: &rocksdb::ColumnFamily, key: K, value: V)
|
||||||
|
where
|
||||||
|
K: IntoDisk + Debug,
|
||||||
|
V: IntoDisk;
|
||||||
|
|
||||||
|
/// Remove the given key form rocksdb column family if it exists.
|
||||||
|
fn zs_delete<K>(&mut self, cf: &rocksdb::ColumnFamily, key: K)
|
||||||
|
where
|
||||||
|
K: IntoDisk + Debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WriteDisk for rocksdb::WriteBatch {
|
||||||
|
fn zs_insert<K, V>(&mut self, cf: &rocksdb::ColumnFamily, key: K, value: V)
|
||||||
|
where
|
||||||
|
K: IntoDisk + Debug,
|
||||||
|
V: IntoDisk,
|
||||||
|
{
|
||||||
|
let key_bytes = key.as_bytes();
|
||||||
|
let value_bytes = value.as_bytes();
|
||||||
|
self.put_cf(cf, key_bytes, value_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zs_delete<K>(&mut self, cf: &rocksdb::ColumnFamily, key: K)
|
||||||
|
where
|
||||||
|
K: IntoDisk + Debug,
|
||||||
|
{
|
||||||
|
let key_bytes = key.as_bytes();
|
||||||
|
self.delete_cf(cf, key_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper trait for retrieving values from rocksdb column familys with a consistently
|
||||||
|
/// defined format
|
||||||
|
pub trait ReadDisk {
|
||||||
|
/// Returns the value for `key` in the rocksdb column family `cf`, if present.
|
||||||
|
fn zs_get<K, V>(&self, cf: &rocksdb::ColumnFamily, key: &K) -> Option<V>
|
||||||
|
where
|
||||||
|
K: IntoDisk,
|
||||||
|
V: FromDisk;
|
||||||
|
|
||||||
|
/// Check if a rocksdb column family `cf` contains the serialized form of `key`.
|
||||||
|
fn zs_contains<K>(&self, cf: &rocksdb::ColumnFamily, key: &K) -> bool
|
||||||
|
where
|
||||||
|
K: IntoDisk;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadDisk for rocksdb::DB {
|
||||||
|
fn zs_get<K, V>(&self, cf: &rocksdb::ColumnFamily, key: &K) -> Option<V>
|
||||||
|
where
|
||||||
|
K: IntoDisk,
|
||||||
|
V: FromDisk,
|
||||||
|
{
|
||||||
|
let key_bytes = key.as_bytes();
|
||||||
|
|
||||||
|
// We use `get_pinned_cf` to avoid taking ownership of the serialized
|
||||||
|
// value, because we're going to deserialize it anyways, which avoids an
|
||||||
|
// extra copy
|
||||||
|
let value_bytes = self
|
||||||
|
.get_pinned_cf(cf, key_bytes)
|
||||||
|
.expect("expected that disk errors would not occur");
|
||||||
|
|
||||||
|
value_bytes.map(V::from_bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zs_contains<K>(&self, cf: &rocksdb::ColumnFamily, key: &K) -> bool
|
||||||
|
where
|
||||||
|
K: IntoDisk,
|
||||||
|
{
|
||||||
|
let key_bytes = key.as_bytes();
|
||||||
|
|
||||||
|
// We use `get_pinned_cf` to avoid taking ownership of the serialized
|
||||||
|
// value, because we don't use the value at all. This avoids an extra copy.
|
||||||
|
self.get_pinned_cf(cf, key_bytes)
|
||||||
|
.expect("expected that disk errors would not occur")
|
||||||
|
.is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
//! Module defining exactly how to move types in and out of rocksdb
|
//! Module defining the serialization format for finalized data.
|
||||||
|
|
||||||
use std::{collections::BTreeMap, convert::TryInto, fmt::Debug, sync::Arc};
|
use std::{collections::BTreeMap, convert::TryInto, fmt::Debug, sync::Arc};
|
||||||
|
|
||||||
use bincode::Options;
|
use bincode::Options;
|
||||||
|
|
@ -16,6 +17,9 @@ use zebra_chain::{
|
||||||
value_balance::ValueBalance,
|
value_balance::ValueBalance,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct TransactionLocation {
|
pub struct TransactionLocation {
|
||||||
pub height: block::Height,
|
pub height: block::Height,
|
||||||
|
|
@ -378,206 +382,3 @@ impl FromDisk for NonEmptyHistoryTree {
|
||||||
.expect("deserialization format should match the serialization format used by IntoDisk")
|
.expect("deserialization format should match the serialization format used by IntoDisk")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper trait for inserting (Key, Value) pairs into rocksdb with a consistently
|
|
||||||
/// defined format
|
|
||||||
pub trait DiskSerialize {
|
|
||||||
/// Serialize and insert the given key and value into a rocksdb column family,
|
|
||||||
/// overwriting any existing `value` for `key`.
|
|
||||||
fn zs_insert<K, V>(&mut self, cf: &rocksdb::ColumnFamily, key: K, value: V)
|
|
||||||
where
|
|
||||||
K: IntoDisk + Debug,
|
|
||||||
V: IntoDisk;
|
|
||||||
|
|
||||||
/// Remove the given key form rocksdb column family if it exists.
|
|
||||||
fn zs_delete<K>(&mut self, cf: &rocksdb::ColumnFamily, key: K)
|
|
||||||
where
|
|
||||||
K: IntoDisk + Debug;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DiskSerialize for rocksdb::WriteBatch {
|
|
||||||
fn zs_insert<K, V>(&mut self, cf: &rocksdb::ColumnFamily, key: K, value: V)
|
|
||||||
where
|
|
||||||
K: IntoDisk + Debug,
|
|
||||||
V: IntoDisk,
|
|
||||||
{
|
|
||||||
let key_bytes = key.as_bytes();
|
|
||||||
let value_bytes = value.as_bytes();
|
|
||||||
self.put_cf(cf, key_bytes, value_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zs_delete<K>(&mut self, cf: &rocksdb::ColumnFamily, key: K)
|
|
||||||
where
|
|
||||||
K: IntoDisk + Debug,
|
|
||||||
{
|
|
||||||
let key_bytes = key.as_bytes();
|
|
||||||
self.delete_cf(cf, key_bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper trait for retrieving values from rocksdb column familys with a consistently
|
|
||||||
/// defined format
|
|
||||||
pub trait DiskDeserialize {
|
|
||||||
/// Returns the value for `key` in the rocksdb column family `cf`, if present.
|
|
||||||
fn zs_get<K, V>(&self, cf: &rocksdb::ColumnFamily, key: &K) -> Option<V>
|
|
||||||
where
|
|
||||||
K: IntoDisk,
|
|
||||||
V: FromDisk;
|
|
||||||
|
|
||||||
/// Check if a rocksdb column family `cf` contains the serialized form of `key`.
|
|
||||||
fn zs_contains<K>(&self, cf: &rocksdb::ColumnFamily, key: &K) -> bool
|
|
||||||
where
|
|
||||||
K: IntoDisk;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DiskDeserialize for rocksdb::DB {
|
|
||||||
fn zs_get<K, V>(&self, cf: &rocksdb::ColumnFamily, key: &K) -> Option<V>
|
|
||||||
where
|
|
||||||
K: IntoDisk,
|
|
||||||
V: FromDisk,
|
|
||||||
{
|
|
||||||
let key_bytes = key.as_bytes();
|
|
||||||
|
|
||||||
// We use `get_pinned_cf` to avoid taking ownership of the serialized
|
|
||||||
// value, because we're going to deserialize it anyways, which avoids an
|
|
||||||
// extra copy
|
|
||||||
let value_bytes = self
|
|
||||||
.get_pinned_cf(cf, key_bytes)
|
|
||||||
.expect("expected that disk errors would not occur");
|
|
||||||
|
|
||||||
value_bytes.map(V::from_bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zs_contains<K>(&self, cf: &rocksdb::ColumnFamily, key: &K) -> bool
|
|
||||||
where
|
|
||||||
K: IntoDisk,
|
|
||||||
{
|
|
||||||
let key_bytes = key.as_bytes();
|
|
||||||
|
|
||||||
// We use `get_pinned_cf` to avoid taking ownership of the serialized
|
|
||||||
// value, because we don't use the value at all. This avoids an extra copy.
|
|
||||||
self.get_pinned_cf(cf, key_bytes)
|
|
||||||
.expect("expected that disk errors would not occur")
|
|
||||||
.is_some()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use proptest::{arbitrary::any, prelude::*};
|
|
||||||
|
|
||||||
impl Arbitrary for TransactionLocation {
|
|
||||||
type Parameters = ();
|
|
||||||
|
|
||||||
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
|
|
||||||
(any::<block::Height>(), any::<u32>())
|
|
||||||
.prop_map(|(height, index)| Self { height, index })
|
|
||||||
.boxed()
|
|
||||||
}
|
|
||||||
|
|
||||||
type Strategy = BoxedStrategy<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn round_trip<T>(input: T) -> T
|
|
||||||
where
|
|
||||||
T: IntoDisk + FromDisk,
|
|
||||||
{
|
|
||||||
let bytes = input.as_bytes();
|
|
||||||
T::from_bytes(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_round_trip<T>(input: T)
|
|
||||||
where
|
|
||||||
T: IntoDisk + FromDisk + Clone + PartialEq + std::fmt::Debug,
|
|
||||||
{
|
|
||||||
let before = input.clone();
|
|
||||||
let after = round_trip(input);
|
|
||||||
assert_eq!(before, after);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn round_trip_ref<T>(input: &T) -> T
|
|
||||||
where
|
|
||||||
T: IntoDisk + FromDisk,
|
|
||||||
{
|
|
||||||
let bytes = input.as_bytes();
|
|
||||||
T::from_bytes(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_round_trip_ref<T>(input: &T)
|
|
||||||
where
|
|
||||||
T: IntoDisk + FromDisk + Clone + PartialEq + std::fmt::Debug,
|
|
||||||
{
|
|
||||||
let before = input;
|
|
||||||
let after = round_trip_ref(input);
|
|
||||||
assert_eq!(before, &after);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn round_trip_arc<T>(input: Arc<T>) -> T
|
|
||||||
where
|
|
||||||
T: IntoDisk + FromDisk,
|
|
||||||
{
|
|
||||||
let bytes = input.as_bytes();
|
|
||||||
T::from_bytes(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_round_trip_arc<T>(input: Arc<T>)
|
|
||||||
where
|
|
||||||
T: IntoDisk + FromDisk + Clone + PartialEq + std::fmt::Debug,
|
|
||||||
{
|
|
||||||
let before = input.clone();
|
|
||||||
let after = round_trip_arc(input);
|
|
||||||
assert_eq!(*before, after);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The round trip test covers types that are used as value field in a rocksdb
|
|
||||||
/// column family. Only these types are ever deserialized, and so they're the only
|
|
||||||
/// ones that implement both `IntoDisk` and `FromDisk`.
|
|
||||||
fn assert_value_properties<T>(input: T)
|
|
||||||
where
|
|
||||||
T: IntoDisk + FromDisk + Clone + PartialEq + std::fmt::Debug,
|
|
||||||
{
|
|
||||||
assert_round_trip_ref(&input);
|
|
||||||
assert_round_trip_arc(Arc::new(input.clone()));
|
|
||||||
assert_round_trip(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn roundtrip_transaction_location() {
|
|
||||||
zebra_test::init();
|
|
||||||
proptest!(|(val in any::<TransactionLocation>())| assert_value_properties(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn roundtrip_block_hash() {
|
|
||||||
zebra_test::init();
|
|
||||||
proptest!(|(val in any::<block::Hash>())| assert_value_properties(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn roundtrip_block_height() {
|
|
||||||
zebra_test::init();
|
|
||||||
proptest!(|(val in any::<block::Height>())| assert_value_properties(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn roundtrip_block() {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
proptest!(|(val in any::<Block>())| assert_value_properties(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn roundtrip_transparent_output() {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
proptest!(|(val in any::<transparent::Utxo>())| assert_value_properties(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn roundtrip_value_balance() {
|
|
||||||
zebra_test::init();
|
|
||||||
|
|
||||||
proptest!(|(val in any::<ValueBalance::<NonNegative>>())| assert_value_properties(val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
//! Tests for the finalized disk format.
|
||||||
|
|
||||||
|
mod prop;
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
//! Randomised tests for the finalized disk format.
|
||||||
|
|
||||||
|
use proptest::{arbitrary::any, prelude::*};
|
||||||
|
|
||||||
|
use zebra_chain::{
|
||||||
|
amount::NonNegative,
|
||||||
|
block::{self, Block},
|
||||||
|
transparent,
|
||||||
|
value_balance::ValueBalance,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::service::finalized_state::{
|
||||||
|
arbitrary::assert_value_properties, disk_format::TransactionLocation,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_transaction_location() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<TransactionLocation>())| assert_value_properties(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_block_hash() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<block::Hash>())| assert_value_properties(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_block_height() {
|
||||||
|
zebra_test::init();
|
||||||
|
proptest!(|(val in any::<block::Height>())| assert_value_properties(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_block() {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
proptest!(|(val in any::<Block>())| assert_value_properties(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_transparent_output() {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
proptest!(|(val in any::<transparent::Utxo>())| assert_value_properties(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_value_balance() {
|
||||||
|
zebra_test::init();
|
||||||
|
|
||||||
|
proptest!(|(val in any::<ValueBalance::<NonNegative>>())| assert_value_properties(val));
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
|
//! Finalized state tests.
|
||||||
|
|
||||||
mod prop;
|
mod prop;
|
||||||
mod vectors;
|
mod vectors;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Randomised property tests for the finalized state.
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use zebra_chain::{block::Height, parameters::NetworkUpgrade};
|
use zebra_chain::{block::Height, parameters::NetworkUpgrade};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Fixed test vectors for the finalized state.
|
||||||
|
|
||||||
use halo2::arithmetic::FieldExt;
|
use halo2::arithmetic::FieldExt;
|
||||||
use halo2::pasta::pallas;
|
use halo2::pasta::pallas;
|
||||||
use hex::FromHex;
|
use hex::FromHex;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue