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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*!
   Functions for bootstrapping N-ary number of chains.
*/

use core::convert::TryInto;
use ibc_relayer::chain::handle::ChainHandle;
use ibc_relayer::config::Config;
use ibc_relayer::foreign_client::ForeignClient;
use ibc_relayer::registry::SharedRegistry;

use crate::bootstrap::binary::chain::{
    add_chain_config, add_keys_to_chain_handle, bootstrap_foreign_client, new_registry,
    save_relayer_config,
};
use crate::error::{handle_generic_error, Error};
use crate::relayer::driver::RelayerDriver;
use crate::types::config::TestConfig;
use crate::types::nary::chains::{DynamicConnectedChains, NaryConnectedChains};
use crate::types::single::node::FullNode;

/**
  Bootstrap a fixed number of chains specified by `SIZE`.
*/
pub fn boostrap_chains_with_nodes<const SIZE: usize>(
    test_config: &TestConfig,
    full_nodes: [FullNode; SIZE],
    config_modifier: impl FnOnce(&mut Config),
) -> Result<(RelayerDriver, NaryConnectedChains<impl ChainHandle, SIZE>), Error> {
    let (relayer, chains) =
        boostrap_chains_with_any_nodes(test_config, full_nodes.into(), config_modifier)?;

    Ok((relayer, chains.try_into()?))
}

/**
   Bootstrap a fixed number of chains that are actually
   backed by the same underlying full node.
*/
pub fn boostrap_chains_with_self_connected_node<const SIZE: usize>(
    test_config: &TestConfig,
    full_node: FullNode,
    config_modifier: impl FnOnce(&mut Config),
) -> Result<(RelayerDriver, NaryConnectedChains<impl ChainHandle, SIZE>), Error> {
    let full_nodes = vec![full_node; SIZE];
    let (relayer, chains) =
        boostrap_chains_with_any_nodes(test_config, full_nodes, config_modifier)?;

    Ok((relayer, chains.try_into()?))
}

/**
   Bootstrap a dynamic number of chains, according to the number of full nodes
   in the `Vec<FullNode>`.
*/
pub fn boostrap_chains_with_any_nodes(
    test_config: &TestConfig,
    full_nodes: Vec<FullNode>,
    config_modifier: impl FnOnce(&mut Config),
) -> Result<(RelayerDriver, DynamicConnectedChains<impl ChainHandle>), Error> {
    let mut config = Config::default();

    for node in full_nodes.iter() {
        add_chain_config(&mut config, node, test_config)?;
    }

    config_modifier(&mut config);

    let config_path = test_config.chain_store_dir.join("relayer-config.toml");

    save_relayer_config(&config, &config_path)?;

    let registry = new_registry(config.clone());

    let mut chain_handles = Vec::new();

    for node in full_nodes.iter() {
        let handle = spawn_chain_handle(&registry, node)?;
        chain_handles.push(handle);
    }

    let mut foreign_clients: Vec<Vec<ForeignClient<_, _>>> = Vec::new();

    for handle_a in chain_handles.iter() {
        let mut foreign_clients_b = Vec::new();

        for handle_b in chain_handles.iter() {
            let foreign_client = bootstrap_foreign_client(handle_a, handle_b, Default::default())?;

            foreign_clients_b.push(foreign_client);
        }

        foreign_clients.push(foreign_clients_b);
    }

    let relayer = RelayerDriver {
        config_path,
        config,
        registry,
        hang_on_fail: test_config.hang_on_fail,
    };

    let connected_chains = DynamicConnectedChains::new(chain_handles, full_nodes, foreign_clients);

    Ok((relayer, connected_chains))
}

fn spawn_chain_handle<Handle: ChainHandle>(
    registry: &SharedRegistry<Handle>,
    node: &FullNode,
) -> Result<Handle, Error> {
    let chain_id = &node.chain_driver.chain_id;
    let handle = registry
        .get_or_spawn(chain_id)
        .map_err(handle_generic_error)?;

    add_keys_to_chain_handle(&handle, &node.wallets)?;

    Ok(handle)
}