Skip to content

Commit

Permalink
temporarily remove balance guard (paritytech#2121)
Browse files Browse the repository at this point in the history
  • Loading branch information
svyatonik authored May 9, 2023
1 parent 183778f commit ae06c73
Show file tree
Hide file tree
Showing 4 changed files with 5 additions and 253 deletions.
24 changes: 1 addition & 23 deletions bridges/relays/client-substrate/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! Substrate node client.

use crate::{
chain::{Chain, ChainWithBalances, ChainWithTransactions},
chain::{Chain, ChainWithTransactions},
rpc::{
SubstrateAuthorClient, SubstrateChainClient, SubstrateFinalityClient,
SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient,
Expand All @@ -31,14 +31,12 @@ use async_trait::async_trait;
use bp_runtime::{HeaderIdProvider, StorageDoubleMapKeyProvider, StorageMapKeyProvider};
use codec::{Decode, Encode};
use frame_support::weights::Weight;
use frame_system::AccountInfo;
use futures::{SinkExt, StreamExt};
use jsonrpsee::{
core::DeserializeOwned,
ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder},
};
use num_traits::{Saturating, Zero};
use pallet_balances::AccountData;
use pallet_transaction_payment::RuntimeDispatchInfo;
use relay_utils::{relay_loop::RECONNECT_DELAY, STALL_TIMEOUT};
use sp_core::{
Expand Down Expand Up @@ -424,26 +422,6 @@ impl<C: Chain> Client<C> {
})
}

/// Return native tokens balance of the account.
pub async fn free_native_balance(&self, account: C::AccountId) -> Result<C::Balance>
where
C: ChainWithBalances,
{
self.jsonrpsee_execute(move |client| async move {
let storage_key = C::account_info_storage_key(&account);
let encoded_account_data =
SubstrateStateClient::<C>::storage(&*client, storage_key, None)
.await?
.ok_or(Error::AccountDoesNotExist)?;
let decoded_account_data = AccountInfo::<C::Index, AccountData<C::Balance>>::decode(
&mut &encoded_account_data.0[..],
)
.map_err(Error::ResponseParseFailed)?;
Ok(decoded_account_data.data.free)
})
.await
}

/// Get the nonce of the given Substrate account.
///
/// Note: It's the caller's responsibility to make sure `account` is a valid SS58 address.
Expand Down
185 changes: 4 additions & 181 deletions bridges/relays/client-substrate/src/guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@
use crate::{error::Error, Chain, ChainWithBalances, Client};

use async_trait::async_trait;
use num_traits::CheckedSub;
use sp_version::RuntimeVersion;
use std::{
collections::VecDeque,
fmt::Display,
time::{Duration, Instant},
};
Expand All @@ -36,11 +34,6 @@ pub trait Environment<C: ChainWithBalances>: Send + Sync + 'static {

/// Return current runtime version.
async fn runtime_version(&mut self) -> Result<RuntimeVersion, Self::Error>;
/// Return free native balance of the account on the chain.
async fn free_native_balance(
&mut self,
account: C::AccountId,
) -> Result<C::Balance, Self::Error>;

/// Return current time.
fn now(&self) -> Instant {
Expand Down Expand Up @@ -99,80 +92,6 @@ pub fn abort_on_spec_version_change<C: ChainWithBalances>(
});
}

/// Abort if, during 24 hours, free balance of given account is decreased at least by given value.
/// Other components may increase (or decrease) balance of account and it WILL affect logic of the
/// guard.
pub fn abort_when_account_balance_decreased<C: ChainWithBalances>(
mut env: impl Environment<C>,
account_id: C::AccountId,
maximal_decrease: C::Balance,
) {
const DAY: Duration = Duration::from_secs(60 * 60 * 24);

async_std::task::spawn(async move {
log::info!(
target: "bridge-guard",
"Starting balance guard for {}/{:?}. Maximal decrease: {:?}",
C::NAME,
account_id,
maximal_decrease,
);

let mut balances = VecDeque::new();

loop {
let current_time = env.now();

// remember balances that are beyound 24h border
if let Some(time_border) = current_time.checked_sub(DAY) {
while balances.front().map(|(time, _)| *time < time_border).unwrap_or(false) {
balances.pop_front();
}
}

// read balance of the account
let current_balance = env.free_native_balance(account_id.clone()).await;

// remember balance and check difference
match current_balance {
Ok(current_balance) => {
// remember balance
balances.push_back((current_time, current_balance));

// check if difference between current and oldest balance is too large
let (oldest_time, oldest_balance) =
balances.front().expect("pushed to queue couple of lines above; qed");
let balances_difference = oldest_balance.checked_sub(&current_balance);
if balances_difference > Some(maximal_decrease) {
log::error!(
target: "bridge-guard",
"Balance of {} account {:?} has decreased from {:?} to {:?} in {} minutes. Aborting relay",
C::NAME,
account_id,
oldest_balance,
current_balance,
current_time.duration_since(*oldest_time).as_secs() / 60,
);

env.abort().await;
}
},
Err(error) => {
log::warn!(
target: "bridge-guard",
"Failed to read {} account {:?} balance: {}. Relay may need to be stopped manually",
C::NAME,
account_id,
error,
);
},
};

env.sleep(conditions_check_delay::<C>()).await;
}
});
}

