Skip to content

Commit

Permalink
Extract minimal Rialto-Sub and Millau-Sub clients (paritytech#365)
Browse files Browse the repository at this point in the history
* extracting sub clients

* fmt + lost docs

* revert enum BridgeInstance

* apply suggestions from review

* explicite debug impl

* remove unused imports from Millau

* fix typo

* fix instance + API name

* Update relays/ethereum/src/ethereum_sync_loop.rs

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>

* separate crates for millau and rialto client

* cargo fmt

* fix

* fmt

* remove no_std support

* fix compilation again

* Update relays/substrate-client/Cargo.toml

* Update relay clients to Substrate 2.0

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
Co-authored-by: Hernando Castano <castano.ha@gmail.com>
  • Loading branch information
3 people authored and bkchr committed Apr 10, 2024
1 parent 7f7d62d commit 52c1913
Show file tree
Hide file tree
Showing 26 changed files with 1,042 additions and 751 deletions.
2 changes: 1 addition & 1 deletion bridges/bin/rialto-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ impl_runtime_apis! {
}
}

impl bp_eth_poa::RialtoHeaderApi<Block> for Runtime {
impl bp_eth_poa::RialtoPoAHeaderApi<Block> for Runtime {
fn best_block() -> (u64, bp_eth_poa::H256) {
let best_block = BridgeRialto::best_block();
(best_block.number, best_block.hash)
Expand Down
2 changes: 1 addition & 1 deletion bridges/primitives/ethereum-poa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ pub fn step_validator<T>(header_validators: &[T], header_step: u64) -> &T {

sp_api::decl_runtime_apis! {
/// API for querying information about headers from the Rialto Bridge Pallet
pub trait RialtoHeaderApi {
pub trait RialtoPoAHeaderApi {
/// Returns number and hash of the best block known to the bridge module.
///
/// The caller should only submit an `import_header` transaction that makes
Expand Down
13 changes: 3 additions & 10 deletions bridges/relays/ethereum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,14 @@ messages-relay = { path = "../messages-relay" }
num-traits = "0.2"
parity-crypto = { version = "0.6", features = ["publickey"] }
relay-ethereum-client = { path = "../ethereum-client" }
relay-rialto-client = { path = "../rialto-client" }
relay-substrate-client = { path = "../substrate-client" }
rialto-runtime = { path = "../../bin/rialto-runtime" }
relay-utils = { path = "../utils" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.57"
time = "0.2"

[dependencies.jsonrpsee]
git = "https://github.com/svyatonik/jsonrpsee.git"
branch = "shared-client-in-rpc-api"
default-features = false
features = ["http"]

# Substrate Based Dependencies
[dependencies.frame-system]
version = "2.0.0"
Expand Down Expand Up @@ -73,7 +70,3 @@ git = "https://github.com/paritytech/substrate.git"
version = "0.8.0"
tag = 'v2.0.0'
git = "https://github.com/paritytech/substrate.git"

[dependencies.rialto-runtime]
version = "0.1.0"
path = "../../bin/rialto-runtime"
2 changes: 0 additions & 2 deletions bridges/relays/ethereum/src/cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ subcommands:
help: Hex-encoded secret to use when transactions are submitted to the Ethereum node.
- sub-host: *sub-host
- sub-port: *sub-port
- sub-pallet-instance: *sub-pallet-instance
- no-prometheus: *no-prometheus
- prometheus-host: *prometheus-host
- prometheus-port: *prometheus-port
Expand All @@ -103,7 +102,6 @@ subcommands:
takes_value: true
- sub-host: *sub-host
- sub-port: *sub-port
- sub-pallet-instance: *sub-pallet-instance
- sub-authorities-set-id:
long: sub-authorities-set-id
value_name: SUB_AUTHORITIES_SET_ID
Expand Down
83 changes: 42 additions & 41 deletions bridges/relays/ethereum/src/ethereum_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.

use crate::rpc_errors::RpcError;
use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId};
use crate::substrate_sync_loop::QueuedRialtoHeader;

use async_trait::async_trait;
use codec::{Decode, Encode};
Expand All @@ -26,7 +26,9 @@ use relay_ethereum_client::{
types::{Address, CallRequest, HeaderId as EthereumHeaderId, Receipt, H256, U256},
Client as EthereumClient, Error as EthereumNodeError, SigningParams as EthereumSigningParams,
};
use relay_rialto_client::HeaderId as RialtoHeaderId;
use relay_utils::{HeaderId, MaybeConnectionError};
use sp_runtime::Justification;
use std::collections::HashSet;

// to encode/decode contract calls
Expand All @@ -39,34 +41,34 @@ type RpcResult<T> = std::result::Result<T, RpcError>;
#[async_trait]
pub trait EthereumHighLevelRpc {
/// Returns best Substrate block that PoA chain knows of.
async fn best_substrate_block(&self, contract_address: Address) -> RpcResult<SubstrateHeaderId>;
async fn best_substrate_block(&self, contract_address: Address) -> RpcResult<RialtoHeaderId>;

/// Returns true if Substrate header is known to Ethereum node.
async fn substrate_header_known(
&self,
contract_address: Address,
id: SubstrateHeaderId,
) -> RpcResult<(SubstrateHeaderId, bool)>;
id: RialtoHeaderId,
) -> RpcResult<(RialtoHeaderId, bool)>;

/// Submits Substrate headers to Ethereum contract.
async fn submit_substrate_headers(
&self,
params: EthereumSigningParams,
contract_address: Address,
headers: Vec<QueuedSubstrateHeader>,
) -> SubmittedHeaders<SubstrateHeaderId, RpcError>;
headers: Vec<QueuedRialtoHeader>,
) -> SubmittedHeaders<RialtoHeaderId, RpcError>;

/// Returns ids of incomplete Substrate headers.
async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult<HashSet<SubstrateHeaderId>>;
async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult<HashSet<RialtoHeaderId>>;

/// Complete Substrate header.
async fn complete_substrate_header(
&self,
params: EthereumSigningParams,
contract_address: Address,
id: SubstrateHeaderId,
justification: GrandpaJustification,
) -> RpcResult<SubstrateHeaderId>;
id: RialtoHeaderId,
justification: Justification,
) -> RpcResult<RialtoHeaderId>;

/// Submit ethereum transaction.
async fn submit_ethereum_transaction(
Expand All @@ -88,7 +90,7 @@ pub trait EthereumHighLevelRpc {

#[async_trait]
impl EthereumHighLevelRpc for EthereumClient {
async fn best_substrate_block(&self, contract_address: Address) -> RpcResult<SubstrateHeaderId> {
async fn best_substrate_block(&self, contract_address: Address) -> RpcResult<RialtoHeaderId> {
let (encoded_call, call_decoder) = bridge_contract::functions::best_known_header::call();
let call_request = CallRequest {
to: Some(contract_address),
Expand All @@ -98,7 +100,7 @@ impl EthereumHighLevelRpc for EthereumClient {

let call_result = self.eth_call(call_request).await?;
let (number, raw_hash) = call_decoder.decode(&call_result.0)?;
let hash = SubstrateHash::decode(&mut &raw_hash[..])?;
let hash = rialto_runtime::Hash::decode(&mut &raw_hash[..])?;

if number != number.low_u32().into() {
return Err(RpcError::Ethereum(EthereumNodeError::InvalidSubstrateBlockNumber));
Expand All @@ -110,8 +112,8 @@ impl EthereumHighLevelRpc for EthereumClient {
async fn substrate_header_known(
&self,
contract_address: Address,
id: SubstrateHeaderId,
) -> RpcResult<(SubstrateHeaderId, bool)> {
id: RialtoHeaderId,
) -> RpcResult<(RialtoHeaderId, bool)> {
let (encoded_call, call_decoder) = bridge_contract::functions::is_known_header::call(id.1);
let call_request = CallRequest {
to: Some(contract_address),
Expand All @@ -129,8 +131,8 @@ impl EthereumHighLevelRpc for EthereumClient {
&self,
params: EthereumSigningParams,
contract_address: Address,
headers: Vec<QueuedSubstrateHeader>,
) -> SubmittedHeaders<SubstrateHeaderId, RpcError> {
headers: Vec<QueuedRialtoHeader>,
) -> SubmittedHeaders<RialtoHeaderId, RpcError> {
// read nonce of signer
let address: Address = params.signer.address().as_fixed_bytes().into();
let nonce = match self.account_nonce(address).await {
Expand Down Expand Up @@ -159,7 +161,7 @@ impl EthereumHighLevelRpc for EthereumClient {
.await
}

async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult<HashSet<SubstrateHeaderId>> {
async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult<HashSet<RialtoHeaderId>> {
let (encoded_call, call_decoder) = bridge_contract::functions::incomplete_headers::call();
let call_request = CallRequest {
to: Some(contract_address),
Expand Down Expand Up @@ -190,9 +192,9 @@ impl EthereumHighLevelRpc for EthereumClient {
&self,
params: EthereumSigningParams,
contract_address: Address,
id: SubstrateHeaderId,
justification: GrandpaJustification,
) -> RpcResult<SubstrateHeaderId> {
id: RialtoHeaderId,
justification: Justification,
) -> RpcResult<RialtoHeaderId> {
let _ = self
.submit_ethereum_transaction(
&params,
Expand Down Expand Up @@ -243,21 +245,21 @@ pub const HEADERS_BATCH: usize = 4;
#[derive(Debug)]
#[cfg_attr(test, derive(Clone))]
pub struct HeadersBatch {
pub header1: QueuedSubstrateHeader,
pub header2: Option<QueuedSubstrateHeader>,
pub header3: Option<QueuedSubstrateHeader>,
pub header4: Option<QueuedSubstrateHeader>,
pub header1: QueuedRialtoHeader,
pub header2: Option<QueuedRialtoHeader>,
pub header3: Option<QueuedRialtoHeader>,
pub header4: Option<QueuedRialtoHeader>,
}

impl HeadersBatch {
/// Create new headers from given header & ids collections.
///
/// This method will pop `HEADERS_BATCH` items from both collections
/// and construct `Headers` object and a vector of `SubstrateheaderId`s.
/// and construct `Headers` object and a vector of `RialtoHeaderId`s.
pub fn pop_from(
headers: &mut Vec<QueuedSubstrateHeader>,
ids: &mut Vec<SubstrateHeaderId>,
) -> Result<(Self, Vec<SubstrateHeaderId>), ()> {
headers: &mut Vec<QueuedRialtoHeader>,
ids: &mut Vec<RialtoHeaderId>,
) -> Result<(Self, Vec<RialtoHeaderId>), ()> {
if headers.len() != ids.len() {
log::error!(target: "bridge", "Collection size mismatch ({} vs {})", headers.len(), ids.len());
return Err(());
Expand Down Expand Up @@ -287,7 +289,7 @@ impl HeadersBatch {
/// Returns unified array of headers.
///
/// The first element is always `Some`.
fn headers(&self) -> [Option<&QueuedSubstrateHeader>; HEADERS_BATCH] {
fn headers(&self) -> [Option<&QueuedRialtoHeader>; HEADERS_BATCH] {
[
Some(&self.header1),
self.header2.as_ref(),
Expand All @@ -298,7 +300,7 @@ impl HeadersBatch {

/// Encodes all headers. If header is not present an empty vector will be returned.
pub fn encode(&self) -> [Vec<u8>; HEADERS_BATCH] {
let encode = |h: &QueuedSubstrateHeader| h.header().encode();
let encode = |h: &QueuedRialtoHeader| h.header().encode();
let headers = self.headers();
[
headers[0].map(encode).unwrap_or_default(),
Expand All @@ -309,7 +311,7 @@ impl HeadersBatch {
}
/// Returns number of contained headers.
pub fn len(&self) -> usize {
let is_set = |h: &Option<&QueuedSubstrateHeader>| if h.is_some() { 1 } else { 0 };
let is_set = |h: &Option<&QueuedRialtoHeader>| if h.is_some() { 1 } else { 0 };
self.headers().iter().map(is_set).sum()
}

Expand Down Expand Up @@ -396,8 +398,8 @@ impl HeadersSubmitter for EthereumHeadersSubmitter {
/// Submit multiple Substrate headers.
async fn submit_substrate_headers(
mut header_submitter: impl HeadersSubmitter,
mut headers: Vec<QueuedSubstrateHeader>,
) -> SubmittedHeaders<SubstrateHeaderId, RpcError> {
mut headers: Vec<QueuedRialtoHeader>,
) -> SubmittedHeaders<RialtoHeaderId, RpcError> {
let mut submitted_headers = SubmittedHeaders::default();

let mut ids = headers.iter().map(|header| header.id()).rev().collect::<Vec<_>>();
Expand All @@ -424,8 +426,8 @@ async fn submit_substrate_headers(
/// Submit 4 Substrate headers in single PoA transaction.
async fn submit_substrate_headers_batch(
header_submitter: &mut impl HeadersSubmitter,
submitted_headers: &mut SubmittedHeaders<SubstrateHeaderId, RpcError>,
mut ids: Vec<SubstrateHeaderId>,
submitted_headers: &mut SubmittedHeaders<RialtoHeaderId, RpcError>,
mut ids: Vec<RialtoHeaderId>,
mut headers: HeadersBatch,
) -> Option<RpcError> {
debug_assert_eq!(ids.len(), headers.len(),);
Expand Down Expand Up @@ -486,12 +488,11 @@ async fn submit_substrate_headers_batch(
#[cfg(test)]
mod tests {
use super::*;
use crate::substrate_types::{Header as SubstrateHeader, Number as SubstrateBlockNumber};
use sp_runtime::traits::Header;

struct TestHeadersSubmitter {
incomplete: Vec<SubstrateHeaderId>,
failed: Vec<SubstrateHeaderId>,
incomplete: Vec<RialtoHeaderId>,
failed: Vec<RialtoHeaderId>,
}

#[async_trait]
Expand All @@ -513,9 +514,9 @@ mod tests {
}
}

fn header(number: SubstrateBlockNumber) -> QueuedSubstrateHeader {
QueuedSubstrateHeader::new(
SubstrateHeader::new(
fn header(number: rialto_runtime::BlockNumber) -> QueuedRialtoHeader {
QueuedRialtoHeader::new(
rialto_runtime::Header::new(
number,
Default::default(),
Default::default(),
Expand Down
26 changes: 12 additions & 14 deletions bridges/relays/ethereum/src/ethereum_deploy_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,17 @@
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.

use crate::ethereum_client::{bridge_contract, EthereumHighLevelRpc};
use crate::instances::BridgeInstance;
use crate::rpc::SubstrateRpc;
use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient};
use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, SubstrateHeaderId};
use crate::rpc_errors::RpcError;

use codec::{Decode, Encode};
use num_traits::Zero;
use relay_ethereum_client::{
Client as EthereumClient, ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams,
};
use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto};
use relay_substrate_client::{
Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, OpaqueGrandpaAuthoritiesSet,
};
use relay_utils::HeaderId;

/// Ethereum synchronization parameters.
Expand All @@ -44,8 +45,6 @@ pub struct EthereumDeployContractParams {
pub sub_initial_authorities_set: Option<Vec<u8>>,
/// Initial header.
pub sub_initial_header: Option<Vec<u8>>,
/// Instance of the bridge pallet being synchronized.
pub instance: Box<dyn BridgeInstance>,
}

/// Deploy Bridge contract on Ethereum chain.
Expand All @@ -56,7 +55,6 @@ pub fn run(params: EthereumDeployContractParams) {
eth_params,
eth_sign,
sub_params,
instance,
sub_initial_authorities_set_id,
sub_initial_authorities_set,
sub_initial_header,
Expand All @@ -65,7 +63,7 @@ pub fn run(params: EthereumDeployContractParams) {

let result = local_pool.run_until(async move {
let eth_client = EthereumClient::new(eth_params);
let sub_client = SubstrateRpcClient::new(sub_params, instance).await?;
let sub_client = SubstrateClient::<Rialto>::new(sub_params).await.map_err(RpcError::Substrate)?;

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);
Expand Down Expand Up @@ -102,11 +100,11 @@ pub fn run(params: EthereumDeployContractParams) {

/// Prepare initial header.
async fn prepare_initial_header(
sub_client: &SubstrateRpcClient,
sub_client: &SubstrateClient<Rialto>,
sub_initial_header: Option<Vec<u8>>,
) -> Result<(SubstrateHeaderId, Vec<u8>), String> {
) -> Result<(RialtoHeaderId, Vec<u8>), String> {
match sub_initial_header {
Some(raw_initial_header) => match SubstrateHeader::decode(&mut &raw_initial_header[..]) {
Some(raw_initial_header) => match rialto_runtime::Header::decode(&mut &raw_initial_header[..]) {
Ok(initial_header) => Ok((
HeaderId(initial_header.number, initial_header.hash()),
raw_initial_header,
Expand All @@ -124,10 +122,10 @@ async fn prepare_initial_header(

/// Prepare initial GRANDPA authorities set.
async fn prepare_initial_authorities_set(
sub_client: &SubstrateRpcClient,
sub_initial_header_hash: SubstrateHash,
sub_client: &SubstrateClient<Rialto>,
sub_initial_header_hash: rialto_runtime::Hash,
sub_initial_authorities_set: Option<Vec<u8>>,
) -> Result<Vec<u8>, String> {
) -> Result<OpaqueGrandpaAuthoritiesSet, String> {
let initial_authorities_set = match sub_initial_authorities_set {
Some(initial_authorities_set) => Ok(initial_authorities_set),
None => sub_client.grandpa_authorities_set(sub_initial_header_hash).await,
Expand Down
Loading

0 comments on commit 52c1913

Please sign in to comment.