Stored conversion rate updater (#1005)

* update conversion rate: initial commit

* Rialto=Polkadot && Millau=Kusama + actually update conversion rates

* update deployment scripts and readme

* allow non-zero difference between stored and real rates

* dummy commit

* Revert "dummy commit"

This reverts commit a438198180a8385feeaaca60c9d2da0950465215.

* clippy

* #[allow(clippy::float_cmp)] in conversion rate update

* dummy

* Revert "dummy"

This reverts commit 90cd6e47cda56f655e94dbef76138e6cc58d664a.

* spell

* shared_value_ref() -> get()

* Revert "shared_value_ref() -> get()"

This reverts commit 20aa30de6a59b2099cfba3e9676e71200b7bb468.
This commit is contained in:
Svyatoslav Nikolsky
2021-09-01 11:51:57 +03:00
committed by Bastian Köcher
parent fc9363619a
commit 3ef4574594
13 changed files with 464 additions and 24 deletions
@@ -26,6 +26,7 @@ use futures::{FutureExt, TryFutureExt};
use structopt::StructOpt;
use strum::VariantNames;
use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_utils::metrics::MetricsParams;
use substrate_relay_helper::messages_lane::{MessagesRelayParams, SubstrateMessageLane};
use substrate_relay_helper::on_demand_headers::OnDemandHeadersRelay;
@@ -33,6 +34,14 @@ use substrate_relay_helper::on_demand_headers::OnDemandHeadersRelay;
use crate::cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams};
use crate::declare_chain_options;
/// Maximal allowed conversion rate error ratio (abs(real - stored) / stored) that we allow.
///
/// If it is zero, then transaction will be submitted every time we see difference between
/// stored and real conversion rates. If it is large enough (e.g. > than 10 percents, which is 0.1),
/// then rational relayers may stop relaying messages because they were submitted using
/// lesser conversion rate.
const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05;
/// Start headers+messages relayer process.
#[derive(StructOpt)]
pub enum RelayHeadersAndMessages {
@@ -68,9 +77,13 @@ macro_rules! declare_bridge_options {
#[structopt(flatten)]
left_sign: [<$chain1 SigningParams>],
#[structopt(flatten)]
left_messages_pallet_owner: [<$chain1 MessagesPalletOwnerSigningParams>],
#[structopt(flatten)]
right: [<$chain2 ConnectionParams>],
#[structopt(flatten)]
right_sign: [<$chain2 SigningParams>],
#[structopt(flatten)]
right_messages_pallet_owner: [<$chain2 MessagesPalletOwnerSigningParams>],
}
#[allow(unreachable_patterns)]
@@ -106,9 +119,11 @@ macro_rules! select_bridge {
use crate::chains::millau_messages_to_rialto::{
add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages,
update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate,
};
use crate::chains::rialto_messages_to_millau::{
add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages,
update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate,
};
$generic
@@ -135,6 +150,22 @@ macro_rules! select_bridge {
add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages,
};
async fn update_right_to_left_conversion_rate(
_client: Client<Left>,
_signer: <Left as TransactionSignScheme>::AccountKeyPair,
_updated_rate: f64,
) -> anyhow::Result<()> {
Err(anyhow::format_err!("Conversion rate is not supported by this bridge"))
}
async fn update_left_to_right_conversion_rate(
_client: Client<Right>,
_signer: <Right as TransactionSignScheme>::AccountKeyPair,
_updated_rate: f64,
) -> anyhow::Result<()> {
Err(anyhow::format_err!("Conversion rate is not supported by this bridge"))
}
$generic
}
}
@@ -158,16 +189,86 @@ impl RelayHeadersAndMessages {
let left_client = params.left.to_client::<Left>().await?;
let left_sign = params.left_sign.to_keypair::<Left>()?;
let left_messages_pallet_owner = params.left_messages_pallet_owner.to_keypair::<Left>()?;
let right_client = params.right.to_client::<Right>().await?;
let right_sign = params.right_sign.to_keypair::<Right>()?;
let right_messages_pallet_owner = params.right_messages_pallet_owner.to_keypair::<Right>()?;
let lanes = params.shared.lane;
let relayer_mode = params.shared.relayer_mode.into();
const METRIC_IS_SOME_PROOF: &str = "it is `None` when metric has been already registered; \
this is the command entrypoint, so nothing has been registered yet; \
qed";
let metrics_params: MetricsParams = params.shared.prometheus_params.into();
let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params();
let (metrics_params, _) = add_left_to_right_standalone_metrics(None, metrics_params, left_client.clone())?;
let (metrics_params, _) = add_right_to_left_standalone_metrics(None, metrics_params, right_client.clone())?;
let (metrics_params, left_to_right_metrics) =
add_left_to_right_standalone_metrics(None, metrics_params, left_client.clone())?;
let (metrics_params, right_to_left_metrics) =
add_right_to_left_standalone_metrics(None, metrics_params, right_client.clone())?;
if let Some(left_messages_pallet_owner) = left_messages_pallet_owner {
let left_client = left_client.clone();
substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop(
left_to_right_metrics
.target_to_source_conversion_rate
.expect(METRIC_IS_SOME_PROOF),
left_to_right_metrics
.target_to_base_conversion_rate
.clone()
.expect(METRIC_IS_SOME_PROOF),
left_to_right_metrics
.source_to_base_conversion_rate
.clone()
.expect(METRIC_IS_SOME_PROOF),
CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO,
move |new_rate| {
log::info!(
target: "bridge",
"Going to update {} -> {} (on {}) conversion rate to {}.",
Right::NAME,
Left::NAME,
Left::NAME,
new_rate,
);
update_right_to_left_conversion_rate(
left_client.clone(),
left_messages_pallet_owner.clone(),
new_rate,
)
},
);
}
if let Some(right_messages_pallet_owner) = right_messages_pallet_owner {
let right_client = right_client.clone();
substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop(
right_to_left_metrics
.target_to_source_conversion_rate
.expect(METRIC_IS_SOME_PROOF),
left_to_right_metrics
.source_to_base_conversion_rate
.expect(METRIC_IS_SOME_PROOF),
left_to_right_metrics
.target_to_base_conversion_rate
.expect(METRIC_IS_SOME_PROOF),
CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO,
move |new_rate| {
log::info!(
target: "bridge",
"Going to update {} -> {} (on {}) conversion rate to {}.",
Left::NAME,
Right::NAME,
Right::NAME,
new_rate,
);
update_left_to_right_conversion_rate(
right_client.clone(),
right_messages_pallet_owner.clone(),
new_rate,
)
},
);
}
let left_to_right_on_demand_headers = OnDemandHeadersRelay::new(
left_client.clone(),