Skip to content

Commit

Permalink
WIP need mock broadcaster
Browse files Browse the repository at this point in the history
  • Loading branch information
kylezs committed Sep 20, 2023
1 parent ba14964 commit 1b5204e
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 101 deletions.
6 changes: 5 additions & 1 deletion state-chain/pallets/cf-ingress-egress/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,10 +398,12 @@ pub mod pallet {
#[pallet::hooks]
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {
/// Recycle addresses if we can
fn on_idle(_n: BlockNumberFor<T>, remaining_weight: Weight) -> Weight {
fn on_idle(n: BlockNumberFor<T>, remaining_weight: Weight) -> Weight {
let current_target_chain_height = T::ChainTracking::get_block_height();

println!("Calling on idle at block: {:?}", n);
DepositChannelLookup::<T, I>::iter().for_each(|(_, details)| {
println!("Checking channel");
// We add an extra lifetime of safety.
// The CFEs will stop witnessing the address of this deposit channel at the
// expires_at block number. However, because the CFE uses a safety margin, and here
Expand All @@ -412,6 +414,7 @@ pub mod pallet {
if details.expires_at + DepositChannelLifetime::<T, I>::get() <=
current_target_chain_height
{
println!("Recycling channel at block {:?}: {:?}", n, details.deposit_channel);
Self::recycle_channel(details.deposit_channel);
}
});
Expand Down Expand Up @@ -867,6 +870,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {

fn recycle_channel(channel: DepositChannel<T::TargetChain>) {
if let Some(state) = channel.state.maybe_recycle() {
println!("Yep, recycle it?");
DepositChannelPool::<T, I>::insert(
channel.channel_id,
DepositChannel { state, ..channel },
Expand Down
11 changes: 10 additions & 1 deletion state-chain/pallets/cf-ingress-egress/src/mock.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::marker::PhantomData;

pub use crate::{self as pallet_cf_ingress_egress};
use crate::{DepositBalances, DepositWitness};

Expand Down Expand Up @@ -73,10 +75,17 @@ impl DepositHandler<Ethereum> for MockDepositHandler {}
pub type MockEgressBroadcaster =
MockBroadcaster<(MockEthereumApiCall<MockEthEnvironment>, RuntimeCall)>;

pub struct BlockNumberProvider;
pub struct BlockNumberProvider<T>(PhantomData<T>);

// Unify with BlockHeightProvider in vaults mocks. Can move it to the central mocks directory.
impl<T> MockPallet for MockBroadcaster<T> {
const PREFIX: &'static [u8] = b"MockBroadcaster";
}

pub const OPEN_INGRESS_AT: u64 = 420;

// We need to be able to set blocks here, if we never progress past 420, we can never expire
// anything. See MockBroadcaster
impl GetBlockHeight<Ethereum> for BlockNumberProvider {
fn get_block_height() -> u64 {
OPEN_INGRESS_AT
Expand Down
206 changes: 108 additions & 98 deletions state-chain/pallets/cf-ingress-egress/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::{
mock::*, Call as PalletCall, ChannelAction, ChannelIdCounter, CrossChainMessage,
DepositChannelLookup, DepositChannelPool, DepositWitness, DisabledEgressAssets,
Event as PalletEvent, FailedVaultTransfers, FetchOrTransfer, MinimumDeposit, Pallet,
ScheduledEgressCcm, ScheduledEgressFetchOrTransfer, TargetChainAccount, VaultTransfer,
DepositChannelLifetime, DepositChannelLookup, DepositChannelPool, DepositWitness,
DisabledEgressAssets, Event as PalletEvent, FailedVaultTransfers, FetchOrTransfer,
MinimumDeposit, Pallet, ScheduledEgressCcm, ScheduledEgressFetchOrTransfer, TargetChainAccount,
VaultTransfer,
};
use cf_chains::{
address::AddressConverter, evm::EvmFetchId, CcmChannelMetadata, DepositChannel,
Expand All @@ -21,6 +22,7 @@ use cf_traits::{
use frame_support::{
assert_ok,
traits::{Hooks, OriginTrait},
weights::Weight,
};
use sp_core::H160;

Expand Down Expand Up @@ -311,6 +313,9 @@ fn all_batch_apicall_creation_failure_should_rollback_storage() {
#[test]
fn addresses_are_getting_reused() {
new_test_ext()
.execute_with(|| {
DepositChannelLifetime::<Test, _>::set(4);
})
// Request 2 deposit addresses and deposit to one of them.
.request_address_and_deposit(&[
(
Expand Down Expand Up @@ -338,10 +343,15 @@ fn addresses_are_getting_reused() {
}
channels
})
// Expire the addresses and check that they are now available for reuse.
.then_execute_at_next_block(|channels| {
for (_request, _id, address) in &channels {
IngressEgress::recycle_channel(*address);
}
let current_block = BlockNumberProvider::get_block_height();
let expired_at = current_block + 2 * DepositChannelLifetime::<Test, _>::get();

println!("Current block: {:?}", current_block);
println!("Expired at: {:?}", expired_at);
IngressEgress::on_idle(expired_at, Weight::MAX);

channels[0].clone()
})
// Check that the used address is now deployed and in the pool of available addresses.
Expand All @@ -361,47 +371,47 @@ fn addresses_are_getting_reused() {
});
}

#[test]
fn proof_address_pool_integrity() {
new_test_ext().execute_with(|| {
let channel_details = (0..3)
.map(|id| request_address_and_deposit(id, eth::Asset::Eth))
.collect::<Vec<_>>();
// All addresses in use
expect_size_of_address_pool(0);
IngressEgress::on_finalize(1);
for (_id, address) in channel_details {
assert_ok!(IngressEgress::finalise_ingress(RuntimeOrigin::root(), vec![address]));
IngressEgress::recycle_channel(address);
}
// Expect all addresses to be available
expect_size_of_address_pool(3);
request_address_and_deposit(4u64, eth::Asset::Eth);
// Expect one address to be in use
expect_size_of_address_pool(2);
});
}
// #[test]
// fn proof_address_pool_integrity() {
// new_test_ext().execute_with(|| {
// let channel_details = (0..3)
// .map(|id| request_address_and_deposit(id, eth::Asset::Eth))
// .collect::<Vec<_>>();
// // All addresses in use
// expect_size_of_address_pool(0);
// IngressEgress::on_finalize(1);
// for (_id, address) in channel_details {
// assert_ok!(IngressEgress::finalise_ingress(RuntimeOrigin::root(), vec![address]));
// IngressEgress::recycle_channel(address);
// }
// // Expect all addresses to be available
// expect_size_of_address_pool(3);
// request_address_and_deposit(4u64, eth::Asset::Eth);
// // Expect one address to be in use
// expect_size_of_address_pool(2);
// });
// }

#[test]
fn create_new_address_while_pool_is_empty() {
new_test_ext().execute_with(|| {
let channel_details = (0..2)
.map(|id| request_address_and_deposit(id, eth::Asset::Eth))
.collect::<Vec<_>>();
IngressEgress::on_finalize(1);
for (_id, address) in channel_details {
assert_ok!(IngressEgress::finalise_ingress(RuntimeOrigin::root(), vec![address]));
IngressEgress::recycle_channel(address);
}
IngressEgress::on_initialize(EXPIRY_BLOCK);
assert_eq!(ChannelIdCounter::<Test>::get(), 2);
request_address_and_deposit(3u64, eth::Asset::Eth);
assert_eq!(ChannelIdCounter::<Test>::get(), 2);
IngressEgress::on_finalize(1);
IngressEgress::on_initialize(EXPIRY_BLOCK);
assert_eq!(ChannelIdCounter::<Test>::get(), 2);
});
}
// #[test]
// fn create_new_address_while_pool_is_empty() {
// new_test_ext().execute_with(|| {
// let channel_details = (0..2)
// .map(|id| request_address_and_deposit(id, eth::Asset::Eth))
// .collect::<Vec<_>>();
// IngressEgress::on_finalize(1);
// for (_id, address) in channel_details {
// assert_ok!(IngressEgress::finalise_ingress(RuntimeOrigin::root(), vec![address]));
// IngressEgress::recycle_channel(address);
// }
// IngressEgress::on_initialize(EXPIRY_BLOCK);
// assert_eq!(ChannelIdCounter::<Test>::get(), 2);
// request_address_and_deposit(3u64, eth::Asset::Eth);
// assert_eq!(ChannelIdCounter::<Test>::get(), 2);
// IngressEgress::on_finalize(1);
// IngressEgress::on_initialize(EXPIRY_BLOCK);
// assert_eq!(ChannelIdCounter::<Test>::get(), 2);
// });
// }

#[test]
fn reused_address_channel_id_matches() {
Expand Down Expand Up @@ -834,58 +844,58 @@ fn handle_pending_deployment_same_block() {
});
}

#[test]
fn channel_reuse_with_different_assets() {
const ASSET_1: eth::Asset = eth::Asset::Eth;
const ASSET_2: eth::Asset = eth::Asset::Flip;
new_test_ext()
// First, request a deposit address and use it, then close it so it gets recycled.
.request_address_and_deposit(&[(
DepositRequest::Liquidity { lp_account: ALICE, asset: ASSET_1 },
100_000,
)])
.map_context(|mut result| result.pop().unwrap())
.then_execute_at_next_block(|ctx| {
// Dispatch callbacks to finalise the ingress.
MockEgressBroadcaster::dispatch_all_callbacks();
ctx
})
.inspect_storage(|(request, _, address)| {
let asset = request.source_asset();
assert_eq!(asset, ASSET_1);
assert!(
DepositChannelLookup::<Test, _>::get(address).unwrap().deposit_channel.asset ==
asset
);
})
// move forward expired blocks
.then_execute_at_next_block(|(details, channel_id, channel_address)| {
IngressEgress::recycle_channel(channel_address);
channel_id
})
.inspect_storage(|channel_id| {
assert!(DepositChannelLookup::<Test, _>::get(ALICE_ETH_ADDRESS).is_none());
assert!(
DepositChannelPool::<Test, _>::iter_values().next().unwrap().channel_id ==
*channel_id
);
})
// Request a new address with a different asset.
.request_deposit_addresses(&[DepositRequest::Liquidity {
lp_account: ALICE,
asset: ASSET_2,
}])
.map_context(|mut result| result.pop().unwrap())
// Ensure that the deposit channel's asset is updated.
.inspect_storage(|(request, _, address)| {
let asset = request.source_asset();
assert_eq!(asset, ASSET_2);
assert!(
DepositChannelLookup::<Test, _>::get(address).unwrap().deposit_channel.asset ==
asset
);
});
}
// #[test]
// fn channel_reuse_with_different_assets() {
// const ASSET_1: eth::Asset = eth::Asset::Eth;
// const ASSET_2: eth::Asset = eth::Asset::Flip;
// new_test_ext()
// // First, request a deposit address and use it, then close it so it gets recycled.
// .request_address_and_deposit(&[(
// DepositRequest::Liquidity { lp_account: ALICE, asset: ASSET_1 },
// 100_000,
// )])
// .map_context(|mut result| result.pop().unwrap())
// .then_execute_at_next_block(|ctx| {
// // Dispatch callbacks to finalise the ingress.
// MockEgressBroadcaster::dispatch_all_callbacks();
// ctx
// })
// .inspect_storage(|(request, _, address)| {
// let asset = request.source_asset();
// assert_eq!(asset, ASSET_1);
// assert!(
// DepositChannelLookup::<Test, _>::get(address).unwrap().deposit_channel.asset ==
// asset
// );
// })
// // move forward expired blocks
// .then_execute_at_next_block(|(details, channel_id, channel_address)| {
// IngressEgress::recycle_channel(channel_address);
// channel_id
// })
// .inspect_storage(|channel_id| {
// assert!(DepositChannelLookup::<Test, _>::get(ALICE_ETH_ADDRESS).is_none());
// assert!(
// DepositChannelPool::<Test, _>::iter_values().next().unwrap().channel_id ==
// *channel_id
// );
// })
// // Request a new address with a different asset.
// .request_deposit_addresses(&[DepositRequest::Liquidity {
// lp_account: ALICE,
// asset: ASSET_2,
// }])
// .map_context(|mut result| result.pop().unwrap())
// // Ensure that the deposit channel's asset is updated.
// .inspect_storage(|(request, _, address)| {
// let asset = request.source_asset();
// assert_eq!(asset, ASSET_2);
// assert!(
// DepositChannelLookup::<Test, _>::get(address).unwrap().deposit_channel.asset ==
// asset
// );
// });
// }

/// This is the sequence we're testing.
/// 1. Request deposit address
Expand Down
1 change: 0 additions & 1 deletion state-chain/pallets/cf-swapping/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ benchmarks! {
SwapType::CcmGas(1)
)]);
}

set_minimum_swap_amount {
let asset = Asset::Eth;
let amount = 1_000;
Expand Down
14 changes: 14 additions & 0 deletions state-chain/test-utilities/src/rich_test_externalities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ impl<Runtime: HasAllPallets> RichExternalities<Runtime> {
});
TestExternalities { ext: self, context }
}

/// Executes the closure as a block, including all the runtime hooks, at
/// `blocks_from_current_block` from the current block number.
#[track_caller]
fn execute_from_current<Ctx>(
mut self,
block_from_current_block: impl Into<BlockNumberFor<Runtime>>,
f: impl FnOnce() -> Ctx,
) -> TestExternalities<Runtime, Ctx> {
let block_from_current_block = block_from_current_block.into();
let block_number = self.0.execute_with(|| frame_system::Pallet::<Runtime>::block_number()) +
block_from_current_block;
self.execute_at_block::<Ctx>(block_number, f)
}
}

/// A wrapper around [sp_io::TestExternalities] that provides a richer API for testing pallets.
Expand Down

0 comments on commit 1b5204e

Please sign in to comment.