Skip to content

Commit

Permalink
fix: make wallet tests wait consensus
Browse files Browse the repository at this point in the history
  • Loading branch information
douglaz committed Aug 22, 2023
1 parent 71e4d2c commit 718d205
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 15 deletions.
34 changes: 31 additions & 3 deletions devimint/src/federation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ impl Federation {

pub async fn pegin(&self, amount: u64) -> Result<()> {
info!(amount, "Peg-in");
// Some blocks must always be mined first before pegin
self.await_minimum_blocks().await?;
let deposit = cmd!(self, "deposit-address").out_json().await?;
let deposit_address = deposit["address"].as_str().unwrap();
let deposit_operation_id = deposit["operation_id"].as_str().unwrap();
Expand All @@ -195,6 +197,8 @@ impl Federation {

pub async fn pegin_gateway(&self, amount: u64, gw: &Gatewayd) -> Result<()> {
info!(amount, "Pegging-in gateway funds");
// Some blocks must always be mined first before pegin
self.await_minimum_blocks().await?;
let fed_id = self.federation_id().await;
let pegin_addr = cmd!(gw, "address", "--federation-id={fed_id}")
.out_json()
Expand Down Expand Up @@ -227,21 +231,44 @@ impl Federation {
.to_string()
}

pub async fn await_block_sync(&self) -> Result<()> {
pub async fn await_block_sync(&self) -> Result<u64> {
let client = self.client().await?;
let wallet_cfg: &WalletClientConfig = client
.config_ref()
.0
.get_module(LEGACY_HARDCODED_INSTANCE_ID_WALLET)?;
let finality_delay = wallet_cfg.finality_delay;
let bitcoind_block_count = self.bitcoind.client().get_blockchain_info()?.blocks;
let expected = bitcoind_block_count - (finality_delay as u64);
let expected = bitcoind_block_count.saturating_sub(finality_delay.into());
cmd!(self, "dev", "wait-block-count", expected)
.run()
.await?;
Ok(expected)
}

pub async fn await_minimum_blocks(&self) -> Result<()> {
let finality_delay = self.get_finality_delay().await?;
let block_count = cmd!(self, "dev", "block-count").out_json().await?["count"]
.as_u64()
.context("missing block count")?;
if block_count >= finality_delay.into() {
return Ok(());
} else {
self.generate_epochs(1).await?;
}
Ok(())
}

async fn get_finality_delay(&self) -> Result<u32, anyhow::Error> {
let client: fedimint_client_legacy::Client<UserClientConfig> = self.client().await?;
let wallet_cfg: &WalletClientConfig = client
.config_ref()
.0
.get_module(LEGACY_HARDCODED_INSTANCE_ID_WALLET)?;
let finality_delay = wallet_cfg.finality_delay;
Ok(finality_delay)
}

pub async fn await_gateways_registered(&self) -> Result<()> {
poll("gateways registered", || async {
Ok(cmd!(self, "list-gateways")
Expand Down Expand Up @@ -279,8 +306,9 @@ impl Federation {
}

pub async fn generate_epochs(&self, epochs: usize) -> Result<()> {
let finality_delay = self.get_finality_delay().await?;
for _ in 0..epochs {
self.bitcoind.mine_blocks(10).await?;
self.bitcoind.mine_blocks(finality_delay.into()).await?;
self.await_block_sync().await?;
}
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion fedimint-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ impl IGlobalClientContext for ModuleGlobalClientContext {
TransactionBuilder::new().with_input(instance_input),
)
.await
.expect("Can obly fail if additional funding is needed")
.expect("Can only fail if additional funding is needed")
}

async fn fund_output_dyn(
Expand Down
26 changes: 16 additions & 10 deletions modules/fedimint-wallet-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ impl ServerModule for Wallet {
.await
.saturating_sub(self.cfg.consensus.finality_delay);

if block_count_proposal != self.consensus_block_count(dbtx).await {
if Some(block_count_proposal) != self.consensus_block_count(dbtx).await {
items.push(WalletConsensusItem::BlockCount(block_count_proposal));
}

Expand Down Expand Up @@ -370,11 +370,14 @@ impl ServerModule for Wallet {
let new_consensus_block_count = self.consensus_block_count(dbtx).await;

// only sync from the first non-default consensus block count
if new_consensus_block_count > old_consensus_block_count {
if old_consensus_block_count.is_some()
&& new_consensus_block_count.is_some()
&& new_consensus_block_count.unwrap() > old_consensus_block_count.unwrap()
{
self.sync_up_to_consensus_height(
dbtx,
old_consensus_block_count,
new_consensus_block_count,
old_consensus_block_count.unwrap(),
new_consensus_block_count.unwrap(),
)
.await;
}
Expand Down Expand Up @@ -574,7 +577,8 @@ impl ServerModule for Wallet {
api_endpoint! {
"block_count",
async |module: &Wallet, context, _params: ()| -> u32 {
Ok(module.consensus_block_count(&mut context.dbtx()).await)
// TODO: should we change this to Option?
Ok(module.consensus_block_count(&mut context.dbtx()).await.unwrap_or_default())
}
},
api_endpoint! {
Expand Down Expand Up @@ -795,7 +799,10 @@ impl Wallet {
.unwrap_or(self.cfg.consensus.default_fee)
}

pub async fn consensus_block_count(&self, dbtx: &mut ModuleDatabaseTransaction<'_>) -> u32 {
pub async fn consensus_block_count(
&self,
dbtx: &mut ModuleDatabaseTransaction<'_>,
) -> Option<u32> {
let peer_count = self.cfg.consensus.peer_peg_in_keys.total();

let mut counts = dbtx
Expand All @@ -806,14 +813,13 @@ impl Wallet {
.await;

assert!(counts.len() <= peer_count);

while counts.len() < peer_count {
counts.push(0);
if counts.len() < peer_count {
return None;
}

counts.sort_unstable();

counts[peer_count / 2]
Some(counts[peer_count / 2])
}

pub async fn consensus_fee_rate(&self, dbtx: &mut ModuleDatabaseTransaction<'_>) -> Feerate {
Expand Down
29 changes: 28 additions & 1 deletion modules/fedimint-wallet-tests/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@ use std::time::{Duration, SystemTime};

use anyhow::bail;
use fedimint_client::Client;
use fedimint_core::task::sleep;
use fedimint_core::util::{BoxStream, NextOrPending};
use fedimint_core::{sats, Amount, Feerate};
use fedimint_dummy_client::DummyClientGen;
use fedimint_dummy_common::config::DummyGenParams;
use fedimint_dummy_server::DummyGen;
use fedimint_testing::btc::BitcoinTest;
use fedimint_testing::fixtures::Fixtures;
use fedimint_wallet_client::{DepositState, WalletClientExt, WalletClientGen, WithdrawState};
use fedimint_wallet_client::api::WalletFederationApi;
use fedimint_wallet_client::{
DepositState, WalletClientExt, WalletClientGen, WalletClientModule, WithdrawState,
};
use fedimint_wallet_common::config::WalletGenParams;
use fedimint_wallet_common::{PegOutFees, Rbf};
use fedimint_wallet_server::WalletGen;
use futures::stream::StreamExt;
use tracing::info;

fn fixtures() -> Fixtures {
let fixtures = Fixtures::new_primary(DummyClientGen, DummyGen, DummyGenParams::default());
Expand Down Expand Up @@ -60,6 +65,25 @@ async fn peg_in<'a>(
Ok(balance_sub)
}

async fn await_consensus_to_catch_up(client: &Client, block_count: u64) -> anyhow::Result<()> {
let (_, instance) =
client.get_first_module::<WalletClientModule>(&fedimint_wallet_client::KIND);
loop {
let current_consensus = client
.api()
.with_module(instance.id)
.fetch_consensus_block_count()
.await?;
if current_consensus < block_count {
info!("Current consensus block count is {current_consensus}, waiting for consensus to reach block count {block_count}");
sleep(Duration::from_secs(1)).await;
} else {
break;
}
}
Ok(())
}

#[tokio::test(flavor = "multi_thread")]
async fn on_chain_peg_in_and_peg_out_happy_case() -> anyhow::Result<()> {
let fixtures = fixtures();
Expand All @@ -69,6 +93,7 @@ async fn on_chain_peg_in_and_peg_out_happy_case() -> anyhow::Result<()> {

let finality_delay = 10;
bitcoin.mine_blocks(finality_delay).await;
await_consensus_to_catch_up(&client, finality_delay).await?;

let mut balance_sub = peg_in(&client, bitcoin.as_ref(), finality_delay).await?;

Expand Down Expand Up @@ -105,6 +130,7 @@ async fn peg_out_fail_refund() -> anyhow::Result<()> {
let bitcoin = fixtures.bitcoin();
let finality_delay = 10;
bitcoin.mine_blocks(finality_delay).await;
await_consensus_to_catch_up(&client, finality_delay).await?;

let mut balance_sub = peg_in(&client, bitcoin.as_ref(), finality_delay).await?;

Expand Down Expand Up @@ -146,6 +172,7 @@ async fn peg_outs_support_rbf() -> anyhow::Result<()> {

let finality_delay = 10;
bitcoin.mine_blocks(finality_delay).await;
await_consensus_to_catch_up(&client, finality_delay).await?;

let mut balance_sub = peg_in(&client, bitcoin.as_ref(), finality_delay).await?;

Expand Down

0 comments on commit 718d205

Please sign in to comment.