frame_storage_access_test_runtime/
lib.rs1#![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 },
146 StorageAccessPayload::Write((changes, maybe_child_info)) => {
147 let delta = changes.iter().map(|(key, value)| (key.as_ref(), Some(value.as_ref())));
148 match maybe_child_info {
149 Some(child_info) => {
150 backend.child_storage_root(&child_info, delta, StateVersion::V1);
151 },
152 None => {
153 backend.storage_root(delta, StateVersion::V1);
154 },
155 }
156 },
157 }
158}
159
160#[cfg(feature = "std")]
162pub fn wasm_binary_unwrap() -> &'static [u8] {
163 WASM_BINARY.expect(
164 "Development wasm binary is not available. Unset SKIP_WASM_BUILD and compile the runtime again.",
165 )
166}
167
168#[cfg(enable_alloc_error_handler)]
169#[alloc_error_handler]
170#[no_mangle]
171pub fn oom(_: core::alloc::Layout) -> ! {
172 core::intrinsics::abort();
173}
174
175#[cfg(all(not(feature = "std"), feature = "runtime-benchmarks"))]
176#[no_mangle]
177pub extern "C" fn validate_block(params: *const u8, len: usize) -> u64 {
178 type Block = generic::Block<generic::Header<u32, traits::BlakeTwo256>, OpaqueExtrinsic>;
179 let params = unsafe { alloc::slice::from_raw_parts(params, len) };
180 proceed_storage_access::<Block>(params);
181 1
182}