Merge commit '392447f5c8f986ded2559a78457f4cd87942f393' into update-bridges-subtree-r/w

This commit is contained in:
antonio-dropulic
2021-12-01 09:46:14 +01:00
321 changed files with 28385 additions and 10466 deletions
@@ -14,46 +14,71 @@
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::cli::bridge::FullBridge;
use crate::cli::encode_call::{self, CliEncodeCall};
use crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee;
use crate::cli::{
Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams,
TargetSigningParams,
bridge::FullBridge,
encode_call::{self, CliEncodeCall},
estimate_fee::estimate_message_delivery_and_dispatch_fee,
Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams,
SourceSigningParams, TargetSigningParams,
};
use bp_message_dispatch::{CallOrigin, MessagePayload};
use bp_runtime::messages::DispatchFeePayment;
use bp_runtime::BalanceOf;
use codec::Encode;
use frame_support::weights::Weight;
use relay_substrate_client::{Chain, TransactionSignScheme};
use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction};
use sp_core::{Bytes, Pair};
use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner};
use std::fmt::Debug;
use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames};
/// Relayer operating mode.
#[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq, Eq)]
#[strum(serialize_all = "kebab_case")]
pub enum DispatchFeePayment {
/// The dispatch fee is paid at the source chain.
AtSourceChain,
/// The dispatch fee is paid at the target chain.
AtTargetChain,
}
impl From<DispatchFeePayment> for bp_runtime::messages::DispatchFeePayment {
fn from(dispatch_fee_payment: DispatchFeePayment) -> Self {
match dispatch_fee_payment {
DispatchFeePayment::AtSourceChain => Self::AtSourceChain,
DispatchFeePayment::AtTargetChain => Self::AtTargetChain,
}
}
}
/// Send bridge message.
#[derive(StructOpt)]
pub struct SendMessage {
/// A bridge instance to encode call for.
#[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)]
#[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)]
bridge: FullBridge,
#[structopt(flatten)]
source: SourceConnectionParams,
#[structopt(flatten)]
source_sign: SourceSigningParams,
/// The SURI of secret key to use when transactions are submitted to the Target node.
#[structopt(long, required_if("origin", "Target"))]
target_signer: Option<String>,
/// The password for the SURI of secret key to use when transactions are submitted to the Target node.
#[structopt(long)]
target_signer_password: Option<String>,
#[structopt(flatten)]
target_sign: TargetSigningParams,
/// Hex-encoded lane id. Defaults to `00000000`.
#[structopt(long, default_value = "00000000")]
lane: HexLaneId,
/// Where dispatch fee is paid?
#[structopt(
long,
possible_values = DispatchFeePayment::VARIANTS,
case_insensitive = true,
default_value = "at-source-chain",
)]
dispatch_fee_payment: DispatchFeePayment,
/// Dispatch weight of the message. If not passed, determined automatically.
#[structopt(long)]
dispatch_weight: Option<ExplicitOrMaximal<Weight>>,
/// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically.
/// Delivery and dispatch fee in source chain base currency units. If not passed, determined
/// automatically.
#[structopt(long)]
fee: Option<Balance>,
/// Message type.
@@ -72,9 +97,9 @@ impl SendMessage {
crate::select_full_bridge!(self.bridge, {
let SendMessage {
source_sign,
target_signer,
target_signer_password,
target_sign,
ref mut message,
dispatch_fee_payment,
dispatch_weight,
origin,
bridge,
@@ -101,12 +126,6 @@ impl SendMessage {
match origin {
Origins::Source => CallOrigin::SourceAccount(source_account_id),
Origins::Target => {
let target_sign = TargetSigningParams {
target_signer: target_signer.clone().ok_or_else(|| {
anyhow::format_err!("The argument target_signer is not available")
})?,
target_signer_password: target_signer_password.clone(),
};
let target_sign = target_sign.to_keypair::<Target>()?;
let digest = account_ownership_digest(
&target_call,
@@ -120,9 +139,10 @@ impl SendMessage {
target_origin_public.into(),
digest_signature.into(),
)
}
},
},
&target_call,
*dispatch_fee_payment,
)
};
Ok(payload)
@@ -141,7 +161,7 @@ impl SendMessage {
let fee = match self.fee {
Some(fee) => fee,
None => Balance(
estimate_message_delivery_and_dispatch_fee::<<Source as Chain>::Balance, _, _>(
estimate_message_delivery_and_dispatch_fee::<BalanceOf<Source>, _, _>(
&source_client,
ESTIMATE_MESSAGE_FEE_METHOD,
lane,
@@ -158,24 +178,46 @@ impl SendMessage {
fee,
})?;
source_client
.submit_signed_extrinsic(source_sign.public().into(), |transaction_nonce| {
let signed_source_call = Source::sign_transaction(
*source_client.genesis_hash(),
let source_genesis_hash = *source_client.genesis_hash();
let estimated_transaction_fee = source_client
.estimate_extrinsic_fee(Bytes(
Source::sign_transaction(
source_genesis_hash,
&source_sign,
transaction_nonce,
send_message_call,
relay_substrate_client::TransactionEra::immortal(),
UnsignedTransaction::new(send_message_call.clone(), 0),
)
.encode(),
))
.await?;
source_client
.submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| {
let signed_source_call = Source::sign_transaction(
source_genesis_hash,
&source_sign,
relay_substrate_client::TransactionEra::immortal(),
UnsignedTransaction::new(send_message_call, transaction_nonce),
)
.encode();
log::info!(
target: "bridge",
"Sending message to {}. Size: {}. Dispatch weight: {}. Fee: {}",
"Sending message to {}. Lane: {:?}. Size: {}. Dispatch weight: {}. Fee: {}",
Target::NAME,
lane,
signed_source_call.len(),
dispatch_weight,
fee,
);
log::info!(
target: "bridge",
"The source account ({:?}) balance will be reduced by (at most) {} (message fee) + {} (tx fee ) = {} {} tokens",
AccountId32::from(source_sign.public()),
fee.0,
estimated_transaction_fee.inclusion_fee(),
fee.0.saturating_add(estimated_transaction_fee.inclusion_fee() as _),
Source::NAME,
);
log::info!(
target: "bridge",
"Signed {} Call: {:?}",
@@ -197,10 +239,7 @@ fn prepare_call_dispatch_weight(
weight_from_pre_dispatch_call: ExplicitOrMaximal<Weight>,
maximal_allowed_weight: Weight,
) -> Weight {
match user_specified_dispatch_weight
.clone()
.unwrap_or(weight_from_pre_dispatch_call)
{
match user_specified_dispatch_weight.clone().unwrap_or(weight_from_pre_dispatch_call) {
ExplicitOrMaximal::Explicit(weight) => weight,
ExplicitOrMaximal::Maximal => maximal_allowed_weight,
}
@@ -211,6 +250,7 @@ pub(crate) fn message_payload<SAccountId, TPublic, TSignature>(
weight: Weight,
origin: CallOrigin<SAccountId, TPublic, TSignature>,
call: &impl Encode,
dispatch_fee_payment: DispatchFeePayment,
) -> MessagePayload<SAccountId, TPublic, TSignature, Vec<u8>>
where
SAccountId: Encode + Debug,
@@ -222,7 +262,7 @@ where
spec_version,
weight,
origin,
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
dispatch_fee_payment: dispatch_fee_payment.into(),
call: HexBytes::encode(call),
};
@@ -230,24 +270,14 @@ where
log::info!(target: "bridge", "Encoded Message Payload: {:?}", HexBytes::encode(&payload));
// re-pack to return `Vec<u8>`
let MessagePayload {
spec_version,
weight,
origin,
dispatch_fee_payment,
call,
} = payload;
MessagePayload {
spec_version,
weight,
origin,
dispatch_fee_payment,
call: call.0,
}
let MessagePayload { spec_version, weight, origin, dispatch_fee_payment, call } = payload;
MessagePayload { spec_version, weight, origin, dispatch_fee_payment, call: call.0 }
}
pub(crate) fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight {
bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight)
bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(
maximal_extrinsic_weight,
)
}
#[cfg(test)]
@@ -260,7 +290,7 @@ mod tests {
// given
let mut send_message = SendMessage::from_iter(vec![
"send-message",
"RialtoToMillau",
"rialto-to-millau",
"--source-port",
"1234",
"--source-signer",
@@ -278,10 +308,12 @@ mod tests {
payload,
MessagePayload {
spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version,
weight: 1038000,
origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()),
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: hex!("0401081234").to_vec(),
weight: 576000,
origin: CallOrigin::SourceAccount(
sp_keyring::AccountKeyring::Alice.to_account_id()
),
dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain,
call: hex!("0001081234").to_vec(),
}
);
}
@@ -291,7 +323,7 @@ mod tests {
// given
let mut send_message = SendMessage::from_iter(vec![
"send-message",
"MillauToRialto",
"millau-to-rialto",
"--source-port",
"1234",
"--source-signer",
@@ -318,24 +350,24 @@ mod tests {
payload,
MessagePayload {
spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version,
weight: 1038000,
weight: 576000,
origin: CallOrigin::TargetAccount(
sp_keyring::AccountKeyring::Alice.to_account_id(),
sp_keyring::AccountKeyring::Bob.into(),
signature,
),
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
call: hex!("0701081234").to_vec(),
dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain,
call: hex!("0001081234").to_vec(),
}
);
}
#[test]
fn target_signer_must_exist_if_origin_is_target() {
fn accepts_send_message_command_without_target_sign_options() {
// given
let send_message = SendMessage::from_iter_safe(vec![
"send-message",
"MillauToRialto",
"rialto-to-millau",
"--source-port",
"1234",
"--source-signer",
@@ -347,6 +379,31 @@ mod tests {
"1234",
]);
assert!(send_message.is_err());
assert!(send_message.is_ok());
}
#[test]
fn accepts_non_default_dispatch_fee_payment() {
// given
let mut send_message = SendMessage::from_iter(vec![
"send-message",
"rialto-to-millau",
"--source-port",
"1234",
"--source-signer",
"//Alice",
"--dispatch-fee-payment",
"at-target-chain",
"remark",
]);
// when
let payload = send_message.encode_payload().unwrap();
// then
assert_eq!(
payload.dispatch_fee_payment,
bp_runtime::messages::DispatchFeePayment::AtTargetChain
);
}
}