1#![warn(missing_docs)]
3
4use crate::chain_spec::create_domain_spec;
5use crate::{
6 AUTO_ID_DOMAIN_ID, BalanceOf, DomainRuntime, EVM_DOMAIN_ID, EcdsaKeyring, Sr25519Keyring,
7 UncheckedExtrinsicFor, construct_extrinsic_generic, node_config,
8};
9use cross_domain_message_gossip::ChainMsg;
10use domain_block_preprocessor::inherents::CreateInherentDataProvider;
11use domain_client_operator::snap_sync::ConsensusChainSyncParams;
12use domain_client_operator::{BootstrapResult, OperatorStreams, fetch_domain_bootstrap_info};
13use domain_eth_service::provider::EthProvider;
14use domain_eth_service::{DefaultEthConfig, EthConfiguration};
15use domain_runtime_primitives::opaque::Block;
16use domain_runtime_primitives::{Balance, EthereumAccountId};
17use domain_service::providers::DefaultProvider;
18use domain_service::{FullBackend, FullClient, FullPool};
19use domain_test_primitives::{EvmOnchainStateApi, OnchainStateApi};
20use frame_support::dispatch::{DispatchInfo, PostDispatchInfo};
21use frame_system::pallet_prelude::{BlockNumberFor, RuntimeCallFor};
22use pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi;
23use sc_client_api::HeaderBackend;
24use sc_domains::RuntimeExecutor;
25use sc_network::service::traits::NetworkService;
26use sc_network::{NetworkStateInfo, ReputationChange};
27use sc_network_sync::SyncingService;
28use sc_service::config::MultiaddrWithPeerId;
29use sc_service::{BasePath, Role, RpcHandlers, TFullBackend, TaskManager, TransactionPool};
30use sc_transaction_pool::FullChainApi;
31use sc_transaction_pool_api::OffchainTransactionPoolFactory;
32use sc_utils::mpsc::{TracingUnboundedSender, tracing_unbounded};
33use sp_api::{ApiExt, ConstructRuntimeApi, Metadata, ProvideRuntimeApi};
34use sp_block_builder::BlockBuilder;
35use sp_blockchain::HashAndNumber;
36use sp_consensus_subspace::SubspaceApi;
37use sp_core::{Encode, H256};
38use sp_domains::core_api::DomainCoreApi;
39use sp_domains::{DomainId, DomainsApi, OperatorId, PermissionedActionAllowedBy};
40use sp_messenger::messages::{ChainId, ChannelId};
41use sp_messenger::{MessengerApi, RelayerApi};
42use sp_offchain::OffchainWorkerApi;
43use sp_runtime::OpaqueExtrinsic;
44use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable, NumberFor};
45use sp_session::SessionKeys;
46use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
47use std::future::Future;
48use std::net::SocketAddr;
49use std::sync::Arc;
50use std::time::Duration;
51use subspace_runtime_primitives::opaque::Block as CBlock;
52use subspace_runtime_primitives::{BlockHashFor, HeaderFor, Nonce};
53use subspace_test_service::MockConsensusNode;
54use substrate_frame_rpc_system::AccountNonceApi;
55use substrate_test_client::{
56 BlockchainEventsExt, RpcHandlersExt, RpcTransactionError, RpcTransactionOutput,
57};
58use tokio::time::sleep;
59
60pub type Backend = TFullBackend<Block>;
62
63type Client<RuntimeApi> = FullClient<Block, RuntimeApi>;
64
65pub type DomainOperator<RuntimeApi> =
67 domain_service::DomainOperator<Block, CBlock, subspace_test_client::Client, RuntimeApi>;
68
69pub struct DomainNode<Runtime, RuntimeApi>
71where
72 Runtime: DomainRuntime,
73 RuntimeApi: ConstructRuntimeApi<Block, Client<RuntimeApi>> + Send + Sync + 'static,
74 RuntimeApi::RuntimeApi: ApiExt<Block>
75 + Metadata<Block>
76 + BlockBuilder<Block>
77 + OffchainWorkerApi<Block>
78 + SessionKeys<Block>
79 + DomainCoreApi<Block>
80 + MessengerApi<Block, NumberFor<CBlock>, BlockHashFor<CBlock>>
81 + TaggedTransactionQueue<Block>
82 + AccountNonceApi<Block, Runtime::AccountId, Nonce>
83 + TransactionPaymentRuntimeApi<Block, Balance>
84 + RelayerApi<Block, NumberFor<Block>, NumberFor<CBlock>, BlockHashFor<CBlock>>,
85{
86 pub domain_id: DomainId,
88 pub key: Runtime::Keyring,
90 pub task_manager: TaskManager,
92 pub client: Arc<Client<RuntimeApi>>,
94 pub backend: Arc<Backend>,
96 pub code_executor: Arc<RuntimeExecutor>,
98 pub network_service: Arc<dyn NetworkService>,
100 pub sync_service: Arc<SyncingService<Block>>,
102 pub addr: MultiaddrWithPeerId,
105 pub rpc_handlers: RpcHandlers,
107 pub operator: DomainOperator<RuntimeApi>,
109 pub tx_pool_sink: TracingUnboundedSender<ChainMsg>,
111 pub base_path: BasePath,
113}
114
115impl<Runtime, RuntimeApi> DomainNode<Runtime, RuntimeApi>
116where
117 Runtime: frame_system::Config<Hash = H256>
118 + pallet_transaction_payment::Config
119 + DomainRuntime
120 + Send
121 + Sync,
122 Runtime::RuntimeCall:
123 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + Send + Sync,
124 crate::BalanceOf<Runtime>: Send + Sync + From<u64> + sp_runtime::FixedPointOperand,
125 u64: From<BlockNumberFor<Runtime>>,
126 RuntimeApi: ConstructRuntimeApi<Block, Client<RuntimeApi>> + Send + Sync + 'static,
127 RuntimeApi::RuntimeApi: ApiExt<Block>
128 + Metadata<Block>
129 + BlockBuilder<Block>
130 + OffchainWorkerApi<Block>
131 + SessionKeys<Block>
132 + DomainCoreApi<Block>
133 + TaggedTransactionQueue<Block>
134 + AccountNonceApi<Block, <Runtime as DomainRuntime>::AccountId, Nonce>
135 + TransactionPaymentRuntimeApi<Block, Balance>
136 + MessengerApi<Block, NumberFor<CBlock>, BlockHashFor<CBlock>>
137 + RelayerApi<Block, NumberFor<Block>, NumberFor<CBlock>, BlockHashFor<CBlock>>
138 + OnchainStateApi<Block, <Runtime as DomainRuntime>::AccountId, Balance>,
139 <RuntimeCallFor<Runtime> as Dispatchable>::RuntimeOrigin:
140 AsSystemOriginSigner<<Runtime as frame_system::Config>::AccountId> + Clone,
141{
142 #[allow(clippy::too_many_arguments)]
143 async fn build<Provider>(
144 domain_id: DomainId,
145 tokio_handle: tokio::runtime::Handle,
146 key: Runtime::Keyring,
147 base_path: BasePath,
148 domain_nodes: Vec<MultiaddrWithPeerId>,
149 domain_nodes_exclusive: bool,
150 skip_empty_bundle_production: bool,
151 maybe_operator_id: Option<OperatorId>,
152 role: Role,
153 mock_consensus_node: &mut MockConsensusNode,
154 rpc_addr: Option<SocketAddr>,
155 rpc_port: Option<u16>,
156 provider: Provider,
157 ) -> Self
158 where
159 Provider: domain_service::providers::BlockImportProvider<Block, Client<RuntimeApi>>
160 + domain_service::providers::RpcProvider<
161 Block,
162 Client<RuntimeApi>,
163 FullPool<RuntimeApi>,
164 FullChainApi<Client<RuntimeApi>, Block>,
165 Backend,
166 <Runtime as DomainRuntime>::AccountId,
167 CreateInherentDataProvider<subspace_test_client::Client, CBlock>,
168 > + 'static,
169 {
170 let mut domain_config = node_config(
171 domain_id,
172 tokio_handle.clone(),
173 Runtime::to_seed(key),
174 domain_nodes,
175 domain_nodes_exclusive,
176 role,
177 base_path.clone(),
178 Box::new(create_domain_spec()) as Box<_>,
179 rpc_addr,
180 rpc_port,
181 )
182 .expect("could not generate domain node Configuration");
183
184 let domain_backend = sc_service::new_db_backend::<Block>(domain_config.db_config())
185 .unwrap_or_else(
186 |err| {
187 tracing::error!("Failed to create domain backend: {domain_id:?} {role:?} {base_path:?} error: {err:?}");
188
189 for dir_path in base_path.path().ancestors() {
191 tracing::error!("{dir_path:?} try_exists: {:?}", dir_path.try_exists());
192 }
193 panic!("Failed to create domain backend: {domain_id:?} {role:?} {base_path:?} error: {err:?}")
194 }
195 );
196
197 let BootstrapResult {
198 domain_instance_data,
199 domain_created_at,
200 imported_block_notification_stream,
201 ..
202 } = fetch_domain_bootstrap_info::<Block, _, _, _>(
203 &*mock_consensus_node.client,
204 &*domain_backend,
205 domain_id,
206 )
207 .await
208 .expect("Failed to get domain instance data");
209
210 domain_config
211 .chain_spec
212 .set_storage(domain_instance_data.raw_genesis.into_storage());
213
214 let span = sc_tracing::tracing::info_span!(
215 sc_tracing::logging::PREFIX_LOG_SPAN,
216 name = domain_config.network.node_name.as_str()
217 );
218 let _enter = span.enter();
219
220 let multiaddr = domain_config.network.listen_addresses[0].clone();
221
222 let operator_streams = OperatorStreams {
223 consensus_block_import_throttling_buffer_size: 0,
226 block_importing_notification_stream: mock_consensus_node
227 .block_importing_notification_stream(),
228 imported_block_notification_stream,
229 new_slot_notification_stream: mock_consensus_node.new_slot_notification_stream(),
230 acknowledgement_sender_stream: mock_consensus_node.new_acknowledgement_sender_stream(),
231 _phantom: Default::default(),
232 };
233
234 let (domain_message_sink, domain_message_receiver) =
235 tracing_unbounded("domain_message_channel", 100);
236 let gossip_msg_sink = mock_consensus_node
237 .xdm_gossip_worker_builder()
238 .gossip_msg_sink();
239
240 let maybe_operator_id = role
241 .is_authority()
242 .then_some(maybe_operator_id.unwrap_or(if domain_id == EVM_DOMAIN_ID { 0 } else { 1 }));
243
244 let consensus_best_hash = mock_consensus_node.client.info().best_hash;
245 let runtime_api = mock_consensus_node.client.runtime_api();
246 let chain_constants = runtime_api.chain_constants(consensus_best_hash).unwrap();
247
248 let domain_block_pruning_depth = runtime_api
249 .block_pruning_depth(consensus_best_hash)
250 .unwrap();
251
252 let domain_params = domain_service::DomainParams {
253 domain_id,
254 domain_config,
255 domain_created_at,
256 consensus_client: mock_consensus_node.client.clone(),
257 consensus_offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(
258 mock_consensus_node.transaction_pool.clone(),
259 ),
260 domain_sync_oracle: mock_consensus_node.sync_service.clone(),
261 consensus_network: mock_consensus_node.network_service.clone(),
262 operator_streams,
263 gossip_message_sink: gossip_msg_sink,
264 domain_message_receiver,
265 provider,
266 skip_empty_bundle_production,
267 skip_out_of_order_slot: true,
268 maybe_operator_id,
269 confirmation_depth_k: chain_constants.confirmation_depth_k(),
270 challenge_period: domain_block_pruning_depth,
271 consensus_chain_sync_params: None::<ConsensusChainSyncParams<_, HeaderFor<Block>>>,
272 domain_backend,
273 };
274
275 let domain_node = domain_service::new_full::<
276 _,
277 _,
278 _,
279 _,
280 _,
281 _,
282 RuntimeApi,
283 <Runtime as DomainRuntime>::AccountId,
284 _,
285 >(domain_params)
286 .await
287 .expect("failed to build domain node");
288
289 let domain_service::NewFull {
290 task_manager,
291 client,
292 backend,
293 code_executor,
294 network_service,
295 sync_service,
296 network_starter,
297 rpc_handlers,
298 operator,
299 ..
300 } = domain_node;
301
302 if role.is_authority() {
303 mock_consensus_node
304 .xdm_gossip_worker_builder()
305 .push_chain_sink(ChainId::Domain(domain_id), domain_message_sink.clone());
306 }
307
308 let addr = MultiaddrWithPeerId {
309 multiaddr,
310 peer_id: network_service.local_peer_id(),
311 };
312
313 network_starter.start_network();
314
315 DomainNode {
316 domain_id,
317 key,
318 task_manager,
319 client,
320 backend,
321 code_executor,
322 network_service,
323 sync_service,
324 addr,
325 rpc_handlers,
326 operator,
327 tx_pool_sink: domain_message_sink,
328 base_path,
329 }
330 }
331
332 pub fn wait_for_blocks(&self, count: usize) -> impl Future<Output = ()> {
336 self.client.wait_for_blocks(count)
337 }
338
339 pub fn account_nonce(&self) -> u32 {
341 self.client
342 .runtime_api()
343 .account_nonce(
344 self.client.info().best_hash,
345 <Runtime as DomainRuntime>::account_id(self.key),
346 )
347 .expect("Fail to get account nonce")
348 }
349
350 pub fn account_nonce_of(&self, account_id: <Runtime as DomainRuntime>::AccountId) -> u32 {
352 self.client
353 .runtime_api()
354 .account_nonce(self.client.info().best_hash, account_id)
355 .expect("Fail to get account nonce")
356 }
357
358 pub async fn send_system_remark(&self) {
360 let nonce = self.account_nonce();
361 let _ = self
362 .construct_and_send_extrinsic(frame_system::Call::remark {
363 remark: nonce.encode(),
364 })
365 .await
366 .map(|_| ());
367 }
368
369 pub async fn construct_and_send_extrinsic(
371 &self,
372 function: impl Into<<Runtime as frame_system::Config>::RuntimeCall>,
373 ) -> Result<RpcTransactionOutput, RpcTransactionError> {
374 self.construct_and_send_extrinsic_with(self.account_nonce(), 0.into(), function)
375 .await
376 }
377
378 pub async fn construct_and_send_extrinsic_with(
380 &self,
381 nonce: u32,
382 tip: BalanceOf<Runtime>,
383 function: impl Into<<Runtime as frame_system::Config>::RuntimeCall>,
384 ) -> Result<RpcTransactionOutput, RpcTransactionError> {
385 let extrinsic = construct_extrinsic_generic::<Runtime, _>(
386 &self.client,
387 function,
388 self.key,
389 false,
390 nonce,
391 tip,
392 );
393 self.rpc_handlers.send_transaction(extrinsic.into()).await
394 }
395
396 pub fn construct_extrinsic(
398 &self,
399 nonce: u32,
400 function: impl Into<<Runtime as frame_system::Config>::RuntimeCall>,
401 ) -> UncheckedExtrinsicFor<Runtime> {
402 construct_extrinsic_generic::<Runtime, _>(
403 &self.client,
404 function,
405 self.key,
406 false,
407 nonce,
408 0.into(),
409 )
410 }
411
412 pub fn construct_extrinsic_with_tip(
414 &self,
415 nonce: u32,
416 tip: BalanceOf<Runtime>,
417 function: impl Into<<Runtime as frame_system::Config>::RuntimeCall>,
418 ) -> UncheckedExtrinsicFor<Runtime> {
419 construct_extrinsic_generic::<Runtime, _>(
420 &self.client,
421 function,
422 self.key,
423 false,
424 nonce,
425 tip,
426 )
427 }
428
429 pub async fn send_extrinsic(
431 &self,
432 extrinsic: impl Into<OpaqueExtrinsic>,
433 ) -> Result<RpcTransactionOutput, RpcTransactionError> {
434 self.rpc_handlers.send_transaction(extrinsic.into()).await
435 }
436
437 pub fn free_balance(&self, account_id: <Runtime as DomainRuntime>::AccountId) -> Balance {
439 self.client
440 .runtime_api()
441 .free_balance(self.client.info().best_hash, account_id)
442 .expect("Fail to get account free balance")
443 }
444
445 pub fn get_open_channel_for_chain(&self, chain_id: ChainId) -> Option<ChannelId> {
447 self.client
448 .runtime_api()
449 .get_open_channel_for_chain(self.client.info().best_hash, chain_id)
450 .expect("Fail to get open channel for Chain")
451 }
452
453 pub fn construct_unsigned_extrinsic(
455 &self,
456 function: impl Into<<Runtime as frame_system::Config>::RuntimeCall>,
457 ) -> UncheckedExtrinsicFor<Runtime>
458 where
459 Runtime:
460 frame_system::Config<Hash = H256> + pallet_transaction_payment::Config + Send + Sync,
461 RuntimeCallFor<Runtime>:
462 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + Send + Sync,
463 BalanceOf<Runtime>: Send + Sync + From<u64> + sp_runtime::FixedPointOperand,
464 {
465 let function = function.into();
466 UncheckedExtrinsicFor::<Runtime>::new_bare(function)
467 }
468
469 pub async fn construct_and_send_unsigned_extrinsic(
471 &self,
472 function: impl Into<<Runtime as frame_system::Config>::RuntimeCall>,
473 ) -> Result<RpcTransactionOutput, RpcTransactionError> {
474 let extrinsic = self.construct_unsigned_extrinsic(function);
475 self.rpc_handlers.send_transaction(extrinsic.into()).await
476 }
477
478 pub fn ban_peer(&self, addr: MultiaddrWithPeerId) {
481 self.network_service.report_peer(
484 addr.peer_id,
485 ReputationChange::new_fatal("Peer banned by test (1)"),
486 );
487 self.network_service.report_peer(
488 addr.peer_id,
489 ReputationChange::new_fatal("Peer banned by test (2)"),
490 );
491 }
492
493 pub fn unban_peer(&self, addr: MultiaddrWithPeerId) {
495 self.network_service.report_peer(
498 addr.peer_id,
499 ReputationChange::new(i32::MAX, "Peer unbanned by test (1)"),
500 );
501 self.network_service.report_peer(
502 addr.peer_id,
503 ReputationChange::new(i32::MAX, "Peer unbanned by test (2)"),
504 );
505 }
506
507 pub async fn stop(self) -> Result<(), std::io::Error> {
513 let lock_file_path = self.base_path.path().join("paritydb").join("lock");
514 std::mem::drop(self);
516
517 sleep(Duration::from_secs(2)).await;
520
521 if let Err(err) = std::fs::remove_file(lock_file_path) {
523 tracing::error!("deleting paritydb lock file failed: {err:?}");
524 }
525 Ok(())
526 }
527
528 pub async fn clear_tx_pool(&self) {
530 let tx_hashes: Vec<_> = self
531 .operator
532 .transaction_pool
533 .ready()
534 .map(|t| self.operator.transaction_pool.hash_of(&t.data))
535 .collect();
536
537 let hash_and_number = HashAndNumber {
538 number: self.client.info().best_number,
539 hash: self.client.info().best_hash,
540 };
541 self.operator
542 .transaction_pool
543 .pool()
544 .prune_known(&hash_and_number, &tx_hashes);
545
546 tokio::time::sleep(std::time::Duration::from_millis(1)).await;
549 self.operator
550 .transaction_pool
551 .pool()
552 .validated_pool()
553 .clear_stale(&hash_and_number);
554 }
555}
556
557impl<Runtime, RuntimeApi> DomainNode<Runtime, RuntimeApi>
558where
559 Runtime: frame_system::Config<Hash = H256>
560 + pallet_transaction_payment::Config
561 + DomainRuntime
562 + Send
563 + Sync,
564 RuntimeApi: ConstructRuntimeApi<Block, Client<RuntimeApi>> + Send + Sync + 'static,
565 RuntimeApi::RuntimeApi: Metadata<Block>
566 + BlockBuilder<Block>
567 + OffchainWorkerApi<Block>
568 + SessionKeys<Block>
569 + DomainCoreApi<Block>
570 + TaggedTransactionQueue<Block>
571 + AccountNonceApi<Block, <Runtime as DomainRuntime>::AccountId, Nonce>
572 + TransactionPaymentRuntimeApi<Block, Balance>
573 + MessengerApi<Block, NumberFor<CBlock>, BlockHashFor<CBlock>>
574 + RelayerApi<Block, NumberFor<Block>, NumberFor<CBlock>, BlockHashFor<CBlock>>
575 + EvmOnchainStateApi<Block>,
576{
577 pub fn evm_contract_creation_allowed_by(
580 &self,
581 ) -> PermissionedActionAllowedBy<EthereumAccountId> {
582 self.client
583 .runtime_api()
584 .evm_contract_creation_allowed_by(self.client.info().best_hash)
585 .expect("Failed to get EVM contact creation allow list")
586 .expect("Should be an EVM domain")
587 }
588}
589
590pub struct DomainNodeBuilder {
592 tokio_handle: tokio::runtime::Handle,
593 domain_nodes: Vec<MultiaddrWithPeerId>,
594 domain_nodes_exclusive: bool,
595 skip_empty_bundle_production: bool,
596 base_path: BasePath,
597 maybe_operator_id: Option<OperatorId>,
598 rpc_addr: Option<SocketAddr>,
599 rpc_port: Option<u16>,
600}
601
602impl DomainNodeBuilder {
603 pub fn new(tokio_handle: tokio::runtime::Handle, base_path: BasePath) -> Self {
608 DomainNodeBuilder {
609 tokio_handle,
610 domain_nodes: Vec::new(),
611 domain_nodes_exclusive: false,
612 skip_empty_bundle_production: false,
613 base_path,
614 maybe_operator_id: None,
615 rpc_addr: None,
616 rpc_port: None,
617 }
618 }
619
620 pub fn exclusively_connect_to_registered_parachain_nodes(mut self) -> Self {
624 self.domain_nodes_exclusive = true;
625 self
626 }
627
628 pub fn connect_to_domain_node(mut self, addr: MultiaddrWithPeerId) -> Self {
633 self.domain_nodes.push(addr);
634 self
635 }
636
637 pub fn skip_empty_bundle(mut self) -> Self {
639 self.skip_empty_bundle_production = true;
640 self
641 }
642
643 pub fn operator_id(mut self, operator_id: OperatorId) -> Self {
645 self.maybe_operator_id = Some(operator_id);
646 self
647 }
648
649 pub fn rpc_addr(mut self, addr: SocketAddr) -> Self {
651 self.rpc_addr = Some(addr);
652 self
653 }
654
655 pub fn rpc_port(mut self, port: u16) -> Self {
657 self.rpc_port = Some(port);
658 self
659 }
660
661 fn evm_eth_provider(
662 base_path: &std::path::Path,
663 ) -> EthProvider<
664 evm_domain_test_runtime::TransactionConverter,
665 DefaultEthConfig<
666 FullClient<Block, evm_domain_test_runtime::RuntimeApi>,
667 FullBackend<Block>,
668 >,
669 > {
670 EthProvider::with_configuration(
671 Some(base_path),
672 EthConfiguration {
673 max_past_logs: 10000,
674 fee_history_limit: 2048,
675 enable_dev_signer: true,
676 target_gas_price: 1,
677 execute_gas_limit_multiplier: 10,
678 eth_log_block_cache: 50,
679 eth_statuses_cache: 50,
680 },
681 )
682 }
683
684 pub async fn build_evm_node(
686 self,
687 role: Role,
688 key: EcdsaKeyring,
689 mock_consensus_node: &mut MockConsensusNode,
690 ) -> EvmDomainNode {
691 let domain_base_path = self
692 .base_path
693 .path()
694 .join(format!("domain-{EVM_DOMAIN_ID}"));
695 let eth_provider = Self::evm_eth_provider(&domain_base_path);
696
697 DomainNode::build(
698 EVM_DOMAIN_ID,
699 self.tokio_handle,
700 key,
701 BasePath::new(domain_base_path),
702 self.domain_nodes,
703 self.domain_nodes_exclusive,
704 self.skip_empty_bundle_production,
705 self.maybe_operator_id,
706 role,
707 mock_consensus_node,
708 self.rpc_addr,
709 self.rpc_port,
710 eth_provider,
711 )
712 .await
713 }
714
715 pub async fn build_auto_id_node(
717 self,
718 role: Role,
719 key: Sr25519Keyring,
720 mock_consensus_node: &mut MockConsensusNode,
721 ) -> AutoIdDomainNode {
722 DomainNode::build(
723 AUTO_ID_DOMAIN_ID,
724 self.tokio_handle,
725 key,
726 BasePath::new(
727 self.base_path
728 .path()
729 .join(format!("domain-{AUTO_ID_DOMAIN_ID}")),
730 ),
731 self.domain_nodes,
732 self.domain_nodes_exclusive,
733 self.skip_empty_bundle_production,
734 self.maybe_operator_id,
735 role,
736 mock_consensus_node,
737 self.rpc_addr,
738 self.rpc_port,
739 DefaultProvider,
740 )
741 .await
742 }
743
744 pub async fn build_evm_node_with(
746 self,
747 role: Role,
748 key: EcdsaKeyring,
749 mock_consensus_node: &mut MockConsensusNode,
750 domain_id: DomainId,
751 ) -> EvmDomainNode {
752 let eth_provider = Self::evm_eth_provider(self.base_path.path());
753
754 DomainNode::build(
755 domain_id,
756 self.tokio_handle,
757 key,
758 self.base_path,
759 self.domain_nodes,
760 self.domain_nodes_exclusive,
761 self.skip_empty_bundle_production,
762 self.maybe_operator_id,
763 role,
764 mock_consensus_node,
765 self.rpc_addr,
766 self.rpc_port,
767 eth_provider,
768 )
769 .await
770 }
771}
772
773pub type EvmDomainNode =
775 DomainNode<evm_domain_test_runtime::Runtime, evm_domain_test_runtime::RuntimeApi>;
776
777pub type EvmDomainClient = Client<evm_domain_test_runtime::RuntimeApi>;
779
780pub type AutoIdDomainNode =
782 DomainNode<auto_id_domain_test_runtime::Runtime, auto_id_domain_test_runtime::RuntimeApi>;
783
784pub type AutoIdDomainClient = Client<auto_id_domain_test_runtime::RuntimeApi>;