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

            
17
use crate::lazy_loading;
18
use cumulus_primitives_core::BlockT;
19
use parity_scale_codec::Encode;
20
use sc_client_api::{Backend, BlockImportOperation, NewBlockState};
21
use sp_core::{twox_128, twox_64, H256};
22
use sp_runtime::traits::{Header, One};
23
use sp_runtime::Saturating;
24
use sp_storage::{StateVersion, Storage, StorageKey};
25
use std::sync::Arc;
26

            
27
pub 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
	// Update System::Number so that frame_system::initialize() doesn't panic
57
	// with "Block number must be strictly increasing" on the next block.
58
	let number_key = [
59
		twox_128(b"System").as_slice(),
60
		twox_128(b"Number").as_slice(),
61
	]
62
	.concat();
63
	state_overrides.push((number_key, next_block_number.encode()));
64

            
65
	let _ = op.reset_storage(
66
		Storage {
67
			top: state_overrides.into_iter().collect(),
68
			children_default: Default::default(),
69
		},
70
		StateVersion::V1,
71
	)?;
72

            
73
	// Create empty first block
74
	let _ = op.set_block_data(
75
		header.clone(),
76
		Some(Default::default()),
77
		None,
78
		None,
79
		NewBlockState::Final,
80
	);
81

            
82
	backend.commit_operation(op)
83
}
84

            
85
pub fn get_parachain_id(rpc_client: Arc<super::rpc_client::RPC>) -> Option<u32> {
86
	let key = [twox_128(b"ParachainInfo"), twox_128(b"ParachainId")].concat();
87
	let result = rpc_client.storage::<H256>(StorageKey(key), None);
88

            
89
	result
90
		.map(|o| {
91
			o.and_then(|data| {
92
				<u32 as parity_scale_codec::Decode>::decode(&mut data.0.as_slice()).ok()
93
			})
94
		})
95
		.ok()
96
		.flatten()
97
}