1//! Serialization formats for finalized data.
2//!
3//! # Correctness
4//!
5//! [`crate::constants::state_database_format_version_in_code()`] must be incremented
6//! each time the database format (column, serialization, etc) changes.
78use std::sync::Arc;
910pub mod block;
11pub mod chain;
12pub mod shielded;
13pub mod transparent;
14pub mod upgrade;
1516#[cfg(feature = "shielded-scan")]
17pub mod scan;
1819#[cfg(any(test, feature = "proptest-impl"))]
20mod tests;
2122pub use block::{TransactionIndex, TransactionLocation, MAX_ON_DISK_HEIGHT};
23pub use transparent::{OutputIndex, OutputLocation};
2425#[cfg(feature = "shielded-scan")]
26pub use scan::{
27 SaplingScannedDatabaseEntry, SaplingScannedDatabaseIndex, SaplingScannedResult,
28 SaplingScanningKey,
29};
3031#[cfg(any(test, feature = "proptest-impl"))]
32pub use tests::KV;
3334/// Helper type for writing types to disk as raw bytes.
35/// Also used to convert key types to raw bytes for disk lookups.
36pub trait IntoDisk {
37/// The type used to write bytes to disk,
38 /// and compare a value as a key to on-disk keys.
39type Bytes: AsRef<[u8]>;
4041/// Converts the current type into serialized raw bytes.
42 ///
43 /// Used to convert keys to bytes in [`ReadDisk`][1],
44 /// and keys and values to bytes in [`WriteDisk`][2].
45 ///
46 /// # Panics
47 ///
48 /// - if the input data doesn't serialize correctly
49 ///
50 /// [1]: super::disk_db::ReadDisk
51 /// [2]: super::disk_db::WriteDisk
52fn as_bytes(&self) -> Self::Bytes;
53}
5455/// Helper type for reading types from disk as raw bytes.
56pub trait FromDisk: Sized {
57/// Converts raw disk bytes back into the deserialized type.
58 ///
59 /// Used to convert keys and values from bytes in [`ReadDisk`][1].
60 ///
61 /// # Panics
62 ///
63 /// - if the input data doesn't deserialize correctly
64 ///
65 /// [1]: super::disk_db::ReadDisk
66fn from_bytes(bytes: impl AsRef<[u8]>) -> Self;
67}
6869// Generic serialization impls
7071impl<T> IntoDisk for &T
72where
73T: IntoDisk,
74{
75type Bytes = T::Bytes;
7677fn as_bytes(&self) -> Self::Bytes {
78 T::as_bytes(*self)
79 }
80}
8182impl<T> IntoDisk for Arc<T>
83where
84T: IntoDisk,
85{
86type Bytes = T::Bytes;
8788fn as_bytes(&self) -> Self::Bytes {
89 T::as_bytes(self)
90 }
91}
9293impl<T> FromDisk for Arc<T>
94where
95T: FromDisk,
96{
97fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
98 Arc::new(T::from_bytes(bytes))
99 }
100}
101102// Commonly used serialization impls
103104impl IntoDisk for () {
105type Bytes = [u8; 0];
106107fn as_bytes(&self) -> Self::Bytes {
108 []
109 }
110}
111112impl FromDisk for () {
113#[allow(clippy::unused_unit)]
114fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
115assert_eq!(
116 bytes.as_ref().len(),
1170,
118"unexpected data in zero-sized column family type",
119 );
120121 ()
122 }
123}
124125/// Access database keys or values as raw bytes.
126/// Mainly for use in tests, runtime checks, or format compatibility code.
127#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
128pub struct RawBytes(Vec<u8>);
129130// Note: don't implement From or Into for RawBytes, because it makes it harder to spot in reviews.
131// Instead, implement IntoDisk and FromDisk on the original type, or a specific wrapper type.
132133impl RawBytes {
134/// Create a new raw byte key or data.
135 ///
136 /// Mainly for use in tests or runtime checks.
137 /// These methods
138pub fn new_raw_bytes(bytes: Vec<u8>) -> Self {
139Self(bytes)
140 }
141142/// Create a new raw byte key or data.
143 /// Mainly for use in tests.
144pub fn raw_bytes(&self) -> &Vec<u8> {
145&self.0
146}
147}
148149impl IntoDisk for RawBytes {
150type Bytes = Vec<u8>;
151152fn as_bytes(&self) -> Self::Bytes {
153self.raw_bytes().clone()
154 }
155}
156157impl FromDisk for RawBytes {
158fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
159Self::new_raw_bytes(bytes.as_ref().to_vec())
160 }
161}
162163// Serialization Modification Functions
164165/// Truncates `mem_bytes` to `disk_len`, by removing zero bytes from the start of the slice.
166/// Used to discard unused zero bytes during serialization.
167///
168/// Return `None` if any of the truncated bytes are non-zero
169///
170/// # Panics
171///
172/// - if `mem_bytes` is shorter than `disk_len`.
173pub fn truncate_zero_be_bytes(mem_bytes: &[u8], disk_len: usize) -> Option<&[u8]> {
174let discarded_bytes = mem_bytes
175 .len()
176 .checked_sub(disk_len)
177 .expect("unexpected `mem_bytes` length: must be at least `disk_len`");
178179if discarded_bytes == 0 {
180return Some(mem_bytes);
181 }
182183let (discarded, truncated) = mem_bytes.split_at(discarded_bytes);
184185if !discarded.iter().all(|&byte| byte == 0) {
186return None;
187 }
188189assert_eq!(truncated.len(), disk_len);
190191Some(truncated)
192}
193194/// Expands `disk_bytes` to `mem_len`, by adding zero bytes at the start of the slice.
195/// Used to zero-fill bytes that were discarded during serialization.
196///
197/// # Panics
198///
199/// - if `disk_bytes` is longer than `mem_len`
200pub fn expand_zero_be_bytes(disk_bytes: &[u8], mem_len: usize) -> Vec<u8> {
201let extra_bytes = mem_len
202 .checked_sub(disk_bytes.len())
203 .expect("unexpected `disk_bytes` length: must not exceed `mem_len`");
204205if extra_bytes == 0 {
206return disk_bytes.to_vec();
207 }
208209let mut expanded = vec![0; extra_bytes];
210 expanded.extend(disk_bytes);
211212assert_eq!(expanded.len(), mem_len);
213214 expanded
215}