Skip to content

Commit

Permalink
Merge commit '03de1a05e86869c53773af303dc461a3a0478fd7' into bko-brid…
Browse files Browse the repository at this point in the history
…ge-origin-check
  • Loading branch information
bkontur committed Dec 6, 2023
2 parents 8e30c83 + 03de1a0 commit 6bacb0b
Show file tree
Hide file tree
Showing 16 changed files with 131 additions and 64 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bridges/bin/runtime-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ bp-parachains = { path = "../../primitives/parachains", default-features = false
bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false }
bp-relayers = { path = "../../primitives/relayers", default-features = false }
bp-runtime = { path = "../../primitives/runtime", default-features = false }
bp-xcm-bridge-hub = { path = "../../primitives/xcm-bridge-hub", default-features = false }
bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false }
pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false }
pallet-bridge-messages = { path = "../../modules/messages", default-features = false }
Expand Down Expand Up @@ -58,6 +59,7 @@ std = [
"bp-polkadot-core/std",
"bp-relayers/std",
"bp-runtime/std",
"bp-xcm-bridge-hub/std",
"bp-xcm-bridge-hub-router/std",
"codec/std",
"frame-support/std",
Expand Down
4 changes: 1 addition & 3 deletions bridges/bin/runtime-common/src/messages_xcm_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use bp_messages::{
LaneId, MessageNonce,
};
use bp_runtime::messages::MessageDispatchResult;
pub use bp_xcm_bridge_hub::XcmAsPlainPayload;
use bp_xcm_bridge_hub_router::XcmChannelStatusProvider;
use codec::{Decode, Encode};
use frame_support::{traits::Get, weights::Weight, CloneNoBound, EqNoBound, PartialEqNoBound};
Expand All @@ -39,9 +40,6 @@ use sp_std::{fmt::Debug, marker::PhantomData};
use xcm::prelude::*;
use xcm_builder::{DispatchBlob, DispatchBlobError};

/// Plain "XCM" payload, which we transfer through bridge
pub type XcmAsPlainPayload = sp_std::prelude::Vec<u8>;

/// Message dispatch result type for single message
#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)]
pub enum XcmBlobMessageDispatchResult {
Expand Down
4 changes: 2 additions & 2 deletions bridges/bin/runtime-common/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,8 @@ impl ChainWithGrandpa for BridgedUnderlyingChain {
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
const MAX_AUTHORITIES_COUNT: u32 = 16;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
const MAX_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64;
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE: u32 = 64;
}

impl Chain for BridgedUnderlyingParachain {
Expand Down
29 changes: 16 additions & 13 deletions bridges/modules/grandpa/src/call_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.

use crate::{weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, Error, Pallet};
use bp_header_chain::{justification::GrandpaJustification, ChainWithGrandpa};
use bp_header_chain::{
justification::GrandpaJustification, max_expected_submit_finality_proof_arguments_size,
ChainWithGrandpa, GrandpaConsensusLogReader,
};
use bp_runtime::{BlockNumberOf, OwnedBridgeModule};
use codec::Encode;
use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight};
Expand Down Expand Up @@ -169,28 +172,28 @@ pub(crate) fn submit_finality_proof_info_from_args<T: Config<I>, I: 'static>(
Weight::zero()
};

// check if the `finality_target` is a mandatory header. If so, we are ready to refund larger
// size
let is_mandatory_finality_target =
GrandpaConsensusLogReader::<BridgedBlockNumber<T, I>>::find_scheduled_change(
finality_target.digest(),
)
.is_some();

// we can estimate extra call size easily, without any additional significant overhead
let actual_call_size: u32 = finality_target
.encoded_size()
.saturating_add(justification.encoded_size())
.saturated_into();
let max_expected_call_size = max_expected_call_size::<T, I>(required_precommits);
let max_expected_call_size = max_expected_submit_finality_proof_arguments_size::<T::BridgedChain>(
is_mandatory_finality_target,
required_precommits,
);
let extra_size = actual_call_size.saturating_sub(max_expected_call_size);

SubmitFinalityProofInfo { block_number, extra_weight, extra_size }
}

