-
Notifications
You must be signed in to change notification settings - Fork 326
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CCV chain bootstrap to CI with Neutron and Gaia (#3451)
- Loading branch information
Showing
18 changed files
with
761 additions
and
4 deletions.
There are no files selected for viewing
6 changes: 6 additions & 0 deletions
6
.changelog/unreleased/features/ibc-integration-test/3450-bootstrap-ics-tests.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
- Add a new trait `InterchainSecurityChainTest` and two functions | ||
`run_binary_interchain_security_node_test` and `run_binary_interchain_security_channel_test` | ||
which can be used to bootstrap a Provider and Consumer chain for integration tests. | ||
Add a CI job to run tests with Gaia as a provider chain and Neutron as a Consumer chain. | ||
([\#3450](https://github.com/informalsystems/hermes/issues/3450)) | ||
([\#3387](https://github.com/informalsystems/hermes/issues/3387)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,7 @@ | |
stride | ||
stride-no-admin | ||
migaloo | ||
neutron | ||
; | ||
|
||
python = nixpkgs.python3.withPackages (p: [ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
150 changes: 150 additions & 0 deletions
150
tools/integration-test/src/tests/interchain_security.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
//! The following tests are for the Interchain Security. | ||
//! These tests require the first chain to be a Producer chain and | ||
//! the second chain a Consumer chain. | ||
use ibc_test_framework::chain::config::set_voting_period; | ||
use ibc_test_framework::framework::binary::channel::run_binary_interchain_security_channel_test; | ||
use ibc_test_framework::prelude::*; | ||
use ibc_test_framework::util::random::random_u128_range; | ||
|
||
#[test] | ||
fn test_ics_transfer() -> Result<(), Error> { | ||
run_binary_interchain_security_channel_test(&InterchainSecurityTest) | ||
} | ||
|
||
struct InterchainSecurityTest; | ||
|
||
impl TestOverrides for InterchainSecurityTest { | ||
fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error> { | ||
// Consumer chain doesn't have a gov key. | ||
if genesis | ||
.get_mut("app_state") | ||
.and_then(|app_state| app_state.get("gov")) | ||
.is_some() | ||
{ | ||
set_voting_period(genesis, "10s")?; | ||
} | ||
Ok(()) | ||
} | ||
|
||
// The `ccv_consumer_chain` must be `true` for the Consumer chain. | ||
// The `trusting_period` must be strictly smaller than the `unbonding_period` | ||
// specified in the Consumer chain proposal. The test framework uses 100s in | ||
// the proposal. | ||
fn modify_relayer_config(&self, config: &mut Config) { | ||
for chain_config in config.chains.iter_mut() { | ||
if chain_config.id == ChainId::from_string("ibcconsumer") { | ||
chain_config.ccv_consumer_chain = true; | ||
chain_config.trusting_period = Some(Duration::from_secs(99)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl BinaryChannelTest for InterchainSecurityTest { | ||
fn run<ChainA: ChainHandle, ChainB: ChainHandle>( | ||
&self, | ||
_config: &TestConfig, | ||
_relayer: RelayerDriver, | ||
chains: ConnectedChains<ChainA, ChainB>, | ||
channel: ConnectedChannel<ChainA, ChainB>, | ||
) -> Result<(), Error> { | ||
let denom_a = chains.node_a.denom(); | ||
|
||
let wallet_a = chains.node_a.wallets().user1().cloned(); | ||
let wallet_b = chains.node_b.wallets().user1().cloned(); | ||
let wallet_c = chains.node_a.wallets().user2().cloned(); | ||
|
||
let balance_a = chains | ||
.node_a | ||
.chain_driver() | ||
.query_balance(&wallet_a.address(), &denom_a)?; | ||
|
||
let a_to_b_amount = random_u128_range(1000, 5000); | ||
|
||
info!( | ||
"Sending IBC transfer from chain {} to chain {} with: channel id {}, port id {} and amount of {} {}", | ||
chains.chain_id_a(), | ||
chains.chain_id_b(), | ||
channel.channel_id_a.to_string(), | ||
channel.port_a.to_string(), | ||
a_to_b_amount, | ||
denom_a | ||
); | ||
|
||
chains.node_a.chain_driver().ibc_transfer_token( | ||
&channel.port_a.as_ref(), | ||
&channel.channel_id_a.as_ref(), | ||
&wallet_a.as_ref(), | ||
&wallet_b.address(), | ||
&denom_a.with_amount(a_to_b_amount).as_ref(), | ||
)?; | ||
|
||
let denom_b = derive_ibc_denom( | ||
&channel.port_b.as_ref(), | ||
&channel.channel_id_b.as_ref(), | ||
&denom_a, | ||
)?; | ||
|
||
info!( | ||
"Waiting for user on chain B to receive IBC transferred amount of {}", | ||
a_to_b_amount | ||
); | ||
|
||
chains.node_a.chain_driver().assert_eventual_wallet_amount( | ||
&wallet_a.address(), | ||
&(balance_a - a_to_b_amount).as_ref(), | ||
)?; | ||
|
||
chains.node_b.chain_driver().assert_eventual_wallet_amount( | ||
&wallet_b.address(), | ||
&denom_b.with_amount(a_to_b_amount).as_ref(), | ||
)?; | ||
|
||
info!( | ||
"successfully performed IBC transfer from chain {} to chain {}", | ||
chains.chain_id_a(), | ||
chains.chain_id_b(), | ||
); | ||
|
||
let balance_c = chains | ||
.node_a | ||
.chain_driver() | ||
.query_balance(&wallet_c.address(), &denom_a)?; | ||
|
||
let b_to_a_amount = random_u128_range(500, a_to_b_amount); | ||
|
||
info!( | ||
"Sending IBC transfer from chain {} to chain {} with: channel id {}, port id {} and amount of {}", | ||
chains.chain_id_b(), | ||
chains.chain_id_a(), | ||
channel.channel_id_b.to_string(), | ||
channel.port_b.to_string(), | ||
b_to_a_amount, | ||
); | ||
|
||
chains.node_b.chain_driver().ibc_transfer_token( | ||
&channel.port_b.as_ref(), | ||
&channel.channel_id_b.as_ref(), | ||
&wallet_b.as_ref(), | ||
&wallet_c.address(), | ||
&denom_b.with_amount(b_to_a_amount).as_ref(), | ||
)?; | ||
|
||
chains.node_b.chain_driver().assert_eventual_wallet_amount( | ||
&wallet_b.address(), | ||
&denom_b.with_amount(a_to_b_amount - b_to_a_amount).as_ref(), | ||
)?; | ||
|
||
chains.node_a.chain_driver().assert_eventual_wallet_amount( | ||
&wallet_c.address(), | ||
&(balance_c + b_to_a_amount).as_ref(), | ||
)?; | ||
|
||
info!( | ||
"successfully performed reverse IBC transfer from chain {} back to chain {}", | ||
chains.chain_id_b(), | ||
chains.chain_id_a(), | ||
); | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/*! | ||
Helper functions for bootstrapping a consumer full node. | ||
*/ | ||
use eyre::eyre; | ||
use std::sync::{Arc, RwLock}; | ||
use std::thread; | ||
use std::time::Duration; | ||
use toml; | ||
use tracing::info; | ||
|
||
use crate::chain::builder::ChainBuilder; | ||
use crate::chain::config; | ||
use crate::chain::ext::bootstrap::ChainBootstrapMethodsExt; | ||
use crate::error::Error; | ||
use crate::prelude::{ChainDriver, Denom, FullNode, TestWallets, Token}; | ||
use crate::util::random::random_u128_range; | ||
|
||
pub fn bootstrap_consumer_node( | ||
builder: &ChainBuilder, | ||
prefix: &str, | ||
node_a: &FullNode, | ||
config_modifier: impl FnOnce(&mut toml::Value) -> Result<(), Error>, | ||
genesis_modifier: impl FnOnce(&mut serde_json::Value) -> Result<(), Error>, | ||
chain_number: usize, | ||
provider_chain_driver: &ChainDriver, | ||
) -> Result<FullNode, Error> { | ||
let stake_denom = Denom::base("stake"); | ||
|
||
let denom = Denom::base("samoleans"); | ||
|
||
let initial_amount = random_u128_range(1_000_000_000_000_000_000, 2_000_000_000_000_000_000); | ||
|
||
let initial_stake = Token::new(stake_denom, initial_amount); | ||
let additional_initial_stake = initial_stake | ||
.clone() | ||
.checked_add(1_000_000_000_000u64) | ||
.ok_or(Error::generic(eyre!( | ||
"error creating initial stake with additional amount" | ||
)))?; | ||
|
||
let initial_coin = Token::new(denom.clone(), initial_amount); | ||
let chain_driver = builder.new_chain(prefix, false, chain_number)?; | ||
|
||
chain_driver.initialize()?; | ||
|
||
let validator = chain_driver.add_wallet("validator")?; | ||
let relayer = chain_driver.add_wallet("relayer")?; | ||
let user1 = chain_driver.add_wallet("user1")?; | ||
let user2 = chain_driver.add_wallet("user2")?; | ||
|
||
chain_driver.add_genesis_account(&validator.address, &[&additional_initial_stake])?; | ||
chain_driver.add_genesis_account(&relayer.address, &[&initial_stake, &initial_coin])?; | ||
chain_driver.add_genesis_account(&user1.address, &[&initial_stake, &initial_coin])?; | ||
chain_driver.add_genesis_account(&user2.address, &[&initial_stake, &initial_coin])?; | ||
|
||
// Wait for the consumer chain to be initialized before querying the genesis | ||
thread::sleep(Duration::from_secs(10)); | ||
|
||
node_a | ||
.chain_driver | ||
.query_consumer_genesis(&chain_driver, chain_driver.chain_id.as_str())?; | ||
|
||
chain_driver.replace_genesis_state()?; | ||
|
||
chain_driver.update_genesis_file("genesis.json", genesis_modifier)?; | ||
// The configuration `soft_opt_out_threshold` might be missing and is required | ||
// for chains such as Neutron | ||
chain_driver.update_genesis_file("genesis.json", |genesis| { | ||
config::set_soft_opt_out_threshold(genesis, "0.05")?; | ||
Ok(()) | ||
})?; | ||
|
||
let log_level = std::env::var("CHAIN_LOG_LEVEL").unwrap_or_else(|_| "info".to_string()); | ||
|
||
chain_driver.update_chain_config("config.toml", |config| { | ||
config::set_log_level(config, &log_level)?; | ||
config::set_rpc_port(config, chain_driver.rpc_port)?; | ||
config::set_p2p_port(config, chain_driver.p2p_port)?; | ||
config::set_pprof_port(config, chain_driver.pprof_port)?; | ||
config::set_timeout_commit(config, Duration::from_secs(1))?; | ||
config::set_timeout_propose(config, Duration::from_secs(1))?; | ||
config::set_mode(config, "validator")?; | ||
|
||
config_modifier(config)?; | ||
|
||
Ok(()) | ||
})?; | ||
|
||
chain_driver.update_chain_config("app.toml", |config| { | ||
config::set_grpc_port(config, chain_driver.grpc_port)?; | ||
config::disable_grpc_web(config)?; | ||
config::disable_api(config)?; | ||
config::set_minimum_gas_price(config, "0stake")?; | ||
|
||
Ok(()) | ||
})?; | ||
|
||
chain_driver.copy_validator_key_pair(provider_chain_driver)?; | ||
|
||
let process = chain_driver.start()?; | ||
|
||
info!( | ||
"started new chain {} at with home path {} and RPC address {}.", | ||
chain_driver.chain_id, | ||
chain_driver.home_path, | ||
chain_driver.rpc_address(), | ||
); | ||
|
||
info!( | ||
"user wallet for chain {} - id: {}, address: {}", | ||
chain_driver.chain_id, user1.id.0, user1.address.0, | ||
); | ||
|
||
info!( | ||
"you can manually interact with the chain using commands starting with:\n{} --home '{}' --node {}", | ||
chain_driver.command_path, | ||
chain_driver.home_path, | ||
chain_driver.rpc_address(), | ||
); | ||
|
||
let wallets = TestWallets { | ||
validator, | ||
relayer, | ||
user1, | ||
user2, | ||
}; | ||
|
||
let node = FullNode { | ||
chain_driver, | ||
denom, | ||
wallets, | ||
process: Arc::new(RwLock::new(process)), | ||
}; | ||
|
||
Ok(node) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
*/ | ||
|
||
pub mod binary; | ||
pub mod consumer; | ||
pub mod init; | ||
pub mod nary; | ||
pub mod single; |
Oops, something went wrong.