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
// Copyright (C) 2023 Polytope Labs (Caymans) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program 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.

// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
#![deny(missing_docs, unused_extern_crates)]

//! ### sc-simnode
use sc_client_api::ExecutorProvider;
use sp_api::ConstructRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_runtime::traits::{Block as BlockT, SignedExtension};
use sp_state_machine::{Ext, OverlayedChanges};
use std::sync::Arc;

pub mod cli;
pub mod client;
pub mod overrides;
pub mod rpc;
pub mod sproof;

pub use cli::*;
pub use client::*;
pub use overrides::*;
pub use rpc::*;
pub use sproof::*;

/// Wrapper trait for concrete type required by this testing framework.
pub trait ChainInfo: Sized {
	/// Opaque block type
	type Block: BlockT;

	/// Runtime
	type Runtime: frame_system::Config;

	/// RuntimeApi
	type RuntimeApi: ConstructRuntimeApi<Self::Block, FullClientFor<Self>> + Send + Sync + 'static;

	/// The signed extras required by the runtime
	type SignedExtras: SignedExtension;

	/// This is for cases you don't yet have the simnode runtime api implemented.
	/// this function is caled in an externalities provided environment, so feel free to read state.
	fn signed_extras(
		from: <Self::Runtime as frame_system::Config>::AccountId,
	) -> Self::SignedExtras;
}

/// Runs the given closure in an externalities provided environment, over the blockchain state
pub fn with_state<T: ChainInfo, R>(
	client: Arc<FullClientFor<T>>,
	id: Option<<T::Block as BlockT>::Hash>,
	closure: impl FnOnce() -> R,
) -> R {
	let mut overlay = OverlayedChanges::default();
	let id = id.unwrap_or_else(|| client.info().best_hash);
	let block_number =
		client.number(id).ok().flatten().unwrap_or_else(|| client.info().best_number);
	let mut extensions = client.execution_extensions().extensions(id, block_number);
	let state_backend = client.state_at(id).expect(&format!("State at block {} not found", id));

	let mut ext = Ext::new(&mut overlay, &state_backend, Some(&mut extensions));
	sp_externalities::set_and_run_with_externalities(&mut ext, closure)
}