/// Returns maximal expected size of `submit_finality_proof` call arguments.
fn max_expected_call_size<T: Config<I>, I: 'static>(required_precommits: u32) -> u32 {
let max_expected_justification_size =
GrandpaJustification::<BridgedHeader<T, I>>::max_reasonable_size::<T::BridgedChain>(
required_precommits,
);

// call arguments are header and justification
T::BridgedChain::MAX_HEADER_SIZE.saturating_add(max_expected_justification_size)
}

#[cfg(test)]
mod tests {
use crate::{
Expand Down
4 changes: 2 additions & 2 deletions bridges/modules/grandpa/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ impl ChainWithGrandpa for TestBridgedChain {
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
const MAX_AUTHORITIES_COUNT: u32 = MAX_BRIDGED_AUTHORITIES;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
const MAX_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64;
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE: u32 = 64;
}

/// Return test externalities to use in tests.
Expand Down
8 changes: 4 additions & 4 deletions bridges/modules/parachains/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ impl ChainWithGrandpa for TestBridgedChain {
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
const MAX_AUTHORITIES_COUNT: u32 = 16;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
const MAX_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64;
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE: u32 = 64;
}

#[derive(Debug)]
Expand Down Expand Up @@ -283,8 +283,8 @@ impl ChainWithGrandpa for OtherBridgedChain {
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "";
const MAX_AUTHORITIES_COUNT: u32 = 16;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8;
const MAX_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64;
const MAX_MANDATORY_HEADER_SIZE: u32 = 256;
const AVERAGE_HEADER_SIZE: u32 = 64;
}

/// Return test externalities to use in tests.
Expand Down
4 changes: 2 additions & 2 deletions bridges/modules/xcm-bridge-hub/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ pub mod pallet {
type MessageExportPrice: Get<MultiAssets>;

/// Get point-to-point links with bridged consensus (`Self::BridgedNetworkId`).
/// (this will be replaced with dynamic on-chain bridges - for Bridges V2)
/// (this will be replaced with dynamic on-chain bridges - `Bridges V2`)
type Lanes: Get<sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))>>;
/// Support for point-to-point links
/// (this will be replaced with dynamic on-chain bridges - for Bridges V2)
/// (this will be replaced with dynamic on-chain bridges - `Bridges V2`)
type LanesSupport: XcmBlobHauler;
}

Expand Down
4 changes: 2 additions & 2 deletions bridges/primitives/chain-kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ impl ChainWithGrandpa for Kusama {
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
}

// The SignedExtension used by Kusama.
Expand Down
8 changes: 4 additions & 4 deletions bridges/primitives/chain-polkadot-bulletin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidi
// This chain reuses most of Polkadot primitives.
pub use bp_polkadot_core::{
AccountAddress, AccountId, Balance, Block, BlockNumber, Hash, Hasher, Header, Nonce, Signature,
SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE_IN_JUSTIFICATION,
EXTRA_STORAGE_PROOF_SIZE, MAX_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY,
SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE, EXTRA_STORAGE_PROOF_SIZE,
MAX_MANDATORY_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY,
};

/// Maximal number of GRANDPA authorities at Polkadot Bulletin chain.
Expand Down Expand Up @@ -207,8 +207,8 @@ impl ChainWithGrandpa for PolkadotBulletin {
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
}

decl_bridge_finality_runtime_apis!(polkadot_bulletin, grandpa);
Expand Down
4 changes: 2 additions & 2 deletions bridges/primitives/chain-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ impl ChainWithGrandpa for Polkadot {
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
}

/// The SignedExtension used by Polkadot.
Expand Down
4 changes: 2 additions & 2 deletions bridges/primitives/chain-rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ impl ChainWithGrandpa for Rococo {
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
}

