1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Copyright 2024 Moonbeam foundation
// This file is part of Moonbeam.

// Moonbeam is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Moonbeam is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.

use crate::lazy_loading;
use crate::lazy_loading::backend::RPC;
use cumulus_primitives_core::BlockT;
use parity_scale_codec::Encode;
use sc_client_api::{Backend, BlockImportOperation, NewBlockState};
use sp_core::{twox_128, twox_64, H256};
use sp_runtime::traits::{Header, One};
use sp_runtime::Saturating;
use sp_storage::{StateVersion, Storage, StorageKey};
use std::sync::Arc;

pub fn produce_first_block<Block: BlockT + sp_runtime::DeserializeOwned>(
	backend: Arc<lazy_loading::backend::Backend<Block>>,
	fork_checkpoint: Block,
	mut state_overrides: Vec<(Vec<u8>, Vec<u8>)>,
) -> sp_blockchain::Result<()> {
	let mut op = backend.begin_operation()?;

	let header = fork_checkpoint.header().clone();
	let next_block_number = header.number().saturating_add(One::one());

	let header: Block::Header = Block::Header::new(
		next_block_number,
		Default::default(),
		Default::default(),
		header.hash(),
		Default::default(),
	);

	// IMPORTANT: Add first block after the fork to frame_system::BlockHash
	// This is required by CheckMortality/CheckEra in SignedExtension
	let key = [
		&twox_128(b"System"),
		&twox_128(b"BlockHash"),
		twox_64(&next_block_number.encode()).as_slice(),
		&next_block_number.encode(),
	]
	.concat();
	state_overrides.push((key, header.hash().encode()));

	let _ = op.reset_storage(
		Storage {
			top: state_overrides.into_iter().collect(),
			children_default: Default::default(),
		},
		StateVersion::V1,
	)?;

	// Create empty first block
	let _ = op.set_block_data(
		header.clone(),
		Some(Default::default()),
		None,
		None,
		NewBlockState::Final,
	);

	backend.commit_operation(op)
}

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

	result
		.map(|o| {
			o.and_then(|data| {
				<u32 as parity_scale_codec::Decode>::decode(&mut data.0.as_slice()).ok()
			})
		})
		.ok()
		.flatten()
}