Skip to content
This repository has been archived by the owner on Mar 20, 2024. It is now read-only.

Commit

Permalink
Fix s2s bridge (#513)
Browse files Browse the repository at this point in the history
* Fix test and add test peaks

* Fix parachain bridge init bridge

* fix compile

* Lint

* Disable kiln bridge check, it's will fix by #502

* Disable chapel bridge, follow #504

* Update log target
  • Loading branch information
fewensa authored Sep 9, 2022
1 parent 86d0989 commit 9d031f0
Show file tree
Hide file tree
Showing 15 changed files with 438 additions and 433 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ jobs:
- darwinia-ethereum
- pangolin-pangoro
- darwinia-crab
- pangoro-chapel
- pangoro-kiln
# - pangoro-chapel
# - pangoro-kiln
- pangolin-pangolinparachain
- crab-crabparachain
steps:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::types::BridgeName;
pub enum Opts {
/// Init bridge pangolin-pangolinparachain
Init {
/// Bridge
/// Bridge, support pangolin-to-pangolin-parachain rococo-to-pangolin
#[structopt()]
bridge: BridgeName,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl S2SClientRelay for CrabParachainClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand All @@ -134,7 +134,7 @@ impl S2SClientRelay for CrabParachainClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand Down Expand Up @@ -212,7 +212,7 @@ impl S2SClientRelay for CrabParachainClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand All @@ -236,7 +236,7 @@ impl S2SClientRelay for CrabParachainClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,83 +1,21 @@
use bridge_s2s_traits::client::{S2SClientBase, S2SClientGeneric};
use bridge_s2s_traits::error::{S2SClientError, S2SClientResult};
use bridge_s2s_traits::types::bp_header_chain;
use bridge_s2s_traits::types::bp_runtime::Chain;
use finality_grandpa::voter_set::VoterSet;
use sp_finality_grandpa::{AuthorityList, ConsensusLog, ScheduledChange};
use bridge_s2s_traits::{
client::{S2SClientBase, S2SClientGeneric},
types::bp_runtime::Chain,
};
use sp_runtime::generic::{Block, SignedBlock};
use sp_runtime::{ConsensusEngineId, DigestItem};
use subxt::rpc::{ClientT, Subscription, SubscriptionClientT};
use subxt::rpc::{Subscription, SubscriptionClientT};
use subxt::{sp_core, sp_runtime};

use support_toolkit::convert::SmartCodecMapper;

use crate::client::CrabParachainClient;
use crate::error::{ClientError, ClientResult};
use crate::types::runtime_types::bp_header_chain::InitializationData;

type BundleHeader = crate::types::runtime_types::sp_runtime::generic::header::Header<
u32,
crate::types::runtime_types::sp_runtime::traits::BlakeTwo256,
>;
type SpHeader = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;

const GRANDPA_ENGINE_ID: ConsensusEngineId = *b"FRNK";

impl CrabParachainClient {
async fn grandpa_authorities(&self, at: sp_core::H256) -> ClientResult<AuthorityList> {
let params = subxt::rpc::rpc_params![
"GrandpaApi_grandpa_authorities",
sp_core::Bytes(Vec::new()),
at
];
let hex: String = self
.subxt()
.rpc()
.client
.request("state_call", params)
.await?;
let raw_authorities_set = array_bytes::hex2bytes(hex.as_ref())?;
let authorities = codec::Decode::decode(&mut &raw_authorities_set[..]).map_err(|err| {
ClientError::Custom(format!(
"[DecodeAuthorities] Can not decode authorities: {:?}",
err
))
})?;
Ok(authorities)
}

/// Find header digest that schedules next GRANDPA authorities set.
fn find_grandpa_authorities_scheduled_change(
&self,
header: &SpHeader,
) -> Option<ScheduledChange<u32>> {
let filter_log = |log: ConsensusLog<u32>| match log {
ConsensusLog::ScheduledChange(change) => Some(change),
_ => None,
};

// find the first consensus digest with the right ID which converts to
// the right kind of consensus log.
header
.digest
.logs
.iter()
.filter_map(|item| match item {
DigestItem::Consensus(engine, logs) => {
if engine == &GRANDPA_ENGINE_ID {
Some(&logs[..])
} else {
None
}
}
_ => None,
})
.find_map(|mut l| {
let log = codec::Decode::decode(&mut l).ok();
log.and_then(filter_log)
})
}
}

impl S2SClientBase for CrabParachainClient {
const CHAIN: &'static str = "crabparachain";
Expand Down Expand Up @@ -134,119 +72,9 @@ impl S2SClientGeneric for CrabParachainClient {
}

async fn prepare_initialization_data(&self) -> S2SClientResult<Self::InitializationData> {
let mut subscription = self.subscribe_grandpa_justifications().await?;
let justification = subscription
.next()
.await
.ok_or_else(|| S2SClientError::Custom("The subscribe is closed".to_string()))??;
let justification: bp_header_chain::justification::GrandpaJustification<SpHeader> =
codec::Decode::decode(&mut &justification.0[..])
.map_err(|err| S2SClientError::Custom(format!("Wrong justification: {:?}", err)))?;

let (initial_header_hash, initial_header_number) = (
justification.commit.target_hash,
justification.commit.target_number,
);
let initial_header = self
.subxt()
.rpc()
.header(Some(initial_header_hash))
.await?
.ok_or_else(|| {
S2SClientError::Custom(format!(
"Can not get initial header by hash: {:?}",
initial_header_hash
))
})?;
tracing::trace!(target: "client-pangolin-parachain", "Selected initial header [{}]: {}",
initial_header_number,
initial_header_hash,
);
let initial_authorities_set = self.grandpa_authorities(initial_header_hash).await?;
tracing::trace!(target: "client-pangolin-parachain", "Selected initial authorities set: {:?}",
initial_authorities_set,
);

// If initial header changes the GRANDPA authorities set, then we need previous authorities
// to verify justification.
let mut authorities_for_verification = initial_authorities_set.clone();
let scheduled_change = self.find_grandpa_authorities_scheduled_change(&initial_header);
if scheduled_change
.as_ref()
.map(|c| c.delay == 0)
.unwrap_or(false)
{
return Err(S2SClientError::Custom(format!(
"GRANDPA authorities change at {} scheduled to happen in {:?} blocks. \
We expect regular hange to have zero delay",
initial_header_hash,
scheduled_change.as_ref().map(|c| c.delay),
)));
}
let schedules_change = scheduled_change.is_some();
if schedules_change {
authorities_for_verification =
self.grandpa_authorities(initial_header.parent_hash).await?;
tracing::trace!(
target: "client-pangolin-parachain",
"Selected header is scheduling GRANDPA authorities set changes. Using previous set: {:?}",
authorities_for_verification,
);
}

// Now let's try to guess authorities set id by verifying justification.
let mut initial_authorities_set_id = 0;
let mut min_possible_block_number = 0;
let authorities_for_verification = VoterSet::new(authorities_for_verification.clone())
.ok_or(S2SClientError::Custom(format!(
"[ReadInvalidAuthorities]: {:?}",
authorities_for_verification,
)))?;
loop {
tracing::trace!(
target: "client-pangolin-parachain",
"Trying GRANDPA authorities set id: {}",
initial_authorities_set_id,
);

let is_valid_set_id = bp_header_chain::justification::verify_justification::<SpHeader>(
(initial_header_hash, initial_header_number),
initial_authorities_set_id,
&authorities_for_verification,
&justification,
)
.is_ok();

if is_valid_set_id {
break;
}

initial_authorities_set_id += 1;
min_possible_block_number += 1;
if min_possible_block_number > initial_header_number {
// there can't be more authorities set changes than headers => if we have reached
// `initial_block_number` and still have not found correct value of
// `initial_authorities_set_id`, then something else is broken => fail
return Err(S2SClientError::Custom(format!(
"[GuessInitialAuthorities]: {}",
initial_header_number
)));
}
}

let initialization_data = bp_header_chain::InitializationData {
header: Box::new(initial_header),
authority_list: initial_authorities_set,
set_id: if schedules_change {
initial_authorities_set_id + 1
} else {
initial_authorities_set_id
},
is_halted: false,
};
let bytes = codec::Encode::encode(&initialization_data);
Ok(codec::Decode::decode(&mut &bytes[..]).map_err(|e| {
S2SClientError::Custom(format!("Failed to decode initialization data: {:?}", e))
})?)
Err(S2SClientError::Custom(format!(
"[{}] not needed prepare_initialization_data",
<Self as S2SClientBase>::CHAIN
)))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl S2SClientRelay for CrabClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand All @@ -134,7 +134,7 @@ impl S2SClientRelay for CrabClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand Down Expand Up @@ -214,7 +214,7 @@ impl S2SClientRelay for CrabClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand All @@ -240,7 +240,7 @@ impl S2SClientRelay for CrabClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand Down Expand Up @@ -285,7 +285,7 @@ impl S2SParaBridgeClientSolochain for CrabClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl S2SClientRelay for CrabClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand All @@ -132,7 +132,7 @@ impl S2SClientRelay for CrabClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand Down Expand Up @@ -212,7 +212,7 @@ impl S2SClientRelay for CrabClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand All @@ -238,7 +238,7 @@ impl S2SClientRelay for CrabClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl S2SClientRelay for DarwiniaClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand All @@ -132,7 +132,7 @@ impl S2SClientRelay for DarwiniaClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand Down Expand Up @@ -212,7 +212,7 @@ impl S2SClientRelay for DarwiniaClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand All @@ -238,7 +238,7 @@ impl S2SClientRelay for DarwiniaClient {
.await?;
let events = track.wait_for_finalized_success().await.map_err(|e| {
S2SClientError::RPC(format!(
"send transactioni failed {}: {:?}",
"send transaction failed {}: {:?}",
<Self as S2SClientBase>::CHAIN,
e
))
Expand Down
Loading

0 comments on commit 9d031f0

Please sign in to comment.