frame_storage_access_test_runtime/
lib.rs
1#![cfg_attr(not(feature = "std"), no_std)]
21
22extern crate alloc;
23
24use alloc::vec::Vec;
25use codec::{Decode, Encode};
26use sp_core::storage::ChildInfo;
27use sp_runtime::traits;
28use sp_trie::StorageProof;
29
30#[cfg(all(not(feature = "std"), feature = "runtime-benchmarks"))]
31use {
32 cumulus_pallet_parachain_system::validate_block::{
33 trie_cache::CacheProvider, trie_recorder::SizeOnlyRecorderProvider,
34 },
35 sp_core::storage::StateVersion,
36 sp_runtime::{generic, OpaqueExtrinsic},
37 sp_state_machine::{Backend, TrieBackendBuilder},
38};
39
40#[cfg(feature = "std")]
42include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
43
44#[derive(Decode, Clone)]
48#[cfg_attr(feature = "std", derive(Encode))]
49pub struct StorageAccessParams<B: traits::Block> {
50 pub state_root: B::Hash,
51 pub storage_proof: StorageProof,
52 pub payload: StorageAccessPayload,
53 pub is_dry_run: bool,
55}
56
57#[derive(Debug, Clone, Decode, Encode)]
59pub enum StorageAccessPayload {
60 Read(Vec<(Vec<u8>, Option<ChildInfo>)>),
62 Write((Vec<(Vec<u8>, Vec<u8>)>, Option<ChildInfo>)),
64}
65
66impl<B: traits::Block> StorageAccessParams<B> {
67 pub fn new_read(
69 state_root: B::Hash,
70 storage_proof: StorageProof,
71 payload: Vec<(Vec<u8>, Option<ChildInfo>)>,
72 ) -> Self {
73 Self {
74 state_root,
75 storage_proof,
76 payload: StorageAccessPayload::Read(payload),
77 is_dry_run: false,
78 }
79 }
80
81 pub fn new_write(
83 state_root: B::Hash,
84 storage_proof: StorageProof,
85 payload: (Vec<(Vec<u8>, Vec<u8>)>, Option<ChildInfo>),
86 ) -> Self {
87 Self {
88 state_root,
89 storage_proof,
90 payload: StorageAccessPayload::Write(payload),
91 is_dry_run: false,
92 }
93 }
94
95 pub fn as_dry_run(&self) -> Self {
97 Self {
98 state_root: self.state_root,
99 storage_proof: self.storage_proof.clone(),
100 payload: self.payload.clone(),
101 is_dry_run: true,
102 }
103 }
104}
105
106#[doc(hidden)]
110#[cfg(all(not(feature = "std"), feature = "runtime-benchmarks"))]
111pub fn proceed_storage_access<B: traits::Block>(mut params: &[u8]) {
112 let StorageAccessParams { state_root, storage_proof, payload, is_dry_run } =
113 StorageAccessParams::<B>::decode(&mut params)
114 .expect("Invalid arguments to `validate_block`.");
115
116 let db = storage_proof.into_memory_db();
117 let recorder = SizeOnlyRecorderProvider::<traits::HashingFor<B>>::default();
118 let cache_provider = CacheProvider::new();
119 let backend = TrieBackendBuilder::new_with_cache(db, state_root, cache_provider)
120 .with_recorder(recorder)
121 .build();
122
123 if is_dry_run {
124 return;
125 }
126
127 match payload {
128 StorageAccessPayload::Read(keys) =>
129 for (key, maybe_child_info) in keys {
130 match maybe_child_info {
131 Some(child_info) => {
132 let _ = backend
133 .child_storage(&child_info, key.as_ref())
134 .expect("Key not found")
135 .ok_or("Value unexpectedly empty");
136 },
137 None => {
138 let _ = backend
139 .storage(key.as_ref())
140 .expect("Key not found")
141 .ok_or("Value unexpectedly empty");
142 },
143 }
144 },
145 StorageAccessPayload::Write((changes, maybe_child_info)) => {
146 let delta = changes.iter().map(|(key, value)| (key.as_ref(), Some(value.as_ref())));
147 match maybe_child_info {
148 Some(child_info) => {
149 backend.child_storage_root(&child_info, delta, StateVersion::V1);
150 },
151 None => {
152 backend.storage_root(delta, StateVersion::V1);
153 },
154 }
155 },
156 }
157}
158
159#[cfg(feature = "std")]
161pub fn wasm_binary_unwrap() -> &'static [u8] {
162 WASM_BINARY.expect(
163 "Development wasm binary is not available. Unset SKIP_WASM_BUILD and compile the runtime again.",
164 )
165}
166
167#[cfg(enable_alloc_error_handler)]
168#[alloc_error_handler]
169#[no_mangle]
170pub fn oom(_: core::alloc::Layout) -> ! {
171 core::intrinsics::abort();
172}
173
174#[cfg(all(not(feature = "std"), feature = "runtime-benchmarks"))]
175#[no_mangle]
176pub extern "C" fn validate_block(params: *const u8, len: usize) -> u64 {
177 type Block = generic::Block<generic::Header<u32, traits::BlakeTwo256>, OpaqueExtrinsic>;
178 let params = unsafe { alloc::slice::from_raw_parts(params, len) };
179 proceed_storage_access::<Block>(params);
180 1
181}