1use std::{
21 any::{TypeId, Any},
22 marker::PhantomData,
23};
24use crate::{Backend, StorageKey, StorageValue};
25use tetsy_hash_db::Hasher;
26use tet_core::{
27 storage::{ChildInfo, TrackedStorageKey},
28 traits::Externalities, Blake2Hasher,
29};
30use codec::Encode;
31
32pub trait InspectState<H: Hasher, B: Backend<H>> {
36 fn inspect_state<F: FnOnce() -> R, R>(&self, f: F) -> R;
43}
44
45impl<H: Hasher, B: Backend<H>> InspectState<H, B> for B {
46 fn inspect_state<F: FnOnce() -> R, R>(&self, f: F) -> R {
47 ReadOnlyExternalities::from(self).execute_with(f)
48 }
49}
50
51#[derive(Debug)]
56pub struct ReadOnlyExternalities<'a, H: Hasher, B: 'a + Backend<H>> {
57 backend: &'a B,
58 _phantom: PhantomData<H>,
59}
60
61impl<'a, H: Hasher, B: 'a + Backend<H>> From<&'a B> for ReadOnlyExternalities<'a, H, B> {
62 fn from(backend: &'a B) -> Self {
63 ReadOnlyExternalities { backend, _phantom: PhantomData }
64 }
65}
66
67impl<'a, H: Hasher, B: 'a + Backend<H>> ReadOnlyExternalities<'a, H, B> {
68 pub fn execute_with<R>(&mut self, f: impl FnOnce() -> R) -> R {
72 externalities::set_and_run_with_externalities(self, f)
73 }
74}
75
76impl<'a, H: Hasher, B: 'a + Backend<H>> Externalities for ReadOnlyExternalities<'a, H, B> {
77 fn set_offchain_storage(&mut self, _key: &[u8], _value: Option<&[u8]>) {
78 panic!("Should not be used in read-only externalities!")
79 }
80
81 fn storage(&self, key: &[u8]) -> Option<StorageValue> {
82 self.backend.storage(key).expect("Backed failed for storage in ReadOnlyExternalities")
83 }
84
85 fn storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
86 self.storage(key).map(|v| Blake2Hasher::hash(&v).encode())
87 }
88
89 fn child_storage(
90 &self,
91 child_info: &ChildInfo,
92 key: &[u8],
93 ) -> Option<StorageValue> {
94 self.backend.child_storage(child_info, key).expect("Backed failed for child_storage in ReadOnlyExternalities")
95 }
96
97 fn child_storage_hash(
98 &self,
99 child_info: &ChildInfo,
100 key: &[u8],
101 ) -> Option<Vec<u8>> {
102 self.child_storage(child_info, key).map(|v| Blake2Hasher::hash(&v).encode())
103 }
104
105 fn next_storage_key(&self, key: &[u8]) -> Option<StorageKey> {
106 self.backend.next_storage_key(key).expect("Backed failed for next_storage_key in ReadOnlyExternalities")
107 }
108
109 fn next_child_storage_key(
110 &self,
111 child_info: &ChildInfo,
112 key: &[u8],
113 ) -> Option<StorageKey> {
114 self.backend.next_child_storage_key(child_info, key)
115 .expect("Backed failed for next_child_storage_key in ReadOnlyExternalities")
116 }
117
118 fn place_storage(&mut self, _key: StorageKey, _maybe_value: Option<StorageValue>) {
119 unimplemented!("place_storage not supported in ReadOnlyExternalities")
120 }
121
122 fn place_child_storage(
123 &mut self,
124 _child_info: &ChildInfo,
125 _key: StorageKey,
126 _value: Option<StorageValue>,
127 ) {
128 unimplemented!("place_child_storage not supported in ReadOnlyExternalities")
129 }
130
131 fn kill_child_storage(
132 &mut self,
133 _child_info: &ChildInfo,
134 _limit: Option<u32>,
135 ) -> bool {
136 unimplemented!("kill_child_storage is not supported in ReadOnlyExternalities")
137 }
138
139 fn clear_prefix(&mut self, _prefix: &[u8]) {
140 unimplemented!("clear_prefix is not supported in ReadOnlyExternalities")
141 }
142
143 fn clear_child_prefix(
144 &mut self,
145 _child_info: &ChildInfo,
146 _prefix: &[u8],
147 ) {
148 unimplemented!("clear_child_prefix is not supported in ReadOnlyExternalities")
149 }
150
151 fn storage_append(
152 &mut self,
153 _key: Vec<u8>,
154 _value: Vec<u8>,
155 ) {
156 unimplemented!("storage_append is not supported in ReadOnlyExternalities")
157 }
158
159 fn storage_root(&mut self) -> Vec<u8> {
160 unimplemented!("storage_root is not supported in ReadOnlyExternalities")
161 }
162
163 fn child_storage_root(
164 &mut self,
165 _child_info: &ChildInfo,
166 ) -> Vec<u8> {
167 unimplemented!("child_storage_root is not supported in ReadOnlyExternalities")
168 }
169
170 fn storage_changes_root(&mut self, _parent: &[u8]) -> Result<Option<Vec<u8>>, ()> {
171 unimplemented!("storage_changes_root is not supported in ReadOnlyExternalities")
172 }
173
174 fn storage_start_transaction(&mut self) {
175 unimplemented!("Transactions are not supported by ReadOnlyExternalities");
176 }
177
178 fn storage_rollback_transaction(&mut self) -> Result<(), ()> {
179 unimplemented!("Transactions are not supported by ReadOnlyExternalities");
180 }
181
182 fn storage_commit_transaction(&mut self) -> Result<(), ()> {
183 unimplemented!("Transactions are not supported by ReadOnlyExternalities");
184 }
185
186 fn wipe(&mut self) {}
187
188 fn commit(&mut self) {}
189
190 fn read_write_count(&self) -> (u32, u32, u32, u32) {
191 unimplemented!("read_write_count is not supported in ReadOnlyExternalities")
192 }
193
194 fn reset_read_write_count(&mut self) {
195 unimplemented!("reset_read_write_count is not supported in ReadOnlyExternalities")
196 }
197
198 fn get_whitelist(&self) -> Vec<TrackedStorageKey> {
199 unimplemented!("get_whitelist is not supported in ReadOnlyExternalities")
200 }
201
202 fn set_whitelist(&mut self, _: Vec<TrackedStorageKey>) {
203 unimplemented!("set_whitelist is not supported in ReadOnlyExternalities")
204 }
205}
206
207impl<'a, H: Hasher, B: 'a + Backend<H>> externalities::ExtensionStore for ReadOnlyExternalities<'a, H, B> {
208 fn extension_by_type_id(&mut self, _type_id: TypeId) -> Option<&mut dyn Any> {
209 unimplemented!("extension_by_type_id is not supported in ReadOnlyExternalities")
210 }
211
212 fn register_extension_with_type_id(
213 &mut self,
214 _type_id: TypeId,
215 _extension: Box<dyn externalities::Extension>,
216 ) -> Result<(), externalities::Error> {
217 unimplemented!("register_extension_with_type_id is not supported in ReadOnlyExternalities")
218 }
219
220 fn deregister_extension_by_type_id(&mut self, _type_id: TypeId) -> Result<(), externalities::Error> {
221 unimplemented!("deregister_extension_by_type_id is not supported in ReadOnlyExternalities")
222 }
223}