/__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 | | } |