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(any(test, feature = "proptest-impl"))]
17mod tests;
1819pub use block::{TransactionIndex, TransactionLocation, MAX_ON_DISK_HEIGHT};
20pub use transparent::OutputLocation;
2122#[cfg(any(test, feature = "proptest-impl"))]
23pub use tests::KV;
2425/// Helper type for writing types to disk as raw bytes.
26/// Also used to convert key types to raw bytes for disk lookups.
27pub trait IntoDisk {
28/// The type used to write bytes to disk,
29 /// and compare a value as a key to on-disk keys.
30type Bytes: AsRef<[u8]>;
3132/// Converts the current type into serialized raw bytes.
33 ///
34 /// Used to convert keys to bytes in [`ReadDisk`][1],
35 /// and keys and values to bytes in [`WriteDisk`][2].
36 ///
37 /// # Panics
38 ///
39 /// - if the input data doesn't serialize correctly
40 ///
41 /// [1]: super::disk_db::ReadDisk
42 /// [2]: super::disk_db::WriteDisk
43fn as_bytes(&self) -> Self::Bytes;
44}
4546/// Helper type for reading types from disk as raw bytes.
47pub trait FromDisk: Sized {
48/// Converts raw disk bytes back into the deserialized type.
49 ///
50 /// Used to convert keys and values from bytes in [`ReadDisk`][1].
51 ///
52 /// # Panics
53 ///
54 /// - if the input data doesn't deserialize correctly
55 ///
56 /// [1]: super::disk_db::ReadDisk
57fn from_bytes(bytes: impl AsRef<[u8]>) -> Self;
58}
5960// Generic serialization impls
6162impl<T> IntoDisk for &T
63where
64T: IntoDisk,
65{
66type Bytes = T::Bytes;
6768fn as_bytes(&self) -> Self::Bytes {
69 T::as_bytes(*self)
70 }
71}
7273impl<T> IntoDisk for Arc<T>
74where
75T: IntoDisk,
76{
77type Bytes = T::Bytes;
7879fn as_bytes(&self) -> Self::Bytes {
80 T::as_bytes(self)
81 }
82}
8384impl<T> FromDisk for Arc<T>
85where
86T: FromDisk,
87{
88fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
89 Arc::new(T::from_bytes(bytes))
90 }
91}
9293// Commonly used serialization impls
9495impl IntoDisk for () {
96type Bytes = [u8; 0];
9798fn as_bytes(&self) -> Self::Bytes {
99 []
100 }
101}
102103impl FromDisk for () {
104#[allow(clippy::unused_unit)]
105fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
106assert_eq!(
107 bytes.as_ref().len(),
1080,
109"unexpected data in zero-sized column family type",
110 );
111112 ()
113 }
114}
115116/// Access database keys or values as raw bytes.
117/// Mainly for use in tests, runtime checks, or format compatibility code.
118#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
119pub struct RawBytes(Vec<u8>);
120121// Note: don't implement From or Into for RawBytes, because it makes it harder to spot in reviews.
122// Instead, implement IntoDisk and FromDisk on the original type, or a specific wrapper type.
123124impl RawBytes {
125/// Create a new raw byte key or data.
126 ///
127 /// Mainly for use in tests or runtime checks.
128 /// These methods
129pub fn new_raw_bytes(bytes: Vec<u8>) -> Self {
130Self(bytes)
131 }
132133/// Create a new raw byte key or data.
134 /// Mainly for use in tests.
135pub fn raw_bytes(&self) -> &Vec<u8> {
136&self.0
137}
138}
139140impl IntoDisk for RawBytes {
141type Bytes = Vec<u8>;
142143fn as_bytes(&self) -> Self::Bytes {
144self.raw_bytes().clone()
145 }
146}
147148impl FromDisk for RawBytes {
149fn from_bytes(bytes: impl AsRef<[u8]>) -> Self {
150Self::new_raw_bytes(bytes.as_ref().to_vec())
151 }
152}
153154// Serialization Modification Functions
155156/// Truncates `mem_bytes` to `disk_len`, by removing zero bytes from the start of the slice.
157/// Used to discard unused zero bytes during serialization.
158///
159/// Return `None` if any of the truncated bytes are non-zero
160///
161/// # Panics
162///
163/// - if `mem_bytes` is shorter than `disk_len`.
164pub fn truncate_zero_be_bytes(mem_bytes: &[u8], disk_len: usize) -> Option<&[u8]> {
165let discarded_bytes = mem_bytes
166 .len()
167 .checked_sub(disk_len)
168 .expect("unexpected `mem_bytes` length: must be at least `disk_len`");
169170if discarded_bytes == 0 {
171return Some(mem_bytes);
172 }
173174let (discarded, truncated) = mem_bytes.split_at(discarded_bytes);
175176if !discarded.iter().all(|&byte| byte == 0) {
177return None;
178 }
179180assert_eq!(truncated.len(), disk_len);
181182Some(truncated)
183}
184185/// Expands `disk_bytes` to `mem_len`, by adding zero bytes at the start of the slice.
186/// Used to zero-fill bytes that were discarded during serialization.
187///
188/// # Panics
189///
190/// - if `disk_bytes` is longer than `mem_len`
191pub fn expand_zero_be_bytes(disk_bytes: &[u8], mem_len: usize) -> Vec<u8> {
192let extra_bytes = mem_len
193 .checked_sub(disk_bytes.len())
194 .expect("unexpected `disk_bytes` length: must not exceed `mem_len`");
195196if extra_bytes == 0 {
197return disk_bytes.to_vec();
198 }
199200let mut expanded = vec![0; extra_bytes];
201 expanded.extend(disk_bytes);
202203assert_eq!(expanded.len(), mem_len);
204205 expanded
206}