moonbeam_service/lazy_loading/
helpers.rs

1// Copyright 2024 Moonbeam foundation
2// This file is part of Moonbeam.
3
4// Moonbeam is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Moonbeam is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16
17use crate::lazy_loading;
18use cumulus_primitives_core::BlockT;
19use parity_scale_codec::Encode;
20use sc_client_api::{Backend, BlockImportOperation, NewBlockState};
21use sp_core::{twox_128, twox_64, H256};
22use sp_runtime::traits::{Header, One};
23use sp_runtime::Saturating;
24use sp_storage::{StateVersion, Storage, StorageKey};
25use std::sync::Arc;
26
27pub fn produce_first_block<Block: BlockT + sp_runtime::DeserializeOwned>(
28	backend: Arc<lazy_loading::substrate_backend::Backend<Block>>,
29	fork_checkpoint: Block,
30	mut state_overrides: Vec<(Vec<u8>, Vec<u8>)>,
31) -> sp_blockchain::Result<()> {
32	let mut op = backend.begin_operation()?;
33
34	let header = fork_checkpoint.header().clone();
35	let next_block_number = header.number().saturating_add(One::one());
36
37	let header: Block::Header = Block::Header::new(
38		next_block_number,
39		Default::default(),
40		Default::default(),
41		header.hash(),
42		Default::default(),
43	);
44
45	// IMPORTANT: Add first block after the fork to frame_system::BlockHash
46	// This is required by CheckMortality/CheckEra in SignedExtension
47	let key = [
48		&twox_128(b"System"),
49		&twox_128(b"BlockHash"),
50		twox_64(&next_block_number.encode()).as_slice(),
51		&next_block_number.encode(),
52	]
53	.concat();
54	state_overrides.push((key, header.hash().encode()));
55
56	let _ = op.reset_storage(
57		Storage {
58			top: state_overrides.into_iter().collect(),
59			children_default: Default::default(),
60		},
61		StateVersion::V1,
62	)?;
63
64	// Create empty first block
65	let _ = op.set_block_data(
66		header.clone(),
67		Some(Default::default()),
68		None,
69		None,
70		NewBlockState::Final,
71	);
72
73	backend.commit_operation(op)
74}
75
76pub fn get_parachain_id(rpc_client: Arc<super::rpc_client::RPC>) -> Option<u32> {
77	let key = [twox_128(b"ParachainInfo"), twox_128(b"ParachainId")].concat();
78	let result = rpc_client.storage::<H256>(StorageKey(key), None);
79
80	result
81		.map(|o| {
82			o.and_then(|data| {
83				<u32 as parity_scale_codec::Decode>::decode(&mut data.0.as_slice()).ok()
84			})
85		})
86		.ok()
87		.flatten()
88}