Update bridges subtree (#5165)

* Squashed 'bridges/' changes from 1602249f0a..f220d2fcca

f220d2fcca Polkadot staging update (#1356)
02fd3d497c fix parse_transaction on Rialto+Millau (#1360)
bc191fd9a2 update parity-scale-codec to 3.1.2 (#1359)
a37226e79c update chain versions (#1358)
ff5d539fcb Update Substrate/Polkadot/Cumulus references (#1353)
1581f60cd5 Support dedicated lanes for pallets (#962)
0a7ccf5c57 ignore more "increase" alerts that are sometimes signalling NoData at startup (#1351)
31165127cc added no_stack_overflow_when_decoding_nested_call_during_dispatch test (#1349)
7000619eb8 replace From<>InboundLaneApi with direct storage reads (#1348)
515df10ccc added alerts for relay balances (#1347)
b56f6a87de Mortal conversion rate updater transactions (#1257)
20f2f331ec edition = "2021" (#1346)
99147d4f75 update regex to 1.5.5 (#1345)
686191f379 use DecodeLimit when decoding incoming calls (#1344)
a70c276006 get rid of '[No Data] Messages from Millau to Rialto are not being delivered' warnings (#1342)
01f29b8ac1 fix conversion rate metric in dashboards (#1341)
51c3bf351f Increase rate from metric when estimating fee (#1340)
3bb9c4f68f fix generator scripts to be consistent with updatedrelay output (#1339)
0475a1667b fixed mess with conversion rates (#1338)
d8fdd7d716 synchronize relay cli changes and token swap generator script (#1337)
6e928137a5 fix conversion rate override in token swap (#1336)
62d4a4811d override conversion rate in tokens swap generator (#1335)
ed9e1c839c fi typo in generator script (#1334)
3254b5af7a Override conversion rate when computing message fee (#1261)
66df68b5b8 Revert "Revert "override conversion rate in estimate-message-fee RPC (#1189)" (#1275)" (#1333)
0ca6fc6ef8 fix clippy issues (#1332)
5414b2fffb Reinitialize bridge relay subcommand (#1331)
a63d95ba7d removed extra *_RUNTIME_VERSION consts from relay code (#1330)
59fb18a310 fix typo in alert expression (#1329)
a6267a47ee Using-same-fork metric for finality and complex relay (#1327)
88d684d37e use mortal transactions in transaction resubmitter (#1326)
8ff88b6844 impl Decode for SignedExtensions (otherwise transaction resubmitter panicks) (#1325)
1ed09854f0 Encode and estimate Rococo/Wococo/Kusama/Polkadot messages (#1322)
ddb4517e13 Add some tests to check integrity of chain constants + bridge configuration (#1316)
bdeedb7ab9 Fix issues from cargo deny (#1311)
d3d79d01e0 expose fee multiplier metrics in messages relay (#1312)
c8b3f0ea16 Endow relayer account at target chain in message benchmarks (#1310)
f51ecd92b6 fix benchmarks before using it in Polkadot/Kusama/Rococo runtimes (#1309)
6935c619ad increase relay balance guard limits for Polkadot<>Kusama bridge (#1308)
7e31834c66 Fix mandatory headers scanning in on-demand relay (#1306)
92ddc3ea7a Polkadot-staging update (#1305)
3787193a31 fix session length of Rococo and Wococo (#1304)
eb468d29c0 Revert nightly docker pin (#1301)
e2d4c073e1 Use raw balance value if tokenDecimals property is missing (#1299)
108f4b29d1 Fix ss58 prefixes of Polkadot, Kusama and Westend used by relay (#1298)
64fbd2705e bump chain spec versions (#1297)
5707777b86 Bump Substrate/Polkadot/Cumulus refs (#1295)
29eecdf1fa Merge pull request #1294 from paritytech/polkadot-staging-update
1f0c05368e Relay balance metrics (#1291)
6356bb90b3 when messages pallet is halted, relay shall not submit messages delivery/confirmation transactions (#1289)
800dc2df8d when GRANDPA pallet is halted, relay shall not submit finality transactions (#1288)
3dd8e4f936 disable BEEFY allerts for Rialto (#1285)
f58fed7380 support version mode cli options in send-message subcommand (#1284)
3aac448da3 reuse polkadot-service code (#1273)
2bdbb651e1 replace latest_confirmed_nonce runtime APIs with direct storage reads (#1282)
5f9c6d241f move "common" code of messages pallet benchmarks helpers to the common library (#1281)
173d2d8229 Merge pull request #1280 from paritytech/polkadot-staging-update
8b9c4ec16d do not start spec_version guard when version mode is set to auto (#1278)
e98d682de2 removed extra messages benchmarks (#1279)
c730e25b61 Move benchmarks from Rialto to Millau (#1277)
54146416e7 Merge pull request #1276 from paritytech/polkadot-staging-update
df70118174 Merge branch 'master' into polkadot-staging-update
ed7def64c4 Revert "override conversion rate in estimate-message-fee RPC (#1189)" (#1275)
38c6c3a49f Use "production" floating tag when uilding docker image from version git tags (#1272)
ded9ff6dbb Replace InboundLaneApi::latest_received_nonce with direct storage read (#1269)
f704a741ee Polkadot staging update (#1270)
8c65f0d7ab verify that GRANDPA pallet is not initialized before submitting initialization transaction (#1267)
e7e83d8944 remove OutboundLaneApi::latest_received_nonce (#1262)
9f4b34acf1 bump rococo version (#1263)
82c08c5a87 read latest_generated_nonce directly from storage (#1260)
50ffb5dd08 override conversion rate in estimate-message-fee RPC (#1189)
467ca5ef59 move storage keys computation to primitivs (#1254)
4f9884066b remporary use pinned bridges-ci image in Dockerfile (#1258)
edfcb74e00 Change submit transaction spec_version and transaction_version query from chain (#1248)
4009d970d0 pin bridges-ci image (#1256)
65e51b5e1c decrease startup sleep to 5s for relays and to 120s for generators + remove curl (#1251)
3bc74355d9 Add missing RPC APIs to rialto parachain node (#1250)
80c9429284 Bump relay version to 1.0.0 (#1249)
9ead06af2a runtimes: fix call_size() test (#1245)
4fc8a29357 Use same endowed accounts set on dev/local chains (#1244)
fed54371c2 Refactor message relay helpers (#1234)
a15b4faae7 post-merge build fix (#1243)
52232d8d54 Fix transactions mortality (#1196)
c07bba931f Expose prometheus BEEFY metrics and add them to grafana dashboard (#1242)
f927775bd5 Refactor finality relay helpers (#1220)
7bf76f14a8 Update Rococo/Wococo version + prepare relay for Rococo<>Wococo bridge (#1241)
e860fecd04 Enable offchain indexing for Rialto/Millau nodes (#1239)
04d4d1c6b4 Enable Beefy debug logs in test deployment (#1237)
cd771f1089 Fix storage parameter name computation (#1238)
816ddd2dd2 Integrate BEEFY with Rialto & Millau runtimes (#1227)
d94b62b1ac update dependencies (#1229)
98eb9ee13d Add mut support (#1232)
ffef6f89f9 fixed set_operational in GRANDPA pallet (#1226)
bd2f8bfbd7 Add CODEOWNERS file (#1219)
6b5cf2b591 Unify metric names (#1209)
d1541e797e remove abandoned exchange relay (#1217)
39140d0b34 Remove unused `relays/headers` (#1216)
9bc071d42b Remove unused PoA<>Substrate bridge (#1210)
877e8d01e3 Fix UI deployment. (#1211)
6cd5775ebe Add `AtLeast32BitUnsigned` for MessageLance::SourceChainBalance (#1207)

git-subtree-dir: bridges
git-subtree-split: f220d2fccabbf141101d19456ecb4e3576a1d797

* fix compilation warnings
This commit is contained in:
Svyatoslav Nikolsky
2022-03-21 13:19:29 +03:00
committed by GitHub
parent 20da356434
commit 8e01ba9c03
212 changed files with 9704 additions and 7984 deletions
@@ -16,39 +16,143 @@
//! Tools for updating conversion rate that is stored in the runtime storage.
use crate::{messages_lane::SubstrateMessageLane, TransactionParams};
use codec::Encode;
use relay_substrate_client::{
transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, CallOf, Chain, Client, SignParam,
TransactionEra, TransactionSignScheme, UnsignedTransaction,
};
use relay_utils::metrics::F64SharedRef;
use std::{future::Future, time::Duration};
use sp_core::{Bytes, Pair};
use std::time::{Duration, Instant};
/// Duration between updater iterations.
const SLEEP_DURATION: Duration = Duration::from_secs(60);
/// Duration which will almost never expire. Since changing conversion rate may require manual
/// intervention (e.g. if call is made through `multisig` pallet), we don't want relayer to
/// resubmit transaction often.
const ALMOST_NEVER_DURATION: Duration = Duration::from_secs(60 * 60 * 24 * 30);
/// Update-conversion-rate transaction status.
#[derive(Debug, Clone, Copy, PartialEq)]
enum TransactionStatus {
/// We have not submitted any transaction recently.
Idle,
/// We have recently submitted transaction that should update conversion rate.
Submitted(f64),
Submitted(Instant, f64),
}
/// Different ways of building 'update conversion rate' calls.
pub trait UpdateConversionRateCallBuilder<C: Chain> {
/// Given conversion rate, build call that updates conversion rate in given chain runtime
/// storage.
fn build_update_conversion_rate_call(conversion_rate: f64) -> anyhow::Result<CallOf<C>>;
}
impl<C: Chain> UpdateConversionRateCallBuilder<C> for () {
fn build_update_conversion_rate_call(_conversion_rate: f64) -> anyhow::Result<CallOf<C>> {
Err(anyhow::format_err!("Conversion rate update is not supported at {}", C::NAME))
}
}
/// Macro that generates `UpdateConversionRateCallBuilder` implementation for the case when
/// you have a direct access to the source chain runtime.
#[rustfmt::skip]
#[macro_export]
macro_rules! generate_direct_update_conversion_rate_call_builder {
(
$source_chain:ident,
$mocked_builder:ident,
$runtime:ty,
$instance:ty,
$parameter:path
) => {
pub struct $mocked_builder;
impl $crate::conversion_rate_update::UpdateConversionRateCallBuilder<$source_chain>
for $mocked_builder
{
fn build_update_conversion_rate_call(
conversion_rate: f64,
) -> anyhow::Result<relay_substrate_client::CallOf<$source_chain>> {
Ok(pallet_bridge_messages::Call::update_pallet_parameter::<$runtime, $instance> {
parameter: $parameter(sp_runtime::FixedU128::from_float(conversion_rate)),
}.into())
}
}
};
}
/// Macro that generates `UpdateConversionRateCallBuilder` implementation for the case when
/// you only have an access to the mocked version of source chain runtime. In this case you
/// should provide "name" of the call variant for the bridge messages calls, the "name" of
/// the variant for the `update_pallet_parameter` call within that first option and the name
/// of the conversion rate parameter itself.
#[rustfmt::skip]
#[macro_export]
macro_rules! generate_mocked_update_conversion_rate_call_builder {
(
$source_chain:ident,
$mocked_builder:ident,
$bridge_messages:path,
$update_pallet_parameter:path,
$parameter:path
) => {
pub struct $mocked_builder;
impl $crate::conversion_rate_update::UpdateConversionRateCallBuilder<$source_chain>
for $mocked_builder
{
fn build_update_conversion_rate_call(
conversion_rate: f64,
) -> anyhow::Result<relay_substrate_client::CallOf<$source_chain>> {
Ok($bridge_messages($update_pallet_parameter($parameter(
sp_runtime::FixedU128::from_float(conversion_rate),
))))
}
}
};
}
/// Run infinite conversion rate updater loop.
///
/// The loop is maintaining the Left -> Right conversion rate, used as `RightTokens = LeftTokens *
/// Rate`.
pub fn run_conversion_rate_update_loop<
SubmitConversionRateFuture: Future<Output = anyhow::Result<()>> + Send + 'static,
>(
pub fn run_conversion_rate_update_loop<Lane, Sign>(
client: Client<Lane::SourceChain>,
transaction_params: TransactionParams<AccountKeyPairOf<Sign>>,
left_to_right_stored_conversion_rate: F64SharedRef,
left_to_base_conversion_rate: F64SharedRef,
right_to_base_conversion_rate: F64SharedRef,
max_difference_ratio: f64,
submit_conversion_rate: impl Fn(f64) -> SubmitConversionRateFuture + Send + 'static,
) {
) where
Lane: SubstrateMessageLane,
Sign: TransactionSignScheme<Chain = Lane::SourceChain>,
AccountIdOf<Lane::SourceChain>: From<<AccountKeyPairOf<Sign> as Pair>::Public>,
{
let stall_timeout = transaction_stall_timeout(
transaction_params.mortality,
Lane::SourceChain::AVERAGE_BLOCK_INTERVAL,
ALMOST_NEVER_DURATION,
);
log::info!(
target: "bridge",
"Starting {} -> {} conversion rate (on {}) update loop. Stall timeout: {}s",
Lane::TargetChain::NAME,
Lane::SourceChain::NAME,
Lane::SourceChain::NAME,
stall_timeout.as_secs(),
);
async_std::task::spawn(async move {
let mut transaction_status = TransactionStatus::Idle;
loop {
async_std::task::sleep(SLEEP_DURATION).await;
let maybe_new_conversion_rate = maybe_select_new_conversion_rate(
stall_timeout,
&mut transaction_status,
&left_to_right_stored_conversion_rate,
&left_to_base_conversion_rate,
@@ -57,13 +161,32 @@ pub fn run_conversion_rate_update_loop<
)
.await;
if let Some((prev_conversion_rate, new_conversion_rate)) = maybe_new_conversion_rate {
let submit_conversion_rate_future = submit_conversion_rate(new_conversion_rate);
match submit_conversion_rate_future.await {
log::info!(
target: "bridge",
"Going to update {} -> {} (on {}) conversion rate to {}.",
Lane::TargetChain::NAME,
Lane::SourceChain::NAME,
Lane::SourceChain::NAME,
new_conversion_rate,
);
let result = update_target_to_source_conversion_rate::<Lane, Sign>(
client.clone(),
transaction_params.clone(),
new_conversion_rate,
)
.await;
match result {
Ok(()) => {
transaction_status = TransactionStatus::Submitted(prev_conversion_rate);
transaction_status =
TransactionStatus::Submitted(Instant::now(), prev_conversion_rate);
},
Err(error) => {
log::trace!(target: "bridge", "Failed to submit conversion rate update transaction: {:?}", error);
log::error!(
target: "bridge",
"Failed to submit conversion rate update transaction: {:?}",
error,
);
},
}
}
@@ -73,6 +196,7 @@ pub fn run_conversion_rate_update_loop<
/// Select new conversion rate to submit to the node.
async fn maybe_select_new_conversion_rate(
stall_timeout: Duration,
transaction_status: &mut TransactionStatus,
left_to_right_stored_conversion_rate: &F64SharedRef,
left_to_base_conversion_rate: &F64SharedRef,
@@ -83,7 +207,18 @@ async fn maybe_select_new_conversion_rate(
(*left_to_right_stored_conversion_rate.read().await)?;
match *transaction_status {
TransactionStatus::Idle => (),
TransactionStatus::Submitted(previous_left_to_right_stored_conversion_rate) => {
TransactionStatus::Submitted(submitted_at, _)
if Instant::now() - submitted_at > stall_timeout =>
{
log::error!(
target: "bridge",
"Conversion rate update transaction has been lost and loop stalled. Restarting",
);
// we assume that our transaction has been lost
*transaction_status = TransactionStatus::Idle;
},
TransactionStatus::Submitted(_, previous_left_to_right_stored_conversion_rate) => {
// we can't compare float values from different sources directly, so we only care
// whether the stored rate has been changed or not. If it has been changed, then we
// assume that our proposal has been accepted.
@@ -106,7 +241,7 @@ async fn maybe_select_new_conversion_rate(
let left_to_base_conversion_rate = (*left_to_base_conversion_rate.read().await)?;
let right_to_base_conversion_rate = (*right_to_base_conversion_rate.read().await)?;
let actual_left_to_right_conversion_rate =
right_to_base_conversion_rate / left_to_base_conversion_rate;
left_to_base_conversion_rate / right_to_base_conversion_rate;
let rate_difference =
(actual_left_to_right_conversion_rate - left_to_right_stored_conversion_rate).abs();
@@ -118,11 +253,50 @@ async fn maybe_select_new_conversion_rate(
Some((left_to_right_stored_conversion_rate, actual_left_to_right_conversion_rate))
}
/// Update Target -> Source tokens conversion rate, stored in the Source runtime storage.
pub async fn update_target_to_source_conversion_rate<Lane, Sign>(
client: Client<Lane::SourceChain>,
transaction_params: TransactionParams<AccountKeyPairOf<Sign>>,
updated_rate: f64,
) -> anyhow::Result<()>
where
Lane: SubstrateMessageLane,
Sign: TransactionSignScheme<Chain = Lane::SourceChain>,
AccountIdOf<Lane::SourceChain>: From<<AccountKeyPairOf<Sign> as Pair>::Public>,
{
let genesis_hash = *client.genesis_hash();
let signer_id = transaction_params.signer.public().into();
let (spec_version, transaction_version) = client.simple_runtime_version().await?;
let call =
Lane::TargetToSourceChainConversionRateUpdateBuilder::build_update_conversion_rate_call(
updated_rate,
)?;
client
.submit_signed_extrinsic(signer_id, move |best_block_id, transaction_nonce| {
Ok(Bytes(
Sign::sign_transaction(SignParam {
spec_version,
transaction_version,
genesis_hash,
signer: transaction_params.signer,
era: TransactionEra::new(best_block_id, transaction_params.mortality),
unsigned: UnsignedTransaction::new(call.into(), transaction_nonce).into(),
})?
.encode(),
))
})
.await
.map(drop)
.map_err(|err| anyhow::format_err!("{:?}", err))
}
#[cfg(test)]
mod tests {
use super::*;
use async_std::sync::{Arc, RwLock};
const TEST_STALL_TIMEOUT: Duration = Duration::from_secs(60);
fn test_maybe_select_new_conversion_rate(
mut transaction_status: TransactionStatus,
stored_conversion_rate: Option<f64>,
@@ -134,6 +308,7 @@ mod tests {
let left_to_base_conversion_rate = Arc::new(RwLock::new(left_to_base_conversion_rate));
let right_to_base_conversion_rate = Arc::new(RwLock::new(right_to_base_conversion_rate));
let result = async_std::task::block_on(maybe_select_new_conversion_rate(
TEST_STALL_TIMEOUT,
&mut transaction_status,
&stored_conversion_rate,
&left_to_base_conversion_rate,
@@ -145,15 +320,10 @@ mod tests {
#[test]
fn rate_is_not_updated_when_transaction_is_submitted() {
let status = TransactionStatus::Submitted(Instant::now(), 10.0);
assert_eq!(
test_maybe_select_new_conversion_rate(
TransactionStatus::Submitted(10.0),
Some(10.0),
Some(1.0),
Some(1.0),
0.0
),
(None, TransactionStatus::Submitted(10.0)),
test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0),
(None, status),
);
}
@@ -161,7 +331,7 @@ mod tests {
fn transaction_state_is_changed_to_idle_when_stored_rate_shanges() {
assert_eq!(
test_maybe_select_new_conversion_rate(
TransactionStatus::Submitted(1.0),
TransactionStatus::Submitted(Instant::now(), 1.0),
Some(10.0),
Some(1.0),
Some(1.0),
@@ -229,15 +399,42 @@ mod tests {
#[test]
fn transaction_is_submitted_when_difference_is_above_threshold() {
let left_to_right_stored_conversion_rate = 1.0;
let left_to_base_conversion_rate = 18f64;
let right_to_base_conversion_rate = 180f64;
assert!(left_to_base_conversion_rate < right_to_base_conversion_rate);
assert_eq!(
test_maybe_select_new_conversion_rate(
TransactionStatus::Idle,
Some(1.0),
Some(1.0),
Some(1.03),
Some(left_to_right_stored_conversion_rate),
Some(left_to_base_conversion_rate),
Some(right_to_base_conversion_rate),
0.02
),
(Some((1.0, 1.03)), TransactionStatus::Idle),
(
Some((
left_to_right_stored_conversion_rate,
left_to_base_conversion_rate / right_to_base_conversion_rate,
)),
TransactionStatus::Idle
),
);
}
#[test]
fn transaction_expires() {
let status = TransactionStatus::Submitted(Instant::now() - TEST_STALL_TIMEOUT / 2, 10.0);
assert_eq!(
test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0),
(None, status),
);
let status = TransactionStatus::Submitted(Instant::now() - TEST_STALL_TIMEOUT * 2, 10.0);
assert_eq!(
test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0),
(Some((10.0, 1.0)), TransactionStatus::Idle),
);
}
}