Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/database/finalized_serialize.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2019-2022  Parity Technologies (UK) Ltd.
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
//! Serializing/deserializing a [`chain_information::ChainInformation`].
19
//!
20
//! This module contains the [`encode_chain_storage`] and [`decode_chain`] functions that can turn
21
//! a [`chain_information::ChainInformation`] into a string and back, with optionally the state of
22
//! the finalized block.
23
//! With no finalized block storage, the string is expected to be in the order of magnitude of a
24
//! few dozens kilobytes.
25
//!
26
//! The string format designed to be stable even if the structure of
27
//! [`chain_information::ChainInformation`] is later modified.
28
//!
29
//! This feature is expected to be used for example by light clients in order to easily (but
30
//! inefficiently) store the state of the finalized chain somewhere and later reload it.
31
32
use crate::chain::chain_information;
33
34
use alloc::{string::String, vec::Vec};
35
use core::iter;
36
use hashbrown::HashMap;
37
38
mod defs;
39
40
/// Serializes the given chain information as a JSON string.
41
///
42
/// This is a shortcut for [`encode_chain_storage`] with no `finalized_storage`.
43
0
pub fn encode_chain<'a>(
44
0
    information: impl Into<chain_information::ValidChainInformationRef<'a>>,
45
0
    block_number_bytes: usize,
46
0
) -> String {
47
0
    encode_chain_storage(
48
0
        information,
49
0
        block_number_bytes,
50
0
        None::<iter::Empty<(Vec<u8>, Vec<u8>)>>,
51
0
    )
52
0
}
Unexecuted instantiation: _RINvNtNtCsN16ciHI6Qf_7smoldot8database19finalized_serialize12encode_chainpEB6_
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8database19finalized_serialize12encode_chainRNtNtNtB6_5chain17chain_information21ValidChainInformationECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8database19finalized_serialize12encode_chainpEB6_
53
54
/// Serializes the given chain information and finalized block storage as a string.
55
0
pub fn encode_chain_storage<'a>(
56
0
    information: impl Into<chain_information::ValidChainInformationRef<'a>>,
57
0
    block_number_bytes: usize,
58
0
    finalized_storage: Option<impl Iterator<Item = (impl AsRef<[u8]>, impl AsRef<[u8]>)>>,
59
0
) -> String {
60
0
    let information = information.into();
61
0
62
0
    let decoded = defs::SerializedChainInformation::V1(defs::SerializedChainInformationV1::new(
63
0
        information.as_ref(),
64
0
        block_number_bytes,
65
0
        finalized_storage,
66
0
    ));
67
0
68
0
    serde_json::to_string(&decoded).unwrap()
69
0
}
Unexecuted instantiation: _RINvNtNtCsN16ciHI6Qf_7smoldot8database19finalized_serialize20encode_chain_storageppppEB6_
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8database19finalized_serialize20encode_chain_storageRNtNtNtB6_5chain17chain_information21ValidChainInformationINtNtCsdZExvAaxgia_5alloc3vec3VechEB2e_INtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyTB2e_B2e_EEECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8database19finalized_serialize20encode_chain_storageppppEB6_
70
71
/// Deserializes the information about the chain.
72
///
73
/// This is the invert operation of [`encode_chain_storage`].
74
0
pub fn decode_chain(encoded: &str, block_number_bytes: usize) -> Result<Decoded, CorruptedError> {
75
0
    let encoded: defs::SerializedChainInformation =
76
0
        serde_json::from_str(encoded).map_err(|e| CorruptedError(CorruptedErrorInner::Serde(e)))?;
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot8database19finalized_serialize12decode_chain0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot8database19finalized_serialize12decode_chain0B7_
77
78
    let defs::Decoded {
79
0
        chain_information,
80
0
        storage,
81
0
    } = encoded
82
0
        .decode(block_number_bytes)
83
0
        .map_err(|err| CorruptedError(CorruptedErrorInner::Deserialize(err)))?;
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot8database19finalized_serialize12decode_chains_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot8database19finalized_serialize12decode_chains_0B7_
84
85
0
    let chain_information = chain_information::ValidChainInformation::try_from(chain_information)
86
0
        .map_err(CorruptedErrorInner::InvalidChain)
87
0
        .map_err(CorruptedError)?;
88
89
0
    Ok(Decoded {
90
0
        chain_information,
91
0
        storage,
92
0
    })
93
0
}
Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot8database19finalized_serialize12decode_chain
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot8database19finalized_serialize12decode_chain
94
95
/// Outcome of [`decode_chain`].
96
pub struct Decoded {
97
    /// Decoded chain information.
98
    pub chain_information: chain_information::ValidChainInformation,
99
    /// All the keys and values found in the database. `None` if no information was found.
100
    pub storage: Option<HashMap<Vec<u8>, Vec<u8>, fnv::FnvBuildHasher>>,
101
}
102
103
/// Opaque error indicating a corruption in the data stored in the local storage.
104
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs_NtNtCsN16ciHI6Qf_7smoldot8database19finalized_serializeNtB4_14CorruptedErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs_NtNtCseuYC0Zibziv_7smoldot8database19finalized_serializeNtB4_14CorruptedErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
105
#[display(fmt = "{_0}")]
106
pub struct CorruptedError(CorruptedErrorInner);
107
108
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs1_NtNtCsN16ciHI6Qf_7smoldot8database19finalized_serializeNtB5_19CorruptedErrorInnerNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1_NtNtCseuYC0Zibziv_7smoldot8database19finalized_serializeNtB5_19CorruptedErrorInnerNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
109
enum CorruptedErrorInner {
110
    #[display(fmt = "{_0}")]
111
    Serde(serde_json::Error),
112
    #[display(fmt = "{_0}")]
113
    Deserialize(defs::DeserializeError),
114
    #[display(fmt = "Invalid chain information: {_0}")]
115
    InvalidChain(chain_information::ValidityError),
116
}