cumulus_client_proof_size_recording/
lib.rs1use codec::{Decode, Encode};
21use sc_client_api::{
22 backend::AuxStore,
23 client::{AuxDataOperations, FinalityNotification, PreCommitActions},
24};
25use sp_blockchain::{Error as ClientError, Result as ClientResult};
26use sp_runtime::traits::Block as BlockT;
27use sp_trie::proof_size_extension::RecordedProofSizeEstimations;
28use std::sync::Arc;
29
30const PROOF_SIZE_RECORDING_VERSION: &[u8] = b"cumulus_proof_size_recording_version";
31const PROOF_SIZE_RECORDING_CURRENT_VERSION: u32 = 1;
32
33fn proof_size_recording_key<H: Encode>(block_hash: H) -> Vec<u8> {
35 (b"cumulus_proof_size_recording", block_hash).encode()
36}
37
38fn load_decode<B, T>(backend: &B, key: &[u8]) -> ClientResult<Option<T>>
39where
40 B: AuxStore,
41 T: Decode,
42{
43 let corrupt = |e: codec::Error| {
44 ClientError::Backend(format!("Proof size recording DB is corrupted. Decode error: {}", e))
45 };
46 match backend.get_aux(key)? {
47 None => Ok(None),
48 Some(t) => T::decode(&mut &t[..]).map(Some).map_err(corrupt),
49 }
50}
51
52pub fn prepare_proof_size_recording_aux_data<H: Encode>(
56 block_hash: H,
57 recordings: Vec<u32>,
58) -> impl Iterator<Item = (Vec<u8>, Vec<u8>)> {
59 let current_version = PROOF_SIZE_RECORDING_CURRENT_VERSION.encode();
60 let key = proof_size_recording_key(block_hash);
61 let recordings = recordings.encode();
62
63 [(key, recordings), (PROOF_SIZE_RECORDING_VERSION.to_vec(), current_version)].into_iter()
64}
65
66pub fn load_proof_size_recording<H: Encode, B: AuxStore>(
68 backend: &B,
69 block_hash: H,
70) -> ClientResult<Option<RecordedProofSizeEstimations>> {
71 let version = load_decode::<_, u32>(backend, PROOF_SIZE_RECORDING_VERSION)?;
72
73 match version {
74 None => Ok(None),
75 Some(PROOF_SIZE_RECORDING_CURRENT_VERSION) => {
76 load_decode::<_, Vec<u32>>(backend, proof_size_recording_key(block_hash).as_slice())
77 .map(|recordings| recordings.map(Into::into))
78 },
79 Some(other) => Err(ClientError::Backend(format!(
80 "Unsupported proof size recording DB version: {:?}",
81 other
82 ))),
83 }
84}
85
86fn aux_storage_cleanup<Block>(notification: &FinalityNotification<Block>) -> AuxDataOperations
92where
93 Block: BlockT,
94{
95 notification
97 .stale_blocks
98 .iter()
99 .map(|b| (proof_size_recording_key(b.hash), None))
100 .collect()
101}
102
103pub fn register_proof_size_recording_cleanup<C, Block>(client: Arc<C>)
108where
109 C: PreCommitActions<Block> + 'static,
110 Block: BlockT,
111{
112 let on_finality = move |notification: &FinalityNotification<Block>| -> AuxDataOperations {
113 aux_storage_cleanup(notification)
114 };
115
116 client.register_finality_action(Box::new(on_finality));
117}