mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 02:51:01 +00:00
Support Pallet Instances in Relay (#238)
* Sketch out how to support different bridge pallet instances * Create a common interface for using pallet instances * Start introducing generic instance parameter Attemps to make the compiler happy, but I'm having second thoughts about this approach. Commiting now as a way to have a checkpoint, but I think I'm going to need to re-consider my approach here. Ideally I want a change which introduces minimal changes, but this seems to be propagating around the codebase in ways I don't want. * Use trait objects instead of generics * Implement traits for Boxed trait objects This is done in order to statisfy trait bounds by types which use these new trait objects * Remove Clone usage for sync parameters * Remove implementation of Default for sync params * Require that BridgeInstance implements Debug * Ensure that BridgeInstance trait implements Send/Sync * Add documentation related to instances * Rust Fmt * Remove needless format * Make instance CLI option case insensitive * Replace `with_*` constructors with `new` * Clean up usage of instance structs * Enforce a default instance in the CLI params * Build sync params as we process input from CLI * Remove case insensitivity from sub-tx-mode I think this should happen, but maybe as part of a different PR * Process default Eth contract deployment config in CLI * Build EthereumExchangeParams in CLI * Process EthereumExchangeSubmitParams params in CLI
This commit is contained in:
committed by
Bastian Köcher
parent
6fd1651b21
commit
7f8360d8ab
@@ -43,6 +43,17 @@ subcommands:
|
|||||||
long: sub-signer-password
|
long: sub-signer-password
|
||||||
value_name: SUB_SIGNER_PASSWORD
|
value_name: SUB_SIGNER_PASSWORD
|
||||||
help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node.
|
help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node.
|
||||||
|
- sub-pallet-instance: &sub-pallet-instance
|
||||||
|
long: instance
|
||||||
|
short: i
|
||||||
|
value_name: PALLET_INSTANCE
|
||||||
|
help: The instance of the bridge pallet the relay should follow.
|
||||||
|
takes_value: true
|
||||||
|
case_insensitive: true
|
||||||
|
possible_values:
|
||||||
|
- Rialto
|
||||||
|
- Kovan
|
||||||
|
default_value: Rialto
|
||||||
- no-prometheus: &no-prometheus
|
- no-prometheus: &no-prometheus
|
||||||
long: no-prometheus
|
long: no-prometheus
|
||||||
help: Do not expose a Prometheus metric endpoint.
|
help: Do not expose a Prometheus metric endpoint.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
use crate::ethereum_client::{
|
use crate::ethereum_client::{
|
||||||
bridge_contract, EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams,
|
bridge_contract, EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams,
|
||||||
};
|
};
|
||||||
|
use crate::instances::BridgeInstance;
|
||||||
use crate::rpc::SubstrateRpc;
|
use crate::rpc::SubstrateRpc;
|
||||||
use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient};
|
use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient};
|
||||||
use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, SubstrateHeaderId};
|
use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, SubstrateHeaderId};
|
||||||
@@ -29,50 +30,48 @@ use num_traits::Zero;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EthereumDeployContractParams {
|
pub struct EthereumDeployContractParams {
|
||||||
/// Ethereum connection params.
|
/// Ethereum connection params.
|
||||||
pub eth: EthereumConnectionParams,
|
pub eth_params: EthereumConnectionParams,
|
||||||
/// Ethereum signing params.
|
/// Ethereum signing params.
|
||||||
pub eth_sign: EthereumSigningParams,
|
pub eth_sign: EthereumSigningParams,
|
||||||
/// Ethereum contract bytecode.
|
/// Ethereum contract bytecode.
|
||||||
pub eth_contract_code: Vec<u8>,
|
pub eth_contract_code: Vec<u8>,
|
||||||
/// Substrate connection params.
|
/// Substrate connection params.
|
||||||
pub sub: SubstrateConnectionParams,
|
pub sub_params: SubstrateConnectionParams,
|
||||||
/// Initial authorities set id.
|
/// Initial authorities set id.
|
||||||
pub sub_initial_authorities_set_id: Option<u64>,
|
pub sub_initial_authorities_set_id: Option<u64>,
|
||||||
/// Initial authorities set.
|
/// Initial authorities set.
|
||||||
pub sub_initial_authorities_set: Option<Vec<u8>>,
|
pub sub_initial_authorities_set: Option<Vec<u8>>,
|
||||||
/// Initial header.
|
/// Initial header.
|
||||||
pub sub_initial_header: Option<Vec<u8>>,
|
pub sub_initial_header: Option<Vec<u8>>,
|
||||||
}
|
/// Instance of the bridge pallet being synchronized.
|
||||||
|
pub instance: Box<dyn BridgeInstance>,
|
||||||
impl Default for EthereumDeployContractParams {
|
|
||||||
fn default() -> Self {
|
|
||||||
EthereumDeployContractParams {
|
|
||||||
eth: Default::default(),
|
|
||||||
eth_sign: Default::default(),
|
|
||||||
eth_contract_code: hex::decode(include_str!("../res/substrate-bridge-bytecode.hex"))
|
|
||||||
.expect("code is hardcoded, thus valid; qed"),
|
|
||||||
sub: Default::default(),
|
|
||||||
sub_initial_authorities_set_id: None,
|
|
||||||
sub_initial_authorities_set: None,
|
|
||||||
sub_initial_header: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deploy Bridge contract on Ethereum chain.
|
/// Deploy Bridge contract on Ethereum chain.
|
||||||
pub fn run(params: EthereumDeployContractParams) {
|
pub fn run(params: EthereumDeployContractParams) {
|
||||||
let mut local_pool = futures::executor::LocalPool::new();
|
let mut local_pool = futures::executor::LocalPool::new();
|
||||||
|
|
||||||
let result = local_pool.run_until(async move {
|
let EthereumDeployContractParams {
|
||||||
let eth_client = EthereumRpcClient::new(params.eth);
|
eth_params,
|
||||||
let sub_client = SubstrateRpcClient::new(params.sub).await?;
|
eth_sign,
|
||||||
|
sub_params,
|
||||||
|
instance,
|
||||||
|
sub_initial_authorities_set_id,
|
||||||
|
sub_initial_authorities_set,
|
||||||
|
sub_initial_header,
|
||||||
|
eth_contract_code,
|
||||||
|
} = params;
|
||||||
|
|
||||||
let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, params.sub_initial_header).await?;
|
let result = local_pool.run_until(async move {
|
||||||
let initial_set_id = params.sub_initial_authorities_set_id.unwrap_or(0);
|
let eth_client = EthereumRpcClient::new(eth_params);
|
||||||
|
let sub_client = SubstrateRpcClient::new(sub_params, instance).await?;
|
||||||
|
|
||||||
|
let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, sub_initial_header).await?;
|
||||||
|
let initial_set_id = sub_initial_authorities_set_id.unwrap_or(0);
|
||||||
let initial_set = prepare_initial_authorities_set(
|
let initial_set = prepare_initial_authorities_set(
|
||||||
&sub_client,
|
&sub_client,
|
||||||
initial_header_id.1,
|
initial_header_id.1,
|
||||||
params.sub_initial_authorities_set,
|
sub_initial_authorities_set,
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
@@ -87,8 +86,8 @@ pub fn run(params: EthereumDeployContractParams) {
|
|||||||
|
|
||||||
deploy_bridge_contract(
|
deploy_bridge_contract(
|
||||||
ð_client,
|
ð_client,
|
||||||
¶ms.eth_sign,
|
ð_sign,
|
||||||
params.eth_contract_code,
|
eth_contract_code,
|
||||||
initial_header,
|
initial_header,
|
||||||
initial_set_id,
|
initial_set_id,
|
||||||
initial_set,
|
initial_set,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ use crate::exchange::{
|
|||||||
TransactionProofPipeline,
|
TransactionProofPipeline,
|
||||||
};
|
};
|
||||||
use crate::exchange_loop::{run as run_loop, InMemoryStorage};
|
use crate::exchange_loop::{run as run_loop, InMemoryStorage};
|
||||||
|
use crate::instances::BridgeInstance;
|
||||||
use crate::metrics::MetricsParams;
|
use crate::metrics::MetricsParams;
|
||||||
use crate::rpc::{EthereumRpc, SubstrateRpc};
|
use crate::rpc::{EthereumRpc, SubstrateRpc};
|
||||||
use crate::rpc_errors::RpcError;
|
use crate::rpc_errors::RpcError;
|
||||||
@@ -58,15 +59,17 @@ pub enum ExchangeRelayMode {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EthereumExchangeParams {
|
pub struct EthereumExchangeParams {
|
||||||
/// Ethereum connection params.
|
/// Ethereum connection params.
|
||||||
pub eth: EthereumConnectionParams,
|
pub eth_params: EthereumConnectionParams,
|
||||||
/// Substrate connection params.
|
/// Substrate connection params.
|
||||||
pub sub: SubstrateConnectionParams,
|
pub sub_params: SubstrateConnectionParams,
|
||||||
/// Substrate signing params.
|
/// Substrate signing params.
|
||||||
pub sub_sign: SubstrateSigningParams,
|
pub sub_sign: SubstrateSigningParams,
|
||||||
/// Relay working mode.
|
/// Relay working mode.
|
||||||
pub mode: ExchangeRelayMode,
|
pub mode: ExchangeRelayMode,
|
||||||
/// Metrics parameters.
|
/// Metrics parameters.
|
||||||
pub metrics_params: Option<MetricsParams>,
|
pub metrics_params: Option<MetricsParams>,
|
||||||
|
/// Instance of the bridge pallet being synchronized.
|
||||||
|
pub instance: Box<dyn BridgeInstance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ethereum to Substrate exchange pipeline.
|
/// Ethereum to Substrate exchange pipeline.
|
||||||
@@ -253,18 +256,6 @@ impl TargetClient<EthereumToSubstrateExchange> for SubstrateTransactionsTarget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EthereumExchangeParams {
|
|
||||||
fn default() -> Self {
|
|
||||||
EthereumExchangeParams {
|
|
||||||
eth: Default::default(),
|
|
||||||
sub: Default::default(),
|
|
||||||
sub_sign: Default::default(),
|
|
||||||
mode: ExchangeRelayMode::Auto(None),
|
|
||||||
metrics_params: Some(Default::default()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Relay exchange transaction proof(s) to Substrate node.
|
/// Relay exchange transaction proof(s) to Substrate node.
|
||||||
pub fn run(params: EthereumExchangeParams) {
|
pub fn run(params: EthereumExchangeParams) {
|
||||||
match params.mode {
|
match params.mode {
|
||||||
@@ -279,14 +270,22 @@ pub fn run(params: EthereumExchangeParams) {
|
|||||||
fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H256) {
|
fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H256) {
|
||||||
let mut local_pool = futures::executor::LocalPool::new();
|
let mut local_pool = futures::executor::LocalPool::new();
|
||||||
|
|
||||||
|
let EthereumExchangeParams {
|
||||||
|
eth_params,
|
||||||
|
sub_params,
|
||||||
|
sub_sign,
|
||||||
|
instance,
|
||||||
|
..
|
||||||
|
} = params;
|
||||||
|
|
||||||
let result = local_pool.run_until(async move {
|
let result = local_pool.run_until(async move {
|
||||||
let eth_client = EthereumRpcClient::new(params.eth);
|
let eth_client = EthereumRpcClient::new(eth_params);
|
||||||
let sub_client = SubstrateRpcClient::new(params.sub).await?;
|
let sub_client = SubstrateRpcClient::new(sub_params, instance).await?;
|
||||||
|
|
||||||
let source = EthereumTransactionsSource { client: eth_client };
|
let source = EthereumTransactionsSource { client: eth_client };
|
||||||
let target = SubstrateTransactionsTarget {
|
let target = SubstrateTransactionsTarget {
|
||||||
client: sub_client,
|
client: sub_client,
|
||||||
sign_params: params.sub_sign,
|
sign_params: sub_sign,
|
||||||
};
|
};
|
||||||
|
|
||||||
relay_single_transaction_proof(&source, &target, eth_tx_hash).await
|
relay_single_transaction_proof(&source, &target, eth_tx_hash).await
|
||||||
@@ -313,9 +312,18 @@ fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H25
|
|||||||
|
|
||||||
/// Run auto-relay loop.
|
/// Run auto-relay loop.
|
||||||
fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_with_block_number: Option<u64>) {
|
fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_with_block_number: Option<u64>) {
|
||||||
|
let EthereumExchangeParams {
|
||||||
|
eth_params,
|
||||||
|
sub_params,
|
||||||
|
sub_sign,
|
||||||
|
metrics_params,
|
||||||
|
instance,
|
||||||
|
..
|
||||||
|
} = params;
|
||||||
|
|
||||||
let do_run_loop = move || -> Result<(), String> {
|
let do_run_loop = move || -> Result<(), String> {
|
||||||
let eth_client = EthereumRpcClient::new(params.eth);
|
let eth_client = EthereumRpcClient::new(eth_params);
|
||||||
let sub_client = async_std::task::block_on(SubstrateRpcClient::new(params.sub))
|
let sub_client = async_std::task::block_on(SubstrateRpcClient::new(sub_params, instance))
|
||||||
.map_err(|err| format!("Error starting Substrate client: {:?}", err))?;
|
.map_err(|err| format!("Error starting Substrate client: {:?}", err))?;
|
||||||
|
|
||||||
let eth_start_with_block_number = match eth_start_with_block_number {
|
let eth_start_with_block_number = match eth_start_with_block_number {
|
||||||
@@ -337,9 +345,9 @@ fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_wi
|
|||||||
EthereumTransactionsSource { client: eth_client },
|
EthereumTransactionsSource { client: eth_client },
|
||||||
SubstrateTransactionsTarget {
|
SubstrateTransactionsTarget {
|
||||||
client: sub_client,
|
client: sub_client,
|
||||||
sign_params: params.sub_sign,
|
sign_params: sub_sign,
|
||||||
},
|
},
|
||||||
params.metrics_params,
|
metrics_params,
|
||||||
futures::future::pending(),
|
futures::future::pending(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ use crate::ethereum_types::{CallRequest, U256};
|
|||||||
use crate::rpc::EthereumRpc;
|
use crate::rpc::EthereumRpc;
|
||||||
|
|
||||||
use bridge_node_runtime::exchange::LOCK_FUNDS_ADDRESS;
|
use bridge_node_runtime::exchange::LOCK_FUNDS_ADDRESS;
|
||||||
use hex_literal::hex;
|
|
||||||
use sp_bridge_eth_poa::{
|
use sp_bridge_eth_poa::{
|
||||||
signatures::{SecretKey, SignTransaction},
|
signatures::{SecretKey, SignTransaction},
|
||||||
UnsignedTransaction,
|
UnsignedTransaction,
|
||||||
@@ -31,7 +30,7 @@ use sp_bridge_eth_poa::{
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EthereumExchangeSubmitParams {
|
pub struct EthereumExchangeSubmitParams {
|
||||||
/// Ethereum connection params.
|
/// Ethereum connection params.
|
||||||
pub eth: EthereumConnectionParams,
|
pub eth_params: EthereumConnectionParams,
|
||||||
/// Ethereum signing params.
|
/// Ethereum signing params.
|
||||||
pub eth_sign: EthereumSigningParams,
|
pub eth_sign: EthereumSigningParams,
|
||||||
/// Ethereum signer nonce.
|
/// Ethereum signer nonce.
|
||||||
@@ -42,28 +41,24 @@ pub struct EthereumExchangeSubmitParams {
|
|||||||
pub sub_recipient: [u8; 32],
|
pub sub_recipient: [u8; 32],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EthereumExchangeSubmitParams {
|
|
||||||
fn default() -> Self {
|
|
||||||
EthereumExchangeSubmitParams {
|
|
||||||
eth: Default::default(),
|
|
||||||
eth_sign: Default::default(),
|
|
||||||
eth_nonce: None,
|
|
||||||
eth_amount: 1_000_000_000_000_000_000_u64.into(), // 1 ETH
|
|
||||||
sub_recipient: hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c"), // ferdie
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Submit single Ethereum -> Substrate exchange transaction.
|
/// Submit single Ethereum -> Substrate exchange transaction.
|
||||||
pub fn run(params: EthereumExchangeSubmitParams) {
|
pub fn run(params: EthereumExchangeSubmitParams) {
|
||||||
let mut local_pool = futures::executor::LocalPool::new();
|
let mut local_pool = futures::executor::LocalPool::new();
|
||||||
|
|
||||||
let result: Result<_, String> = local_pool.run_until(async move {
|
let EthereumExchangeSubmitParams {
|
||||||
let eth_client = EthereumRpcClient::new(params.eth);
|
eth_params,
|
||||||
|
eth_sign,
|
||||||
|
eth_nonce,
|
||||||
|
eth_amount,
|
||||||
|
sub_recipient,
|
||||||
|
} = params;
|
||||||
|
|
||||||
let eth_signer_address = params.eth_sign.signer.address();
|
let result: Result<_, String> = local_pool.run_until(async move {
|
||||||
let sub_recipient_encoded = params.sub_recipient;
|
let eth_client = EthereumRpcClient::new(eth_params);
|
||||||
let nonce = match params.eth_nonce {
|
|
||||||
|
let eth_signer_address = eth_sign.signer.address();
|
||||||
|
let sub_recipient_encoded = sub_recipient;
|
||||||
|
let nonce = match eth_nonce {
|
||||||
Some(eth_nonce) => eth_nonce,
|
Some(eth_nonce) => eth_nonce,
|
||||||
None => eth_client
|
None => eth_client
|
||||||
.account_nonce(eth_signer_address)
|
.account_nonce(eth_signer_address)
|
||||||
@@ -74,7 +69,7 @@ pub fn run(params: EthereumExchangeSubmitParams) {
|
|||||||
.estimate_gas(CallRequest {
|
.estimate_gas(CallRequest {
|
||||||
from: Some(eth_signer_address),
|
from: Some(eth_signer_address),
|
||||||
to: Some(LOCK_FUNDS_ADDRESS.into()),
|
to: Some(LOCK_FUNDS_ADDRESS.into()),
|
||||||
value: Some(params.eth_amount),
|
value: Some(eth_amount),
|
||||||
data: Some(sub_recipient_encoded.to_vec().into()),
|
data: Some(sub_recipient_encoded.to_vec().into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
@@ -82,16 +77,16 @@ pub fn run(params: EthereumExchangeSubmitParams) {
|
|||||||
.map_err(|err| format!("error estimating gas requirements: {:?}", err))?;
|
.map_err(|err| format!("error estimating gas requirements: {:?}", err))?;
|
||||||
let eth_tx_unsigned = UnsignedTransaction {
|
let eth_tx_unsigned = UnsignedTransaction {
|
||||||
nonce,
|
nonce,
|
||||||
gas_price: params.eth_sign.gas_price,
|
gas_price: eth_sign.gas_price,
|
||||||
gas,
|
gas,
|
||||||
to: Some(LOCK_FUNDS_ADDRESS.into()),
|
to: Some(LOCK_FUNDS_ADDRESS.into()),
|
||||||
value: params.eth_amount,
|
value: eth_amount,
|
||||||
payload: sub_recipient_encoded.to_vec(),
|
payload: sub_recipient_encoded.to_vec(),
|
||||||
};
|
};
|
||||||
let eth_tx_signed = eth_tx_unsigned.clone().sign_by(
|
let eth_tx_signed = eth_tx_unsigned.clone().sign_by(
|
||||||
&SecretKey::parse(params.eth_sign.signer.secret().as_fixed_bytes())
|
&SecretKey::parse(eth_sign.signer.secret().as_fixed_bytes())
|
||||||
.expect("key is accepted by secp256k1::KeyPair and thus is valid; qed"),
|
.expect("key is accepted by secp256k1::KeyPair and thus is valid; qed"),
|
||||||
Some(params.eth_sign.chain_id),
|
Some(eth_sign.chain_id),
|
||||||
);
|
);
|
||||||
eth_client
|
eth_client
|
||||||
.submit_transaction(eth_tx_signed)
|
.submit_transaction(eth_tx_signed)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
use crate::ethereum_client::{EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient};
|
use crate::ethereum_client::{EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient};
|
||||||
use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt};
|
use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt};
|
||||||
|
use crate::instances::BridgeInstance;
|
||||||
use crate::metrics::MetricsParams;
|
use crate::metrics::MetricsParams;
|
||||||
use crate::rpc::{EthereumRpc, SubstrateRpc};
|
use crate::rpc::{EthereumRpc, SubstrateRpc};
|
||||||
use crate::rpc_errors::RpcError;
|
use crate::rpc_errors::RpcError;
|
||||||
@@ -32,57 +33,45 @@ use crate::sync_types::{SourceHeader, SubmittedHeaders};
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use web3::types::H256;
|
use web3::types::H256;
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::{collections::HashSet, time::Duration};
|
use std::{collections::HashSet, time::Duration};
|
||||||
|
|
||||||
|
pub mod consts {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
/// Interval at which we check new Ethereum headers when we are synced/almost synced.
|
/// Interval at which we check new Ethereum headers when we are synced/almost synced.
|
||||||
const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10);
|
pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10);
|
||||||
/// Interval at which we check new Substrate blocks.
|
/// Interval at which we check new Substrate blocks.
|
||||||
const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5);
|
pub const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
/// Max number of headers in single submit transaction.
|
/// Max number of headers in single submit transaction.
|
||||||
const MAX_HEADERS_IN_SINGLE_SUBMIT: usize = 32;
|
pub const MAX_HEADERS_IN_SINGLE_SUBMIT: usize = 32;
|
||||||
/// Max total size of headers in single submit transaction. This only affects signed
|
/// Max total size of headers in single submit transaction. This only affects signed
|
||||||
/// submissions, when several headers are submitted at once. 4096 is the maximal **expected**
|
/// submissions, when several headers are submitted at once. 4096 is the maximal **expected**
|
||||||
/// size of the Ethereum header + transactions receipts (if they're required).
|
/// size of the Ethereum header + transactions receipts (if they're required).
|
||||||
const MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT: usize = MAX_HEADERS_IN_SINGLE_SUBMIT * 4096;
|
pub const MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT: usize = MAX_HEADERS_IN_SINGLE_SUBMIT * 4096;
|
||||||
/// Max Ethereum headers we want to have in all 'before-submitted' states.
|
/// Max Ethereum headers we want to have in all 'before-submitted' states.
|
||||||
const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 128;
|
pub const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 128;
|
||||||
/// Max Ethereum headers count we want to have in 'submitted' state.
|
/// Max Ethereum headers count we want to have in 'submitted' state.
|
||||||
const MAX_SUBMITTED_HEADERS: usize = 128;
|
pub const MAX_SUBMITTED_HEADERS: usize = 128;
|
||||||
/// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned).
|
/// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned).
|
||||||
const PRUNE_DEPTH: u32 = 4096;
|
pub const PRUNE_DEPTH: u32 = 4096;
|
||||||
|
}
|
||||||
|
|
||||||
/// Ethereum synchronization parameters.
|
/// Ethereum synchronization parameters.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EthereumSyncParams {
|
pub struct EthereumSyncParams {
|
||||||
/// Ethereum connection params.
|
/// Ethereum connection params.
|
||||||
pub eth: EthereumConnectionParams,
|
pub eth_params: EthereumConnectionParams,
|
||||||
/// Substrate connection params.
|
/// Substrate connection params.
|
||||||
pub sub: SubstrateConnectionParams,
|
pub sub_params: SubstrateConnectionParams,
|
||||||
/// Substrate signing params.
|
/// Substrate signing params.
|
||||||
pub sub_sign: SubstrateSigningParams,
|
pub sub_sign: SubstrateSigningParams,
|
||||||
/// Synchronization parameters.
|
/// Synchronization parameters.
|
||||||
pub sync_params: HeadersSyncParams,
|
pub sync_params: HeadersSyncParams,
|
||||||
/// Metrics parameters.
|
/// Metrics parameters.
|
||||||
pub metrics_params: Option<MetricsParams>,
|
pub metrics_params: Option<MetricsParams>,
|
||||||
}
|
/// Instance of the bridge pallet being synchronized.
|
||||||
|
pub instance: Box<dyn BridgeInstance>,
|
||||||
impl Default for EthereumSyncParams {
|
|
||||||
fn default() -> Self {
|
|
||||||
EthereumSyncParams {
|
|
||||||
eth: Default::default(),
|
|
||||||
sub: Default::default(),
|
|
||||||
sub_sign: Default::default(),
|
|
||||||
sync_params: HeadersSyncParams {
|
|
||||||
max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD,
|
|
||||||
max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS,
|
|
||||||
max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT,
|
|
||||||
max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT,
|
|
||||||
prune_depth: PRUNE_DEPTH,
|
|
||||||
target_tx_mode: TargetTransactionMode::Signed,
|
|
||||||
},
|
|
||||||
metrics_params: Some(Default::default()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ethereum client as headers source.
|
/// Ethereum client as headers source.
|
||||||
@@ -190,26 +179,33 @@ impl TargetClient<EthereumHeadersSyncPipeline> for SubstrateHeadersTarget {
|
|||||||
|
|
||||||
/// Run Ethereum headers synchronization.
|
/// Run Ethereum headers synchronization.
|
||||||
pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> {
|
pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> {
|
||||||
let sub_params = params.clone();
|
let EthereumSyncParams {
|
||||||
|
eth_params,
|
||||||
|
sub_params,
|
||||||
|
sub_sign,
|
||||||
|
sync_params,
|
||||||
|
metrics_params,
|
||||||
|
instance,
|
||||||
|
} = params;
|
||||||
|
|
||||||
let eth_client = EthereumRpcClient::new(params.eth);
|
let eth_client = EthereumRpcClient::new(eth_params);
|
||||||
let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params.sub).await })?;
|
let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params, instance).await })?;
|
||||||
|
|
||||||
let sign_sub_transactions = match params.sync_params.target_tx_mode {
|
let sign_sub_transactions = match sync_params.target_tx_mode {
|
||||||
TargetTransactionMode::Signed | TargetTransactionMode::Backup => true,
|
TargetTransactionMode::Signed | TargetTransactionMode::Backup => true,
|
||||||
TargetTransactionMode::Unsigned => false,
|
TargetTransactionMode::Unsigned => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let source = EthereumHeadersSource::new(eth_client);
|
let source = EthereumHeadersSource::new(eth_client);
|
||||||
let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, params.sub_sign);
|
let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, sub_sign);
|
||||||
|
|
||||||
crate::sync_loop::run(
|
crate::sync_loop::run(
|
||||||
source,
|
source,
|
||||||
ETHEREUM_TICK_INTERVAL,
|
consts::ETHEREUM_TICK_INTERVAL,
|
||||||
target,
|
target,
|
||||||
SUBSTRATE_TICK_INTERVAL,
|
consts::SUBSTRATE_TICK_INTERVAL,
|
||||||
params.sync_params,
|
sync_params,
|
||||||
params.metrics_params,
|
metrics_params,
|
||||||
futures::future::pending(),
|
futures::future::pending(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity Bridges Common.
|
||||||
|
|
||||||
|
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// 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/>.
|
||||||
|
|
||||||
|
//! The PoA Bridge Pallet provides a way to include multiple instances of itself in a runtime. When
|
||||||
|
//! synchronizing a Substrate chain which can include multiple instances of the bridge pallet we
|
||||||
|
//! must somehow decide which of the instances to sync.
|
||||||
|
//!
|
||||||
|
//! Note that each instance of the bridge pallet is coupled with an instance of the currency exchange
|
||||||
|
//! pallet. We must also have a way to create `Call`s for the correct currency exchange instance.
|
||||||
|
//!
|
||||||
|
//! This module helps by preparing the correct `Call`s for each of the different pallet instances.
|
||||||
|
|
||||||
|
use crate::ethereum_types::QueuedEthereumHeader;
|
||||||
|
use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts};
|
||||||
|
|
||||||
|
use bridge_node_runtime::exchange::EthereumTransactionInclusionProof as Proof;
|
||||||
|
use bridge_node_runtime::Call;
|
||||||
|
|
||||||
|
/// Interface for `Calls` which are needed to correctly sync the bridge.
|
||||||
|
///
|
||||||
|
/// Each instance of the bridge and currency exchange pallets in the bridge runtime requires similar
|
||||||
|
/// but slightly different `Call` in order to be synchronized.
|
||||||
|
pub trait BridgeInstance: Send + Sync + std::fmt::Debug {
|
||||||
|
/// Used to build a `Call` for importing signed headers to a Substrate runtime.
|
||||||
|
fn build_signed_header_call(&self, headers: Vec<QueuedEthereumHeader>) -> Call;
|
||||||
|
/// Used to build a `Call` for importing an unsigned header to a Substrate runtime.
|
||||||
|
fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call;
|
||||||
|
/// Used to build a `Call` for importing peer transactions to a Substrate runtime.
|
||||||
|
fn build_currency_exchange_call(&self, proof: Proof) -> Call;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Corresponds to the Rialto instance used in the bridge runtime.
|
||||||
|
#[derive(Default, Clone, Debug)]
|
||||||
|
pub struct Rialto;
|
||||||
|
|
||||||
|
impl BridgeInstance for Rialto {
|
||||||
|
fn build_signed_header_call(&self, headers: Vec<QueuedEthereumHeader>) -> Call {
|
||||||
|
let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_signed_headers(
|
||||||
|
headers
|
||||||
|
.into_iter()
|
||||||
|
.map(|header| {
|
||||||
|
(
|
||||||
|
into_substrate_ethereum_header(header.header()),
|
||||||
|
into_substrate_ethereum_receipts(header.extra()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
|
||||||
|
bridge_node_runtime::Call::BridgeRialto(pallet_call)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call {
|
||||||
|
let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_unsigned_header(
|
||||||
|
into_substrate_ethereum_header(header.header()),
|
||||||
|
into_substrate_ethereum_receipts(header.extra()),
|
||||||
|
);
|
||||||
|
|
||||||
|
bridge_node_runtime::Call::BridgeRialto(pallet_call)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_currency_exchange_call(&self, proof: Proof) -> Call {
|
||||||
|
let pallet_call = bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof);
|
||||||
|
bridge_node_runtime::Call::BridgeRialtoCurrencyExchange(pallet_call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Corresponds to the Kovan instance used in the bridge runtime.
|
||||||
|
#[derive(Default, Clone, Debug)]
|
||||||
|
pub struct Kovan;
|
||||||
|
|
||||||
|
impl BridgeInstance for Kovan {
|
||||||
|
fn build_signed_header_call(&self, headers: Vec<QueuedEthereumHeader>) -> Call {
|
||||||
|
let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_signed_headers(
|
||||||
|
headers
|
||||||
|
.into_iter()
|
||||||
|
.map(|header| {
|
||||||
|
(
|
||||||
|
into_substrate_ethereum_header(header.header()),
|
||||||
|
into_substrate_ethereum_receipts(header.extra()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
|
||||||
|
bridge_node_runtime::Call::BridgeKovan(pallet_call)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call {
|
||||||
|
let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_unsigned_header(
|
||||||
|
into_substrate_ethereum_header(header.header()),
|
||||||
|
into_substrate_ethereum_receipts(header.extra()),
|
||||||
|
);
|
||||||
|
|
||||||
|
bridge_node_runtime::Call::BridgeKovan(pallet_call)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_currency_exchange_call(&self, proof: Proof) -> Call {
|
||||||
|
let pallet_call = bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof);
|
||||||
|
bridge_node_runtime::Call::BridgeKovanCurrencyExchange(pallet_call)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ mod exchange;
|
|||||||
mod exchange_loop;
|
mod exchange_loop;
|
||||||
mod exchange_loop_metrics;
|
mod exchange_loop_metrics;
|
||||||
mod headers;
|
mod headers;
|
||||||
|
mod instances;
|
||||||
mod metrics;
|
mod metrics;
|
||||||
mod rpc;
|
mod rpc;
|
||||||
mod rpc_errors;
|
mod rpc_errors;
|
||||||
@@ -40,12 +41,19 @@ mod sync_types;
|
|||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use ethereum_client::{EthereumConnectionParams, EthereumSigningParams};
|
use ethereum_client::{EthereumConnectionParams, EthereumSigningParams};
|
||||||
|
use ethereum_deploy_contract::EthereumDeployContractParams;
|
||||||
|
use ethereum_exchange::EthereumExchangeParams;
|
||||||
|
use ethereum_exchange_submit::EthereumExchangeSubmitParams;
|
||||||
use ethereum_sync_loop::EthereumSyncParams;
|
use ethereum_sync_loop::EthereumSyncParams;
|
||||||
|
use hex_literal::hex;
|
||||||
|
use instances::{BridgeInstance, Kovan, Rialto};
|
||||||
use parity_crypto::publickey::{KeyPair, Secret};
|
use parity_crypto::publickey::{KeyPair, Secret};
|
||||||
use sp_core::crypto::Pair;
|
use sp_core::crypto::Pair;
|
||||||
use std::io::Write;
|
|
||||||
use substrate_client::{SubstrateConnectionParams, SubstrateSigningParams};
|
use substrate_client::{SubstrateConnectionParams, SubstrateSigningParams};
|
||||||
use substrate_sync_loop::SubstrateSyncParams;
|
use substrate_sync_loop::SubstrateSyncParams;
|
||||||
|
use sync::HeadersSyncParams;
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
initialize();
|
initialize();
|
||||||
@@ -210,110 +218,134 @@ fn substrate_signing_params(matches: &clap::ArgMatches) -> Result<SubstrateSigni
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result<EthereumSyncParams, String> {
|
fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result<EthereumSyncParams, String> {
|
||||||
let mut eth_sync_params = EthereumSyncParams::default();
|
let mut sync_params = HeadersSyncParams::ethereum_sync_default();
|
||||||
eth_sync_params.eth = ethereum_connection_params(matches)?;
|
|
||||||
eth_sync_params.sub = substrate_connection_params(matches)?;
|
|
||||||
eth_sync_params.sub_sign = substrate_signing_params(matches)?;
|
|
||||||
eth_sync_params.metrics_params = metrics_params(matches)?;
|
|
||||||
|
|
||||||
match matches.value_of("sub-tx-mode") {
|
match matches.value_of("sub-tx-mode") {
|
||||||
Some("signed") => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Signed,
|
Some("signed") => sync_params.target_tx_mode = sync::TargetTransactionMode::Signed,
|
||||||
Some("unsigned") => {
|
Some("unsigned") => {
|
||||||
eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Unsigned;
|
sync_params.target_tx_mode = sync::TargetTransactionMode::Unsigned;
|
||||||
|
|
||||||
// tx pool won't accept too much unsigned transactions
|
// tx pool won't accept too much unsigned transactions
|
||||||
eth_sync_params.sync_params.max_headers_in_submitted_status = 10;
|
sync_params.max_headers_in_submitted_status = 10;
|
||||||
}
|
}
|
||||||
Some("backup") => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Backup,
|
Some("backup") => sync_params.target_tx_mode = sync::TargetTransactionMode::Backup,
|
||||||
Some(mode) => return Err(format!("Invalid sub-tx-mode: {}", mode)),
|
Some(mode) => return Err(format!("Invalid sub-tx-mode: {}", mode)),
|
||||||
None => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Signed,
|
None => sync_params.target_tx_mode = sync::TargetTransactionMode::Signed,
|
||||||
}
|
}
|
||||||
|
|
||||||
log::debug!(target: "bridge", "Ethereum sync params: {:?}", eth_sync_params);
|
let params = EthereumSyncParams {
|
||||||
|
eth_params: ethereum_connection_params(matches)?,
|
||||||
|
sub_params: substrate_connection_params(matches)?,
|
||||||
|
sub_sign: substrate_signing_params(matches)?,
|
||||||
|
metrics_params: metrics_params(matches)?,
|
||||||
|
instance: instance_params(matches)?,
|
||||||
|
sync_params,
|
||||||
|
};
|
||||||
|
|
||||||
Ok(eth_sync_params)
|
log::debug!(target: "bridge", "Ethereum sync params: {:?}", params);
|
||||||
|
|
||||||
|
Ok(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn substrate_sync_params(matches: &clap::ArgMatches) -> Result<SubstrateSyncParams, String> {
|
fn substrate_sync_params(matches: &clap::ArgMatches) -> Result<SubstrateSyncParams, String> {
|
||||||
let mut sub_sync_params = SubstrateSyncParams::default();
|
let eth_contract_address: ethereum_types::Address = if let Some(eth_contract) = matches.value_of("eth-contract") {
|
||||||
sub_sync_params.eth = ethereum_connection_params(matches)?;
|
eth_contract.parse().map_err(|e| format!("{}", e))?
|
||||||
sub_sync_params.eth_sign = ethereum_signing_params(matches)?;
|
} else {
|
||||||
sub_sync_params.sub = substrate_connection_params(matches)?;
|
"731a10897d267e19b34503ad902d0a29173ba4b1"
|
||||||
sub_sync_params.metrics_params = metrics_params(matches)?;
|
|
||||||
|
|
||||||
if let Some(eth_contract) = matches.value_of("eth-contract") {
|
|
||||||
sub_sync_params.eth_contract_address = eth_contract.parse().map_err(|e| format!("{}", e))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
log::debug!(target: "bridge", "Substrate sync params: {:?}", sub_sync_params);
|
|
||||||
|
|
||||||
Ok(sub_sync_params)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ethereum_deploy_contract_params(
|
|
||||||
matches: &clap::ArgMatches,
|
|
||||||
) -> Result<ethereum_deploy_contract::EthereumDeployContractParams, String> {
|
|
||||||
let mut eth_deploy_params = ethereum_deploy_contract::EthereumDeployContractParams::default();
|
|
||||||
eth_deploy_params.eth = ethereum_connection_params(matches)?;
|
|
||||||
eth_deploy_params.eth_sign = ethereum_signing_params(matches)?;
|
|
||||||
eth_deploy_params.sub = substrate_connection_params(matches)?;
|
|
||||||
|
|
||||||
if let Some(eth_contract_code) = matches.value_of("eth-contract-code") {
|
|
||||||
eth_deploy_params.eth_contract_code =
|
|
||||||
hex::decode(ð_contract_code).map_err(|e| format!("Failed to parse eth-contract-code: {}", e))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
log::debug!(target: "bridge", "Deploy params: {:?}", eth_deploy_params);
|
|
||||||
|
|
||||||
Ok(eth_deploy_params)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ethereum_exchange_submit_params(
|
|
||||||
matches: &clap::ArgMatches,
|
|
||||||
) -> Result<ethereum_exchange_submit::EthereumExchangeSubmitParams, String> {
|
|
||||||
let mut params = ethereum_exchange_submit::EthereumExchangeSubmitParams::default();
|
|
||||||
params.eth = ethereum_connection_params(matches)?;
|
|
||||||
params.eth_sign = ethereum_signing_params(matches)?;
|
|
||||||
|
|
||||||
if let Some(eth_nonce) = matches.value_of("eth-nonce") {
|
|
||||||
params.eth_nonce = Some(
|
|
||||||
ethereum_types::U256::from_dec_str(ð_nonce).map_err(|e| format!("Failed to parse eth-nonce: {}", e))?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if let Some(eth_amount) = matches.value_of("eth-amount") {
|
|
||||||
params.eth_amount = eth_amount
|
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|e| format!("Failed to parse eth-amount: {}", e))?;
|
.expect("address is hardcoded, thus valid; qed")
|
||||||
|
};
|
||||||
|
|
||||||
|
let params = SubstrateSyncParams {
|
||||||
|
sub_params: substrate_connection_params(matches)?,
|
||||||
|
eth_params: ethereum_connection_params(matches)?,
|
||||||
|
eth_sign: ethereum_signing_params(matches)?,
|
||||||
|
metrics_params: metrics_params(matches)?,
|
||||||
|
instance: instance_params(matches)?,
|
||||||
|
sync_params: HeadersSyncParams::substrate_sync_default(),
|
||||||
|
eth_contract_address,
|
||||||
|
};
|
||||||
|
|
||||||
|
log::debug!(target: "bridge", "Substrate sync params: {:?}", params);
|
||||||
|
|
||||||
|
Ok(params)
|
||||||
}
|
}
|
||||||
if let Some(sub_recipient) = matches.value_of("sub-recipient") {
|
|
||||||
params.sub_recipient = hex::decode(&sub_recipient)
|
fn ethereum_deploy_contract_params(matches: &clap::ArgMatches) -> Result<EthereumDeployContractParams, String> {
|
||||||
|
let eth_contract_code = if let Some(eth_contract_code) = matches.value_of("eth-contract-code") {
|
||||||
|
hex::decode(ð_contract_code).map_err(|e| format!("Failed to parse eth-contract-code: {}", e))?
|
||||||
|
} else {
|
||||||
|
hex::decode(include_str!("../res/substrate-bridge-bytecode.hex")).expect("code is hardcoded, thus valid; qed")
|
||||||
|
};
|
||||||
|
|
||||||
|
let params = EthereumDeployContractParams {
|
||||||
|
eth_params: ethereum_connection_params(matches)?,
|
||||||
|
eth_sign: ethereum_signing_params(matches)?,
|
||||||
|
sub_params: substrate_connection_params(matches)?,
|
||||||
|
instance: instance_params(matches)?,
|
||||||
|
sub_initial_authorities_set_id: None,
|
||||||
|
sub_initial_authorities_set: None,
|
||||||
|
sub_initial_header: None,
|
||||||
|
eth_contract_code,
|
||||||
|
};
|
||||||
|
|
||||||
|
log::debug!(target: "bridge", "Deploy params: {:?}", params);
|
||||||
|
|
||||||
|
Ok(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ethereum_exchange_submit_params(matches: &clap::ArgMatches) -> Result<EthereumExchangeSubmitParams, String> {
|
||||||
|
let eth_nonce = if let Some(eth_nonce) = matches.value_of("eth-nonce") {
|
||||||
|
Some(ethereum_types::U256::from_dec_str(ð_nonce).map_err(|e| format!("Failed to parse eth-nonce: {}", e))?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let eth_amount = if let Some(eth_amount) = matches.value_of("eth-amount") {
|
||||||
|
eth_amount
|
||||||
|
.parse()
|
||||||
|
.map_err(|e| format!("Failed to parse eth-amount: {}", e))?
|
||||||
|
} else {
|
||||||
|
// This is in Wei, represents 1 ETH
|
||||||
|
1_000_000_000_000_000_000_u64.into()
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is the well-known Substrate account of Ferdie
|
||||||
|
let default_recepient = hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c");
|
||||||
|
|
||||||
|
let sub_recipient = if let Some(sub_recipient) = matches.value_of("sub-recipient") {
|
||||||
|
hex::decode(&sub_recipient)
|
||||||
.map_err(|err| err.to_string())
|
.map_err(|err| err.to_string())
|
||||||
.and_then(|vsub_recipient| {
|
.and_then(|vsub_recipient| {
|
||||||
let expected_len = params.sub_recipient.len();
|
let expected_len = default_recepient.len();
|
||||||
if expected_len != vsub_recipient.len() {
|
if expected_len != vsub_recipient.len() {
|
||||||
Err(format!("invalid length. Expected {} bytes", expected_len))
|
Err(format!("invalid length. Expected {} bytes", expected_len))
|
||||||
} else {
|
} else {
|
||||||
let mut sub_recipient = params.sub_recipient;
|
let mut sub_recipient = default_recepient;
|
||||||
sub_recipient.copy_from_slice(&vsub_recipient[..expected_len]);
|
sub_recipient.copy_from_slice(&vsub_recipient[..expected_len]);
|
||||||
Ok(sub_recipient)
|
Ok(sub_recipient)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map_err(|e| format!("Failed to parse sub-recipient: {}", e))?;
|
.map_err(|e| format!("Failed to parse sub-recipient: {}", e))?
|
||||||
}
|
} else {
|
||||||
|
default_recepient
|
||||||
|
};
|
||||||
|
|
||||||
|
let params = EthereumExchangeSubmitParams {
|
||||||
|
eth_params: ethereum_connection_params(matches)?,
|
||||||
|
eth_sign: ethereum_signing_params(matches)?,
|
||||||
|
eth_nonce,
|
||||||
|
eth_amount,
|
||||||
|
sub_recipient,
|
||||||
|
};
|
||||||
|
|
||||||
log::debug!(target: "bridge", "Submit Ethereum exchange tx params: {:?}", params);
|
log::debug!(target: "bridge", "Submit Ethereum exchange tx params: {:?}", params);
|
||||||
|
|
||||||
Ok(params)
|
Ok(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result<ethereum_exchange::EthereumExchangeParams, String> {
|
fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result<EthereumExchangeParams, String> {
|
||||||
let mut params = ethereum_exchange::EthereumExchangeParams::default();
|
let mode = match matches.value_of("eth-tx-hash") {
|
||||||
params.eth = ethereum_connection_params(matches)?;
|
|
||||||
params.sub = substrate_connection_params(matches)?;
|
|
||||||
params.sub_sign = substrate_signing_params(matches)?;
|
|
||||||
params.metrics_params = metrics_params(matches)?;
|
|
||||||
|
|
||||||
params.mode = match matches.value_of("eth-tx-hash") {
|
|
||||||
Some(eth_tx_hash) => ethereum_exchange::ExchangeRelayMode::Single(
|
Some(eth_tx_hash) => ethereum_exchange::ExchangeRelayMode::Single(
|
||||||
eth_tx_hash
|
eth_tx_hash
|
||||||
.parse()
|
.parse()
|
||||||
@@ -329,6 +361,15 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result<ethereum_excha
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let params = EthereumExchangeParams {
|
||||||
|
eth_params: ethereum_connection_params(matches)?,
|
||||||
|
sub_params: substrate_connection_params(matches)?,
|
||||||
|
sub_sign: substrate_signing_params(matches)?,
|
||||||
|
metrics_params: metrics_params(matches)?,
|
||||||
|
instance: instance_params(matches)?,
|
||||||
|
mode,
|
||||||
|
};
|
||||||
|
|
||||||
log::debug!(target: "bridge", "Ethereum exchange params: {:?}", params);
|
log::debug!(target: "bridge", "Ethereum exchange params: {:?}", params);
|
||||||
|
|
||||||
Ok(params)
|
Ok(params)
|
||||||
@@ -352,3 +393,17 @@ fn metrics_params(matches: &clap::ArgMatches) -> Result<Option<metrics::MetricsP
|
|||||||
|
|
||||||
Ok(Some(metrics_params))
|
Ok(Some(metrics_params))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn instance_params(matches: &clap::ArgMatches) -> Result<Box<dyn BridgeInstance>, String> {
|
||||||
|
let instance: Box<dyn BridgeInstance> = if let Some(instance) = matches.value_of("sub-pallet-instance") {
|
||||||
|
match instance.to_lowercase().as_str() {
|
||||||
|
"rialto" => Box::new(Rialto::default()),
|
||||||
|
"kovan" => Box::new(Kovan::default()),
|
||||||
|
_ => return Err("Unsupported bridge pallet instance".to_string()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("CLI config enforces a default instance, can never be None")
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(instance)
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,12 +15,10 @@
|
|||||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::ethereum_types::{Bytes, EthereumHeaderId, QueuedEthereumHeader, H256};
|
use crate::ethereum_types::{Bytes, EthereumHeaderId, QueuedEthereumHeader, H256};
|
||||||
|
use crate::instances::BridgeInstance;
|
||||||
use crate::rpc::{Substrate, SubstrateRpc};
|
use crate::rpc::{Substrate, SubstrateRpc};
|
||||||
use crate::rpc_errors::RpcError;
|
use crate::rpc_errors::RpcError;
|
||||||
use crate::substrate_types::{
|
use crate::substrate_types::{Hash, Header as SubstrateHeader, Number, SignedBlock as SignedSubstrateBlock};
|
||||||
into_substrate_ethereum_header, into_substrate_ethereum_receipts, Hash, Header as SubstrateHeader, Number,
|
|
||||||
SignedBlock as SignedSubstrateBlock,
|
|
||||||
};
|
|
||||||
use crate::sync_types::{HeaderId, SubmittedHeaders};
|
use crate::sync_types::{HeaderId, SubmittedHeaders};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@@ -89,11 +87,13 @@ pub struct SubstrateRpcClient {
|
|||||||
client: Client,
|
client: Client,
|
||||||
/// Genesis block hash.
|
/// Genesis block hash.
|
||||||
genesis_hash: H256,
|
genesis_hash: H256,
|
||||||
|
/// Instance of the bridge pallet being synchronized.
|
||||||
|
instance: Box<dyn BridgeInstance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SubstrateRpcClient {
|
impl SubstrateRpcClient {
|
||||||
/// Returns client that is able to call RPCs on Substrate node.
|
/// Returns client that is able to call RPCs on Substrate node.
|
||||||
pub async fn new(params: SubstrateConnectionParams) -> Result<Self> {
|
pub async fn new(params: SubstrateConnectionParams, instance: Box<dyn BridgeInstance>) -> Result<Self> {
|
||||||
let uri = format!("http://{}:{}", params.host, params.port);
|
let uri = format!("http://{}:{}", params.host, params.port);
|
||||||
let transport = HttpTransportClient::new(&uri);
|
let transport = HttpTransportClient::new(&uri);
|
||||||
let raw_client = RawClient::new(transport);
|
let raw_client = RawClient::new(transport);
|
||||||
@@ -102,7 +102,11 @@ impl SubstrateRpcClient {
|
|||||||
let number: Number = Zero::zero();
|
let number: Number = Zero::zero();
|
||||||
let genesis_hash = Substrate::chain_get_block_hash(&client, number).await?;
|
let genesis_hash = Substrate::chain_get_block_hash(&client, number).await?;
|
||||||
|
|
||||||
Ok(Self { client, genesis_hash })
|
Ok(Self {
|
||||||
|
client,
|
||||||
|
genesis_hash,
|
||||||
|
instance,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +252,8 @@ impl SubmitEthereumHeaders for SubstrateRpcClient {
|
|||||||
let account_id = params.signer.public().as_array_ref().clone().into();
|
let account_id = params.signer.public().as_array_ref().clone().into();
|
||||||
let nonce = self.next_account_index(account_id).await?;
|
let nonce = self.next_account_index(account_id).await?;
|
||||||
|
|
||||||
let transaction = create_signed_submit_transaction(headers, ¶ms.signer, nonce, self.genesis_hash);
|
let call = self.instance.build_signed_header_call(headers);
|
||||||
|
let transaction = create_signed_submit_transaction(call, ¶ms.signer, nonce, self.genesis_hash);
|
||||||
let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?;
|
let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -276,9 +281,13 @@ impl SubmitEthereumHeaders for SubstrateRpcClient {
|
|||||||
) -> SubmittedHeaders<EthereumHeaderId, RpcError> {
|
) -> SubmittedHeaders<EthereumHeaderId, RpcError> {
|
||||||
let mut ids = headers.iter().map(|header| header.id()).collect::<VecDeque<_>>();
|
let mut ids = headers.iter().map(|header| header.id()).collect::<VecDeque<_>>();
|
||||||
let mut submitted_headers = SubmittedHeaders::default();
|
let mut submitted_headers = SubmittedHeaders::default();
|
||||||
|
|
||||||
for header in headers {
|
for header in headers {
|
||||||
let id = ids.pop_front().expect("both collections have same size; qed");
|
let id = ids.pop_front().expect("both collections have same size; qed");
|
||||||
let transaction = create_unsigned_submit_transaction(header);
|
|
||||||
|
let call = self.instance.build_unsigned_header_call(header);
|
||||||
|
let transaction = create_unsigned_submit_transaction(call);
|
||||||
|
|
||||||
match self.submit_extrinsic(Bytes(transaction.encode())).await {
|
match self.submit_extrinsic(Bytes(transaction.encode())).await {
|
||||||
Ok(_) => submitted_headers.submitted.push(id),
|
Ok(_) => submitted_headers.submitted.push(id),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
@@ -335,15 +344,9 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient {
|
|||||||
let account_id = params.signer.public().as_array_ref().clone().into();
|
let account_id = params.signer.public().as_array_ref().clone().into();
|
||||||
let nonce = self.next_account_index(account_id).await?;
|
let nonce = self.next_account_index(account_id).await?;
|
||||||
|
|
||||||
let transaction = create_signed_transaction(
|
let call = self.instance.build_currency_exchange_call(proof);
|
||||||
// TODO [#209]: Change so that that it's dynamic
|
let transaction = create_signed_transaction(call, ¶ms.signer, nonce, self.genesis_hash);
|
||||||
bridge_node_runtime::Call::BridgeRialtoCurrencyExchange(
|
|
||||||
bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof),
|
|
||||||
),
|
|
||||||
¶ms.signer,
|
|
||||||
nonce,
|
|
||||||
self.genesis_hash,
|
|
||||||
);
|
|
||||||
let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?;
|
let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -351,40 +354,17 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient {
|
|||||||
|
|
||||||
/// Create signed Substrate transaction for submitting Ethereum headers.
|
/// Create signed Substrate transaction for submitting Ethereum headers.
|
||||||
fn create_signed_submit_transaction(
|
fn create_signed_submit_transaction(
|
||||||
headers: Vec<QueuedEthereumHeader>,
|
signed_call: bridge_node_runtime::Call,
|
||||||
signer: &sp_core::sr25519::Pair,
|
signer: &sp_core::sr25519::Pair,
|
||||||
index: node_primitives::Index,
|
index: node_primitives::Index,
|
||||||
genesis_hash: H256,
|
genesis_hash: H256,
|
||||||
) -> bridge_node_runtime::UncheckedExtrinsic {
|
) -> bridge_node_runtime::UncheckedExtrinsic {
|
||||||
create_signed_transaction(
|
create_signed_transaction(signed_call, signer, index, genesis_hash)
|
||||||
// TODO [#209]: Change so that that it's dynamic
|
|
||||||
bridge_node_runtime::Call::BridgeRialto(bridge_node_runtime::BridgeEthPoACall::import_signed_headers(
|
|
||||||
headers
|
|
||||||
.into_iter()
|
|
||||||
.map(|header| {
|
|
||||||
(
|
|
||||||
into_substrate_ethereum_header(header.header()),
|
|
||||||
into_substrate_ethereum_receipts(header.extra()),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
)),
|
|
||||||
signer,
|
|
||||||
index,
|
|
||||||
genesis_hash,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create unsigned Substrate transaction for submitting Ethereum header.
|
/// Create unsigned Substrate transaction for submitting Ethereum header.
|
||||||
fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_node_runtime::UncheckedExtrinsic {
|
fn create_unsigned_submit_transaction(call: bridge_node_runtime::Call) -> bridge_node_runtime::UncheckedExtrinsic {
|
||||||
let function =
|
bridge_node_runtime::UncheckedExtrinsic::new_unsigned(call)
|
||||||
// TODO [#209]: Change so that that it's dynamic
|
|
||||||
bridge_node_runtime::Call::BridgeRialto(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header(
|
|
||||||
into_substrate_ethereum_header(header.header()),
|
|
||||||
into_substrate_ethereum_receipts(header.extra()),
|
|
||||||
));
|
|
||||||
|
|
||||||
bridge_node_runtime::UncheckedExtrinsic::new_unsigned(function)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create signed Substrate transaction.
|
/// Create signed Substrate transaction.
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use crate::ethereum_client::{
|
|||||||
EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams,
|
EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams,
|
||||||
};
|
};
|
||||||
use crate::ethereum_types::Address;
|
use crate::ethereum_types::Address;
|
||||||
|
use crate::instances::BridgeInstance;
|
||||||
use crate::metrics::MetricsParams;
|
use crate::metrics::MetricsParams;
|
||||||
use crate::rpc::SubstrateRpc;
|
use crate::rpc::SubstrateRpc;
|
||||||
use crate::rpc_errors::RpcError;
|
use crate::rpc_errors::RpcError;
|
||||||
@@ -27,66 +28,47 @@ use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient};
|
|||||||
use crate::substrate_types::{
|
use crate::substrate_types::{
|
||||||
GrandpaJustification, Hash, Header, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline,
|
GrandpaJustification, Hash, Header, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline,
|
||||||
};
|
};
|
||||||
use crate::sync::{HeadersSyncParams, TargetTransactionMode};
|
use crate::sync::HeadersSyncParams;
|
||||||
use crate::sync_loop::{SourceClient, TargetClient};
|
use crate::sync_loop::{SourceClient, TargetClient};
|
||||||
use crate::sync_types::{SourceHeader, SubmittedHeaders};
|
use crate::sync_types::{SourceHeader, SubmittedHeaders};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::{collections::HashSet, time::Duration};
|
use std::{collections::HashSet, time::Duration};
|
||||||
|
|
||||||
|
pub mod consts {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
/// Interval at which we check new Substrate headers when we are synced/almost synced.
|
/// Interval at which we check new Substrate headers when we are synced/almost synced.
|
||||||
const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(10);
|
pub const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(10);
|
||||||
/// Interval at which we check new Ethereum blocks.
|
/// Interval at which we check new Ethereum blocks.
|
||||||
const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(5);
|
pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
/// Max Ethereum headers we want to have in all 'before-submitted' states.
|
/// Max Ethereum headers we want to have in all 'before-submitted' states.
|
||||||
const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8;
|
pub const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8;
|
||||||
/// Max Ethereum headers count we want to have in 'submitted' state.
|
/// Max Ethereum headers count we want to have in 'submitted' state.
|
||||||
const MAX_SUBMITTED_HEADERS: usize = 1;
|
pub const MAX_SUBMITTED_HEADERS: usize = 1;
|
||||||
/// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned).
|
/// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned).
|
||||||
const PRUNE_DEPTH: u32 = 256;
|
pub const PRUNE_DEPTH: u32 = 256;
|
||||||
|
}
|
||||||
|
|
||||||
/// Substrate synchronization parameters.
|
/// Substrate synchronization parameters.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct SubstrateSyncParams {
|
pub struct SubstrateSyncParams {
|
||||||
|
/// Substrate connection params.
|
||||||
|
pub sub_params: SubstrateConnectionParams,
|
||||||
/// Ethereum connection params.
|
/// Ethereum connection params.
|
||||||
pub eth: EthereumConnectionParams,
|
pub eth_params: EthereumConnectionParams,
|
||||||
/// Ethereum signing params.
|
/// Ethereum signing params.
|
||||||
pub eth_sign: EthereumSigningParams,
|
pub eth_sign: EthereumSigningParams,
|
||||||
/// Ethereum bridge contract address.
|
/// Ethereum bridge contract address.
|
||||||
pub eth_contract_address: Address,
|
pub eth_contract_address: Address,
|
||||||
/// Substrate connection params.
|
|
||||||
pub sub: SubstrateConnectionParams,
|
|
||||||
/// Synchronization parameters.
|
/// Synchronization parameters.
|
||||||
pub sync_params: HeadersSyncParams,
|
pub sync_params: HeadersSyncParams,
|
||||||
/// Metrics parameters.
|
/// Metrics parameters.
|
||||||
pub metrics_params: Option<MetricsParams>,
|
pub metrics_params: Option<MetricsParams>,
|
||||||
}
|
/// Instance of the bridge pallet being synchronized.
|
||||||
|
pub instance: Box<dyn BridgeInstance>,
|
||||||
impl Default for SubstrateSyncParams {
|
|
||||||
fn default() -> Self {
|
|
||||||
SubstrateSyncParams {
|
|
||||||
eth: Default::default(),
|
|
||||||
eth_sign: Default::default(),
|
|
||||||
// the address 0x731a10897d267e19b34503ad902d0a29173ba4b1 is the address
|
|
||||||
// of the contract that is deployed by default signer and 0 nonce
|
|
||||||
eth_contract_address: "731a10897d267e19b34503ad902d0a29173ba4b1"
|
|
||||||
.parse()
|
|
||||||
.expect("address is hardcoded, thus valid; qed"),
|
|
||||||
sub: Default::default(),
|
|
||||||
sync_params: HeadersSyncParams {
|
|
||||||
max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD,
|
|
||||||
max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS,
|
|
||||||
// since we always have single Substrate header in separate Ethereum transaction,
|
|
||||||
// all max_**_in_single_submit aren't important here
|
|
||||||
max_headers_in_single_submit: 4,
|
|
||||||
max_headers_size_in_single_submit: std::usize::MAX,
|
|
||||||
prune_depth: PRUNE_DEPTH,
|
|
||||||
target_tx_mode: TargetTransactionMode::Signed,
|
|
||||||
},
|
|
||||||
metrics_params: Some(Default::default()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Substrate client as headers source.
|
/// Substrate client as headers source.
|
||||||
@@ -199,21 +181,29 @@ impl TargetClient<SubstrateHeadersSyncPipeline> for EthereumHeadersTarget {
|
|||||||
|
|
||||||
/// Run Substrate headers synchronization.
|
/// Run Substrate headers synchronization.
|
||||||
pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> {
|
pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> {
|
||||||
let sub_params = params.clone();
|
let SubstrateSyncParams {
|
||||||
|
sub_params,
|
||||||
|
eth_params,
|
||||||
|
eth_sign,
|
||||||
|
eth_contract_address,
|
||||||
|
sync_params,
|
||||||
|
metrics_params,
|
||||||
|
instance,
|
||||||
|
} = params;
|
||||||
|
|
||||||
let eth_client = EthereumRpcClient::new(params.eth);
|
let eth_client = EthereumRpcClient::new(eth_params);
|
||||||
let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params.sub).await })?;
|
let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params, instance).await })?;
|
||||||
|
|
||||||
let target = EthereumHeadersTarget::new(eth_client, params.eth_contract_address, params.eth_sign);
|
let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign);
|
||||||
let source = SubstrateHeadersSource::new(sub_client);
|
let source = SubstrateHeadersSource::new(sub_client);
|
||||||
|
|
||||||
crate::sync_loop::run(
|
crate::sync_loop::run(
|
||||||
source,
|
source,
|
||||||
SUBSTRATE_TICK_INTERVAL,
|
consts::SUBSTRATE_TICK_INTERVAL,
|
||||||
target,
|
target,
|
||||||
ETHEREUM_TICK_INTERVAL,
|
consts::ETHEREUM_TICK_INTERVAL,
|
||||||
params.sync_params,
|
sync_params,
|
||||||
params.metrics_params,
|
metrics_params,
|
||||||
futures::future::pending(),
|
futures::future::pending(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,38 @@ pub struct HeadersSyncParams {
|
|||||||
pub target_tx_mode: TargetTransactionMode,
|
pub target_tx_mode: TargetTransactionMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HeadersSyncParams {
|
||||||
|
/// Default parameters for syncing Ethereum headers.
|
||||||
|
pub fn ethereum_sync_default() -> Self {
|
||||||
|
use crate::ethereum_sync_loop::consts::*;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD,
|
||||||
|
max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS,
|
||||||
|
max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT,
|
||||||
|
max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT,
|
||||||
|
prune_depth: PRUNE_DEPTH,
|
||||||
|
target_tx_mode: TargetTransactionMode::Signed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default parameters for syncing Substrate headers.
|
||||||
|
pub fn substrate_sync_default() -> Self {
|
||||||
|
use crate::substrate_sync_loop::consts::*;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD,
|
||||||
|
max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS,
|
||||||
|
// since we always have single Substrate header in separate Ethereum transaction,
|
||||||
|
// all max_**_in_single_submit aren't important here
|
||||||
|
max_headers_in_single_submit: 4,
|
||||||
|
max_headers_size_in_single_submit: std::usize::MAX,
|
||||||
|
prune_depth: PRUNE_DEPTH,
|
||||||
|
target_tx_mode: TargetTransactionMode::Signed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Target transaction mode.
|
/// Target transaction mode.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum TargetTransactionMode {
|
pub enum TargetTransactionMode {
|
||||||
|
|||||||
Reference in New Issue
Block a user