/// Delay between conditions check.
fn conditions_check_delay<C: Chain>() -> Duration {
C::AVERAGE_BLOCK_INTERVAL * (10 + rand::random::<u32>() % 10)
Expand All @@ -185,13 +104,6 @@ impl<C: ChainWithBalances> Environment<C> for Client<C> {
async fn runtime_version(&mut self) -> Result<RuntimeVersion, Self::Error> {
Client::<C>::runtime_version(self).await
}

async fn free_native_balance(
&mut self,
account: C::AccountId,
) -> Result<C::Balance, Self::Error> {
Client::<C>::free_native_balance(self, account).await
}
}

#[cfg(test)]
Expand All @@ -207,7 +119,6 @@ mod tests {

struct TestEnvironment {
runtime_version_rx: UnboundedReceiver<RuntimeVersion>,
free_native_balance_rx: UnboundedReceiver<u32>,
slept_tx: UnboundedSender<()>,
aborted_tx: UnboundedSender<()>,
}
Expand All @@ -220,10 +131,6 @@ mod tests {
Ok(self.runtime_version_rx.next().await.unwrap_or_default())
}

async fn free_native_balance(&mut self, _account: u32) -> Result<u32, Self::Error> {
Ok(self.free_native_balance_rx.next().await.unwrap_or_default())
}

async fn sleep(&mut self, _duration: Duration) {
let _ = self.slept_tx.send(()).await;
}
Expand All @@ -240,17 +147,11 @@ mod tests {
async_std::task::block_on(async {
let (
(mut runtime_version_tx, runtime_version_rx),
(_free_native_balance_tx, free_native_balance_rx),
(slept_tx, mut slept_rx),
(aborted_tx, mut aborted_rx),
) = (unbounded(), unbounded(), unbounded(), unbounded());
) = (unbounded(), unbounded(), unbounded());
abort_on_spec_version_change(
TestEnvironment {
runtime_version_rx,
free_native_balance_rx,
slept_tx,
aborted_tx,
},
TestEnvironment { runtime_version_rx, slept_tx, aborted_tx },
0,
);

Expand All @@ -272,17 +173,11 @@ mod tests {
async_std::task::block_on(async {
let (
(mut runtime_version_tx, runtime_version_rx),
(_free_native_balance_tx, free_native_balance_rx),
(slept_tx, mut slept_rx),
(aborted_tx, mut aborted_rx),
) = (unbounded(), unbounded(), unbounded(), unbounded());
) = (unbounded(), unbounded(), unbounded());
abort_on_spec_version_change(
TestEnvironment {
runtime_version_rx,
free_native_balance_rx,
slept_tx,
aborted_tx,
},
TestEnvironment { runtime_version_rx, slept_tx, aborted_tx },
42,
);

Expand All @@ -298,76 +193,4 @@ mod tests {
assert!(aborted_rx.next().now_or_never().is_none());
});
}

#[test]
fn aborts_when_balance_is_too_low() {
async_std::task::block_on(async {
let (
(_runtime_version_tx, runtime_version_rx),
(mut free_native_balance_tx, free_native_balance_rx),
(slept_tx, mut slept_rx),
(aborted_tx, mut aborted_rx),
) = (unbounded(), unbounded(), unbounded(), unbounded());
abort_when_account_balance_decreased(
TestEnvironment {
runtime_version_rx,
free_native_balance_rx,
slept_tx,
aborted_tx,
},
0,
100,
);

// client responds with initial balance
free_native_balance_tx.send(1000).await.unwrap();

// then the guard sleeps
slept_rx.next().await;

// and then client responds with updated balance, which is too low
free_native_balance_tx.send(899).await.unwrap();

// then the `abort` function is called
aborted_rx.next().await;
// and we do not reach next `sleep` function call
assert!(slept_rx.next().now_or_never().is_none());
});
}

#[test]
fn does_not_aborts_when_balance_is_enough() {
async_std::task::block_on(async {
let (
(_runtime_version_tx, runtime_version_rx),
(mut free_native_balance_tx, free_native_balance_rx),
(slept_tx, mut slept_rx),
(aborted_tx, mut aborted_rx),
) = (unbounded(), unbounded(), unbounded(), unbounded());
abort_when_account_balance_decreased(
TestEnvironment {
runtime_version_rx,
free_native_balance_rx,
slept_tx,
aborted_tx,
},
0,
100,
);

// client responds with initial balance
free_native_balance_tx.send(1000).await.unwrap();

// then the guard sleeps
slept_rx.next().await;

// and then client responds with updated balance, which is enough
free_native_balance_tx.send(950).await.unwrap();

// then the `sleep` function is called
slept_rx.next().await;
// and `abort` is not called
assert!(aborted_rx.next().now_or_never().is_none());
});
}
}
48 changes: 0 additions & 48 deletions bridges/relays/lib-substrate-relay/src/finality/guards.rs

This file was deleted.

1 change: 0 additions & 1 deletion bridges/relays/lib-substrate-relay/src/finality/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ use sp_core::Pair;
use std::{fmt::Debug, marker::PhantomData};

pub mod engine;
pub mod guards;
pub mod initialize;
pub mod source;
pub mod target;
Expand Down

0 comments on commit ae06c73

Please sign in to comment.