1use bitcoin::Block;
2use bitcoin::consensus::Decodable;
3use bitcoin::hex::FromHex;
4use sc_consensus_nakamoto::{
5 BitcoinBlockImport, BitcoinBlockImporter, BlockVerification, ImportConfig, ImportStatus,
6 ScriptEngine,
7};
8use sc_service::config::{
9 BlocksPruning, DatabaseSource, ExecutorConfiguration, KeystoreConfig, NetworkConfiguration,
10 OffchainWorkerConfig, PruningMode, RpcBatchRequestConfig, RpcConfiguration,
11 WasmExecutionMethod, WasmtimeInstantiationStrategy,
12};
13use sc_service::error::Error as ServiceError;
14use sc_service::{BasePath, ChainSpec, Configuration, Role};
15use sp_consensus::BlockOrigin;
16use sp_keyring::sr25519::Keyring as Sr25519Keyring;
17use std::sync::Arc;
18use subcoin_service::{FullClient, NodeComponents, SubcoinConfiguration};
19
20fn decode_raw_block(hex_str: &str) -> Block {
21 let data = Vec::<u8>::from_hex(hex_str).expect("Failed to convert hex str");
22 Block::consensus_decode(&mut data.as_slice()).expect("Failed to convert hex data to Block")
23}
24
25pub fn block_data() -> Vec<Block> {
26 let block0 = decode_raw_block(
28 "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",
29 );
30 let block1 = decode_raw_block(
33 "010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e362990101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000",
34 );
35 let block2 = decode_raw_block(
38 "010000004860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000d5fdcc541e25de1c7a5addedf24858b8bb665c9f36ef744ee42c316022c90f9bb0bc6649ffff001d08d2bd610101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d010bffffffff0100f2052a010000004341047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77ac00000000",
39 );
40 let block3 = decode_raw_block(
43 "01000000bddd99ccfda39da1b108ce1a5d70038d0a967bacb68b6b63065f626a0000000044f672226090d85db9a9f2fbfe5f0f9609b387af7be5b7fbb7a1767c831c9e995dbe6649ffff001d05e0ed6d0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d010effffffff0100f2052a0100000043410494b9d3e76c5b1629ecf97fff95d7a4bbdac87cc26099ada28066c6ff1eb9191223cd897194a08d0c2726c5747f1db49e8cf90e75dc3e3550ae9b30086f3cd5aaac00000000",
44 );
45 vec![block0, block1, block2, block3]
46}
47
48pub fn full_test_configuration(
49 tokio_handle: tokio::runtime::Handle,
50 chain_spec: Box<dyn ChainSpec>,
51) -> Configuration {
52 let tmp = tempfile::tempdir().unwrap();
53 let base_path = BasePath::new(tmp.path());
54 let root = base_path.path().to_path_buf();
55
56 let network_config = NetworkConfiguration::new(
57 Sr25519Keyring::Alice.to_seed(),
58 "network/test/0.1",
59 Default::default(),
60 None,
61 );
62
63 Configuration {
64 impl_name: "subcoin-test-node".to_string(),
65 impl_version: "1.0".to_string(),
66 role: Role::Full,
67 tokio_handle,
68 transaction_pool: Default::default(),
69 network: network_config,
70 keystore: KeystoreConfig::InMemory,
71 database: DatabaseSource::ParityDb {
72 path: root.join("db"),
73 },
74 trie_cache_maximum_size: Some(64 * 1024 * 1024),
75 state_pruning: Some(PruningMode::ArchiveAll),
76 blocks_pruning: BlocksPruning::KeepAll,
77 chain_spec,
78 executor: ExecutorConfiguration {
79 wasm_method: WasmExecutionMethod::Compiled {
80 instantiation_strategy: WasmtimeInstantiationStrategy::PoolingCopyOnWrite,
81 },
82 max_runtime_instances: 8,
83 runtime_cache_size: 2,
84 default_heap_pages: None,
85 },
86 rpc: RpcConfiguration {
87 addr: None,
88 max_connections: Default::default(),
89 cors: None,
90 methods: Default::default(),
91 max_request_size: Default::default(),
92 max_response_size: Default::default(),
93 id_provider: Default::default(),
94 max_subs_per_conn: Default::default(),
95 port: 9944,
96 message_buffer_capacity: Default::default(),
97 batch_config: RpcBatchRequestConfig::Unlimited,
98 rate_limit: None,
99 rate_limit_whitelisted_ips: Default::default(),
100 rate_limit_trust_proxy_headers: Default::default(),
101 },
102 prometheus_config: None,
103 telemetry_endpoints: None,
104 offchain_worker: OffchainWorkerConfig {
105 enabled: true,
106 indexing_enabled: false,
107 },
108 force_authoring: false,
109 disable_grandpa: false,
110 dev_key_seed: Some(Sr25519Keyring::Alice.to_seed()),
111 tracing_targets: None,
112 tracing_receiver: Default::default(),
113 announce_block: true,
114 data_path: base_path.path().into(),
115 base_path,
116 wasm_runtime_overrides: None,
117 warm_up_trie_cache: None,
118 }
119}
120
121pub fn test_configuration(tokio_handle: tokio::runtime::Handle) -> Configuration {
122 let spec = subcoin_service::chain_spec::config(bitcoin::Network::Bitcoin)
123 .expect("Failed to create chain spec");
124
125 full_test_configuration(tokio_handle, Box::new(spec))
126}
127
128pub fn new_test_node(tokio_handle: tokio::runtime::Handle) -> Result<NodeComponents, ServiceError> {
129 let config = test_configuration(tokio_handle);
130 subcoin_service::new_node(SubcoinConfiguration {
131 network: bitcoin::Network::Bitcoin,
132 config: &config,
133 no_hardware_benchmarks: true,
134 storage_monitor: Default::default(),
135 })
136}
137
138pub async fn new_test_node_and_produce_blocks(
139 config: &Configuration,
140 up_to: u32,
141) -> Arc<FullClient> {
142 let NodeComponents { client, .. } =
143 subcoin_service::new_node(SubcoinConfiguration::test_config(config))
144 .expect("Failed to create node");
145
146 let mut bitcoin_block_import =
147 BitcoinBlockImporter::<_, _, _, _, subcoin_service::TransactionAdapter>::new(
148 client.clone(),
149 client.clone(),
150 ImportConfig {
151 network: bitcoin::Network::Bitcoin,
152 block_verification: BlockVerification::None,
153 execute_block: true,
154 script_engine: ScriptEngine::Core,
155 },
156 Arc::new(subcoin_service::CoinStorageKey),
157 None,
158 );
159
160 let test_blocks = block_data();
161
162 if up_to as usize >= test_blocks.len() {
163 panic!(
164 "Can not produce too many blocks (maximum: {}) in test env",
165 test_blocks.len()
166 );
167 }
168
169 for block_number in 1..=up_to {
170 let block = test_blocks[block_number as usize].clone();
171 let import_status = bitcoin_block_import
172 .import_block(block, BlockOrigin::Own)
173 .await
174 .unwrap();
175 assert!(matches!(import_status, ImportStatus::Imported { .. }));
176 }
177
178 client
179}