Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Temporarily remove balance guard #2121

Merged
merged 1 commit into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 1 addition & 23 deletions 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 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 relays/lib-substrate-relay/src/finality/guards.rs

This file was deleted.

1 change: 0 additions & 1 deletion 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