1#[cfg(not(feature = "std"))]
2extern crate alloc;
3
4use crate::{
5 DomainId, PermissionedActionAllowedBy, evm_chain_id_storage_key,
6 evm_contract_creation_allowed_by_storage_key, self_domain_id_storage_key,
7};
8#[cfg(not(feature = "std"))]
9use alloc::vec::Vec;
10use domain_runtime_primitives::{EVMChainId, EthereumAccountId};
11use hash_db::Hasher;
12use parity_scale_codec::{Codec, Decode, Encode};
13use scale_info::TypeInfo;
14use sp_core::storage::{ChildInfo, well_known_keys};
15#[cfg(feature = "std")]
16use sp_core::storage::{Storage, StorageChild};
17use sp_runtime::StateVersion;
18use sp_state_machine::{Backend, TrieBackend, TrieBackendBuilder};
19use sp_std::collections::btree_map::BTreeMap;
20use sp_trie::{LayoutV0, MemoryDB, RandomState, empty_trie_root};
21
22fn new_in_mem<H>() -> TrieBackend<MemoryDB<H>, H>
28where
29 H: Hasher,
30 H::Out: Codec + Ord,
31{
32 let db = MemoryDB::with_hasher(RandomState::default());
33 TrieBackendBuilder::new(db, empty_trie_root::<LayoutV0<H>>()).build()
35}
36
37#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode, TypeInfo)]
39pub struct StorageKey(pub Vec<u8>);
40
41#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode, TypeInfo)]
43pub struct StorageData(pub Vec<u8>);
44
45type GenesisStorage = BTreeMap<StorageKey, StorageData>;
46
47#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode, TypeInfo)]
49pub struct RawGenesis {
50 top: GenesisStorage,
51 children_default: BTreeMap<StorageKey, GenesisStorage>,
52}
53
54impl RawGenesis {
55 pub fn set_domain_id(&mut self, domain_id: DomainId) {
56 let _ = self.top.insert(
57 self_domain_id_storage_key(),
58 StorageData(domain_id.encode()),
59 );
60 }
61
62 pub fn set_evm_chain_id(&mut self, chain_id: EVMChainId) {
63 let _ = self
64 .top
65 .insert(evm_chain_id_storage_key(), StorageData(chain_id.encode()));
66 }
67
68 pub fn set_evm_contract_creation_allowed_by(
69 &mut self,
70 contract_creation_allowed_by: &PermissionedActionAllowedBy<EthereumAccountId>,
71 ) {
72 let _ = self.top.insert(
73 evm_contract_creation_allowed_by_storage_key(),
74 StorageData(contract_creation_allowed_by.encode()),
75 );
76 }
77
78 pub fn set_top_storages(&mut self, storages: Vec<(StorageKey, StorageData)>) {
79 for (k, v) in storages {
80 let _ = self.top.insert(k, v);
81 }
82 }
83
84 fn set_runtime_code(&mut self, code: Vec<u8>) {
85 let _ = self.top.insert(
86 StorageKey(well_known_keys::CODE.to_vec()),
87 StorageData(code),
88 );
89 }
90
91 pub fn get_runtime_code(&self) -> Option<&[u8]> {
92 self.top
93 .get(&StorageKey(well_known_keys::CODE.to_vec()))
94 .map(|sd| sd.0.as_ref())
95 }
96
97 pub fn take_runtime_code(&mut self) -> Option<Vec<u8>> {
98 self.top
99 .remove(&StorageKey(well_known_keys::CODE.to_vec()))
100 .map(|sd| sd.0)
101 }
102
103 pub fn state_root<H>(&self, state_version: StateVersion) -> H::Out
104 where
105 H: Hasher,
106 H::Out: Codec + Ord,
107 {
108 let backend = new_in_mem::<H>();
109
110 let child_infos: Vec<_> = self
114 .children_default
115 .keys()
116 .map(|k| ChildInfo::new_default(k.0.as_slice()))
117 .collect();
118 let child_delta = child_infos.iter().zip(
119 self.children_default
120 .values()
121 .map(|v| v.iter().map(|(k, v)| (&k.0[..], Some(&v.0[..])))),
122 );
123
124 let (root, _) = backend.full_storage_root(
125 self.top.iter().map(|(k, v)| (&k.0[..], Some(&v.0[..]))),
126 child_delta,
127 state_version,
128 );
129
130 root
131 }
132
133 pub fn dummy(code: Vec<u8>) -> Self {
134 let mut raw_genesis = Self::default();
135 raw_genesis.set_runtime_code(code);
136 raw_genesis
137 }
138}
139
140#[cfg(feature = "std")]
141impl RawGenesis {
142 pub fn from_storage(storage: Storage) -> Self {
146 let top = storage
147 .top
148 .into_iter()
149 .map(|(k, v)| (StorageKey(k), StorageData(v)))
150 .collect();
151
152 let children_default = storage
153 .children_default
154 .into_iter()
155 .map(|(k, child)| {
156 (
157 StorageKey(k),
158 child
159 .data
160 .into_iter()
161 .map(|(k, v)| (StorageKey(k), StorageData(v)))
162 .collect(),
163 )
164 })
165 .collect();
166
167 RawGenesis {
168 top,
169 children_default,
170 }
171 }
172
173 pub fn into_storage(self) -> Storage {
177 let RawGenesis {
178 top: map,
179 children_default: children_map,
180 } = self;
181 let mut storage = Storage::default();
182
183 storage.top.extend(map.into_iter().map(|(k, v)| (k.0, v.0)));
184
185 children_map.into_iter().for_each(|(k, v)| {
186 let child_info = ChildInfo::new_default(k.0.as_slice());
187 storage
188 .children_default
189 .entry(k.0)
190 .or_insert_with(|| StorageChild {
191 data: Default::default(),
192 child_info,
193 })
194 .data
195 .extend(v.into_iter().map(|(k, v)| (k.0, v.0)));
196 });
197
198 storage
199 }
200}