referrerpolicy=no-referrer-when-downgrade

cumulus_primitives_proof_size_hostfunction/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3// SPDX-License-Identifier: Apache-2.0
4
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// 	http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17//! Tools for reclaiming PoV weight in parachain runtimes.
18
19#![cfg_attr(not(feature = "std"), no_std)]
20
21#[cfg(feature = "std")]
22use sp_externalities::ExternalitiesExt;
23
24use sp_runtime_interface::runtime_interface;
25
26#[cfg(feature = "std")]
27use sp_trie::proof_size_extension::ProofSizeExt;
28
29pub const PROOF_RECORDING_DISABLED: u64 = u64::MAX;
30
31/// Interface that provides access to the current storage proof size.
32///
33/// Should return the current storage proof size if [`ProofSizeExt`] is registered. Otherwise, needs
34/// to return u64::MAX.
35#[runtime_interface]
36pub trait StorageProofSize {
37	/// Returns the current storage proof size.
38	fn storage_proof_size(&mut self) -> u64 {
39		self.extension::<ProofSizeExt>()
40			.map_or(PROOF_RECORDING_DISABLED, |e| e.storage_proof_size())
41	}
42}
43
44#[cfg(test)]
45mod tests {
46	use sp_core::Blake2Hasher;
47	use sp_state_machine::TestExternalities;
48	use sp_trie::{
49		proof_size_extension::ProofSizeExt, recorder::Recorder, LayoutV1, PrefixedMemoryDB,
50		TrieDBMutBuilder, TrieMut,
51	};
52
53	use crate::{storage_proof_size, PROOF_RECORDING_DISABLED};
54
55	const TEST_DATA: &[(&[u8], &[u8])] = &[(b"key1", &[1; 64]), (b"key2", &[2; 64])];
56
57	type TestLayout = LayoutV1<sp_core::Blake2Hasher>;
58
59	fn get_prepared_test_externalities() -> (TestExternalities<Blake2Hasher>, Recorder<Blake2Hasher>)
60	{
61		let mut db = PrefixedMemoryDB::default();
62		let mut root = Default::default();
63
64		{
65			let mut trie = TrieDBMutBuilder::<TestLayout>::new(&mut db, &mut root).build();
66			for (k, v) in TEST_DATA {
67				trie.insert(k, v).expect("Inserts data");
68			}
69		}
70
71		let recorder: sp_trie::recorder::Recorder<Blake2Hasher> = Default::default();
72		let trie_backend = sp_state_machine::TrieBackendBuilder::new(db, root)
73			.with_recorder(recorder.clone())
74			.build();
75
76		let mut ext: TestExternalities<Blake2Hasher> = TestExternalities::default();
77		ext.backend = trie_backend;
78		(ext, recorder)
79	}
80
81	#[test]
82	fn host_function_returns_size_from_recorder() {
83		let (mut ext, recorder) = get_prepared_test_externalities();
84		ext.register_extension(ProofSizeExt::new(recorder));
85
86		ext.execute_with(|| {
87			assert_eq!(storage_proof_size::storage_proof_size(), 0);
88			sp_io::storage::get(b"key1");
89			assert_eq!(storage_proof_size::storage_proof_size(), 175);
90			sp_io::storage::get(b"key2");
91			assert_eq!(storage_proof_size::storage_proof_size(), 275);
92			sp_io::storage::get(b"key2");
93			assert_eq!(storage_proof_size::storage_proof_size(), 275);
94		});
95	}
96
97	#[test]
98	fn host_function_returns_max_without_extension() {
99		let (mut ext, _) = get_prepared_test_externalities();
100
101		ext.execute_with(|| {
102			assert_eq!(storage_proof_size::storage_proof_size(), PROOF_RECORDING_DISABLED);
103			sp_io::storage::get(b"key1");
104			assert_eq!(storage_proof_size::storage_proof_size(), PROOF_RECORDING_DISABLED);
105			sp_io::storage::get(b"key2");
106			assert_eq!(storage_proof_size::storage_proof_size(), PROOF_RECORDING_DISABLED);
107		});
108	}
109}