parameter_types! {
Expand Down
4 changes: 2 additions & 2 deletions bridges/primitives/chain-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ impl ChainWithGrandpa for Westend {
const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE;
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
}

parameter_types! {
Expand Down
4 changes: 2 additions & 2 deletions bridges/primitives/header-chain/src/justification/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ impl<H: HeaderT> GrandpaJustification<H> {
.saturating_add(BlockNumberOf::<C>::max_encoded_len().saturated_into())
.saturating_add(HashOf::<C>::max_encoded_len().saturated_into());

let max_expected_votes_ancestries_size = C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY
.saturating_mul(C::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION);
let max_expected_votes_ancestries_size =
C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY.saturating_mul(C::AVERAGE_HEADER_SIZE);

// justification is round number (u64=8b), a signed GRANDPA commit and the
// `votes_ancestries` vector
Expand Down
93 changes: 79 additions & 14 deletions bridges/primitives/header-chain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,23 +266,28 @@ pub trait ChainWithGrandpa: Chain {
/// to submitter.
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32;

/// Maximal size of the chain header. The header may be the header that enacts new GRANDPA
/// authorities set (so it has large digest inside).
/// Maximal size of the mandatory chain header. Mandatory header is the header that enacts new
/// GRANDPA authorities set (so it has large digest inside).
///
/// This isn't a strict limit. The relay may submit larger headers and the pallet will accept
/// the call. The limit is only used to compute maximal refund amount and doing calls which
/// exceed the limit, may be costly to submitter.
const MAX_HEADER_SIZE: u32;
const MAX_MANDATORY_HEADER_SIZE: u32;

/// Average size of the chain header from justification ancestry. We don't expect to see there
/// headers that change GRANDPA authorities set (GRANDPA will probably be able to finalize at
/// least one additional header per session on non test chains), so this is average size of
/// headers that aren't changing the set.
/// Average size of the chain header. We don't expect to see there headers that change GRANDPA
/// authorities set (GRANDPA will probably be able to finalize at least one additional header
/// per session on non test chains), so this is average size of headers that aren't changing the
/// set.
///
/// This isn't a strict limit. The relay may submit justifications with larger headers in its
/// ancestry and the pallet will accept the call. The limit is only used to compute maximal
/// refund amount and doing calls which exceed the limit, may be costly to submitter.
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32;
/// This isn't a strict limit. The relay may submit justifications with larger headers and the
/// pallet will accept the call. However, if the total size of all `submit_finality_proof`
/// arguments exceeds the maximal size, computed using this average size, relayer will only get
/// partial refund.
///
/// We expect some headers on production chains that are above this size. But they are rare and
/// if rellayer cares about its profitability, we expect it'll select other headers for
/// submission.
const AVERAGE_HEADER_SIZE: u32;
}

impl<T> ChainWithGrandpa for T
Expand All @@ -295,7 +300,67 @@ where
const MAX_AUTHORITIES_COUNT: u32 = <T::Chain as ChainWithGrandpa>::MAX_AUTHORITIES_COUNT;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
<T::Chain as ChainWithGrandpa>::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
const MAX_HEADER_SIZE: u32 = <T::Chain as ChainWithGrandpa>::MAX_HEADER_SIZE;
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 =
<T::Chain as ChainWithGrandpa>::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
const MAX_MANDATORY_HEADER_SIZE: u32 =
<T::Chain as ChainWithGrandpa>::MAX_MANDATORY_HEADER_SIZE;
const AVERAGE_HEADER_SIZE: u32 = <T::Chain as ChainWithGrandpa>::AVERAGE_HEADER_SIZE;
}

/// Returns maximal expected size of `submit_finality_proof` call arguments.
pub fn max_expected_submit_finality_proof_arguments_size<C: ChainWithGrandpa>(
is_mandatory_finality_target: bool,
precommits: u32,
) -> u32 {
let max_expected_justification_size =
GrandpaJustification::<HeaderOf<C>>::max_reasonable_size::<C>(precommits);

// call arguments are header and justification
let max_expected_finality_target_size = if is_mandatory_finality_target {
C::MAX_MANDATORY_HEADER_SIZE
} else {
C::AVERAGE_HEADER_SIZE
};
max_expected_finality_target_size.saturating_add(max_expected_justification_size)
}

#[cfg(test)]
mod tests {
use super::*;
use frame_support::weights::Weight;
use sp_runtime::{testing::H256, traits::BlakeTwo256, MultiSignature};

struct TestChain;

impl Chain for TestChain {
type BlockNumber = u32;
type Hash = H256;
type Hasher = BlakeTwo256;
type Header = sp_runtime::generic::Header<u32, BlakeTwo256>;
type AccountId = u64;
type Balance = u64;
type Nonce = u64;
type Signature = MultiSignature;

fn max_extrinsic_size() -> u32 {
0
}
fn max_extrinsic_weight() -> Weight {
Weight::zero()
}
}

impl ChainWithGrandpa for TestChain {
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "Test";
const MAX_AUTHORITIES_COUNT: u32 = 128;
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2;
const MAX_MANDATORY_HEADER_SIZE: u32 = 100_000;
const AVERAGE_HEADER_SIZE: u32 = 1_024;
}

#[test]
fn max_expected_submit_finality_proof_arguments_size_respects_mandatory_argument() {
assert!(
max_expected_submit_finality_proof_arguments_size::<TestChain>(true, 100) >
max_expected_submit_finality_proof_arguments_size::<TestChain>(false, 100),
);
}
}
18 changes: 8 additions & 10 deletions bridges/primitives/polkadot-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,30 +64,28 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 1_256;
///
/// See [`bp-header-chain::ChainWithGrandpa`] for more details.
///
/// This value comes from recent (February, 2023) Kusama and Polkadot headers. There are no
/// This value comes from recent (December, 2023) Kusama and Polkadot headers. There are no
/// justifications with any additional headers in votes ancestry, so reasonable headers may
/// be set to zero. But we assume that there may be small GRANDPA lags, so we're leaving some
/// reserve here.
pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2;

/// Approximate average header size in `votes_ancestries` field of justification on Polkadot-like
/// Average header size in `votes_ancestries` field of justification on Polkadot-like
/// chains.
///
/// See [`bp-header-chain::ChainWithGrandpa`] for more details.
///
/// This value comes from recent (February, 2023) Kusama headers. Average is `336` there, but some
/// non-mandatory headers has size `40kb` (they contain the BABE epoch descriptor with all
/// authorities - just like our mandatory header). Since we assume `2` headers in justification
/// votes ancestry, let's set average header to `40kb / 2`.
pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 20 * 1024;
/// This value comes from recent (December, 2023) Kusama headers. Most of headers are `327` bytes
/// there, but let's have some reserve and make it 1024.
pub const AVERAGE_HEADER_SIZE: u32 = 1024;

/// Approximate maximal header size on Polkadot-like chains.
///
/// See [`bp-header-chain::ChainWithGrandpa`] for more details.
///
/// This value comes from recent (February, 2023) Kusama headers. Maximal header is a mandatory
/// header. In its SCALE-encoded form it is `80348` bytes. Let's have some reserve here.
pub const MAX_HEADER_SIZE: u32 = 90_000;
/// This value comes from recent (December, 2023) Kusama headers. Maximal header is a mandatory
/// header. In its SCALE-encoded form it is `113407` bytes. Let's have some reserve here.
pub const MAX_MANDATORY_HEADER_SIZE: u32 = 120 * 1024;

/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at
/// Polkadot-like chain. This mostly depends on number of entries in the storage trie.
Expand Down

0 comments on commit 6bacb0b

Please sign in to comment.