Skip to content

Commit

Permalink
Integrate BEEFY with Rialto & Millau runtimes (paritytech#1227)
Browse files Browse the repository at this point in the history
* Add Beefy pallet to Rialto runtime

* Add Beefy gadget to Rialto node

* Add MMR pallet to Rialto runtime

* Add Beefy pallet to Millau runtime

* Add Beefy gadget to Millau node

* Add MMR pallet to Millau runtime

* Add pallet_beefy_mmr to Millau runtime

* Add pallet_beefy_mmr to Rialto runtime

* Implement MMR and BEEFY APIs in Rialto

* fix unit tests

- should_encode_bridge_send_message_call() tests for new
  runtime encoding resulted from newly added pallets.
- runtime size_of::<Call>() slightly increased from newly
  added pallets.

* fix grumbles

* tighten clippy allowances

* fix more grumbles

* Add MMR RPC to Rialto and Millau nodes

Also implement MmrApi in Millau runtime.

* rialto: use upstream polkadot_client::RuntimeApiCollection
  • Loading branch information
acatangiu authored and bkchr committed Apr 10, 2024
1 parent 7b30098 commit 1fb70c7
Show file tree
Hide file tree
Showing 11 changed files with 322 additions and 86 deletions.
4 changes: 4 additions & 0 deletions bridges/bin/millau/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ pallet-bridge-messages = { path = "../../../modules/messages" }

# Substrate Dependencies

beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] }
Expand Down
21 changes: 13 additions & 8 deletions bridges/bin/millau/node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.

use beefy_primitives::crypto::AuthorityId as BeefyId;
use bp_millau::derive_account_from_rialto_id;
use millau_runtime::{
AccountId, AuraConfig, BalancesConfig, BridgeRialtoMessagesConfig, BridgeWestendGrandpaConfig,
GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig,
WASM_BINARY,
AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig,
BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys,
Signature, SudoConfig, SystemConfig, WASM_BINARY,
};
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{sr25519, Pair, Public};
Expand Down Expand Up @@ -57,10 +58,11 @@ where
}

/// Helper function to generate an authority key for Aura
pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) {
pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, BeefyId, GrandpaId) {
(
get_account_id_from_seed::<sr25519::Public>(s),
get_from_seed::<AuraId>(s),
get_from_seed::<BeefyId>(s),
get_from_seed::<GrandpaId>(s),
)
}
Expand Down Expand Up @@ -173,12 +175,12 @@ impl Alternative {
}
}

fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys {
SessionKeys { aura, grandpa }
fn session_keys(aura: AuraId, beefy: BeefyId, grandpa: GrandpaId) -> SessionKeys {
SessionKeys { aura, beefy, grandpa }
}

fn testnet_genesis(
initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>,
initial_authorities: Vec<(AccountId, AuraId, BeefyId, GrandpaId)>,
root_key: AccountId,
endowed_accounts: Vec<AccountId>,
_enable_println: bool,
Expand All @@ -191,12 +193,15 @@ fn testnet_genesis(
balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(),
},
aura: AuraConfig { authorities: Vec::new() },
beefy: BeefyConfig { authorities: Vec::new() },
grandpa: GrandpaConfig { authorities: Vec::new() },
sudo: SudoConfig { key: root_key },
session: SessionConfig {
keys: initial_authorities
.iter()
.map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone())))
.map(|x| {
(x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone(), x.3.clone()))
})
.collect::<Vec<_>>(),
},
bridge_westend_grandpa: BridgeWestendGrandpaConfig {
Expand Down
42 changes: 36 additions & 6 deletions bridges/bin/millau/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
// =====================================================================================
// UPDATE GUIDE:
// 1) replace everything with node-template/src/service.rs contents (found in main Substrate repo);
// 2) the only thing to keep from old code, is `rpc_extensions_builder` - we use our own custom
// RPCs; 3) fix compilation errors;
// 4) test :)
// 2) from old code keep `rpc_extensions_builder` - we use our own custom RPCs;
// 3) from old code keep the Beefy gadget;
// 4) fix compilation errors;
// 5) test :)
// =====================================================================================
// =====================================================================================
// =====================================================================================
Expand Down Expand Up @@ -209,6 +210,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
}

config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config());
config.network.extra_sets.push(beefy_gadget::beefy_peers_set_config());
let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new(
backend.clone(),
grandpa_link.shared_authority_set().clone(),
Expand Down Expand Up @@ -242,6 +244,8 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
let enable_grandpa = !config.disable_grandpa;
let prometheus_registry = config.prometheus_registry().cloned();
let shared_voter_state = SharedVoterState::empty();
let (signed_commitment_sender, signed_commitment_stream) =
beefy_gadget::notification::BeefySignedCommitmentStream::channel();

let rpc_extensions_builder = {
use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider;
Expand All @@ -264,7 +268,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
Some(shared_authority_set.clone()),
);

Box::new(move |_, subscription_executor| {
Box::new(move |_, subscription_executor: sc_rpc::SubscriptionTaskExecutor| {
let mut io = jsonrpc_core::IoHandler::default();
io.extend_with(SystemApi::to_delegate(FullSystem::new(
client.clone(),
Expand All @@ -278,9 +282,18 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
shared_authority_set.clone(),
shared_voter_state.clone(),
justification_stream.clone(),
subscription_executor,
subscription_executor.clone(),
finality_proof_provider.clone(),
)));
io.extend_with(beefy_gadget_rpc::BeefyApi::to_delegate(
beefy_gadget_rpc::BeefyRpcHandler::new(
signed_commitment_stream.clone(),
subscription_executor,
),
));
io.extend_with(pallet_mmr_rpc::MmrApi::to_delegate(pallet_mmr_rpc::Mmr::new(
client.clone(),
)));
Ok(io)
})
};
Expand All @@ -292,7 +305,7 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
task_manager: &mut task_manager,
transaction_pool: transaction_pool.clone(),
rpc_extensions_builder,
backend,
backend: backend.clone(),
system_rpc_tx,
config,
telemetry: telemetry.as_mut(),
Expand Down Expand Up @@ -355,6 +368,23 @@ pub fn new_full(mut config: Configuration) -> Result<TaskManager, ServiceError>
let keystore =
if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None };

let beefy_params = beefy_gadget::BeefyParams {
client,
backend,
key_store: keystore.clone(),
network: network.clone(),
signed_commitment_sender,
min_block_delta: 4,
prometheus_registry: prometheus_registry.clone(),
};

// Start the BEEFY bridge gadget.
task_manager.spawn_essential_handle().spawn_blocking(
"beefy-gadget",
None,
beefy_gadget::start_beefy_gadget::<_, _, _, _>(beefy_params),
);

let grandpa_config = sc_finality_grandpa::Config {
// FIXME #1578 make this available through chainspec
gossip_duration: Duration::from_millis(333),
Expand Down
9 changes: 9 additions & 0 deletions bridges/bin/millau/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,19 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager"

# Substrate Dependencies

beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
Expand All @@ -64,6 +69,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran
[features]
default = ["std"]
std = [
"beefy-primitives/std",
"bp-header-chain/std",
"bp-messages/std",
"bp-millau/std",
Expand All @@ -78,11 +84,14 @@ std = [
"frame-system/std",
"pallet-aura/std",
"pallet-balances/std",
"pallet-beefy/std",
"pallet-beefy-mmr/std",
"pallet-bridge-dispatch/std",
"pallet-bridge-grandpa/std",
"pallet-bridge-messages/std",
"pallet-bridge-token-swap/std",
"pallet-grandpa/std",
"pallet-mmr/std",
"pallet-randomness-collective-flip/std",
"pallet-session/std",
"pallet-shift-session-manager/std",
Expand Down
90 changes: 89 additions & 1 deletion bridges/bin/millau/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,23 @@ pub mod rialto_messages;

use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge};

use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet};
use bridge_runtime_common::messages::{
source::estimate_message_dispatch_and_delivery_fee, MessageBridge,
};
use pallet_grandpa::{
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
};
use pallet_mmr_primitives::{
DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof,
};
use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo};
use sp_api::impl_runtime_apis;
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys},
traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill,
};
Expand Down Expand Up @@ -120,6 +124,7 @@ pub mod opaque {
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
pub beefy: Beefy,
pub grandpa: Grandpa,
}
}
Expand Down Expand Up @@ -212,6 +217,11 @@ impl pallet_aura::Config for Runtime {
type MaxAuthorities = MaxAuthorities;
type DisabledValidators = ();
}

impl pallet_beefy::Config for Runtime {
type BeefyId = BeefyId;
}

impl pallet_bridge_dispatch::Config for Runtime {
type Event = Event;
type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce);
Expand Down Expand Up @@ -240,6 +250,40 @@ impl pallet_grandpa::Config for Runtime {
type MaxAuthorities = MaxAuthorities;
}

type MmrHash = <Keccak256 as sp_runtime::traits::Hash>::Output;

impl pallet_mmr::Config for Runtime {
const INDEXING_PREFIX: &'static [u8] = b"mmr";
type Hashing = Keccak256;
type Hash = MmrHash;
type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest<Runtime>;
type WeightInfo = ();
type LeafData = pallet_beefy_mmr::Pallet<Runtime>;
}

parameter_types! {
/// Version of the produced MMR leaf.
///
/// The version consists of two parts;
/// - `major` (3 bits)
/// - `minor` (5 bits)
///
/// `major` should be updated only if decoding the previous MMR Leaf format from the payload
/// is not possible (i.e. backward incompatible change).
/// `minor` should be updated if fields are added to the previous MMR Leaf, which given SCALE
/// encoding does not prevent old leafs from being decoded.
///
/// Hence we expect `major` to be changed really rarely (think never).
/// See [`MmrLeafVersion`] type documentation for more details.
pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0);
}

impl pallet_beefy_mmr::Config for Runtime {
type LeafVersion = LeafVersion;
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
type ParachainHeads = ();
}

parameter_types! {
pub const MinimumPeriod: u64 = bp_millau::SLOT_DURATION / 2;
}
Expand Down Expand Up @@ -459,6 +503,11 @@ construct_runtime!(
ShiftSessionManager: pallet_shift_session_manager::{Pallet},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},

// BEEFY Bridges support.
Beefy: pallet_beefy::{Pallet, Storage, Config<T>},
Mmr: pallet_mmr::{Pallet, Storage},
MmrLeaf: pallet_beefy_mmr::{Pallet, Storage},

// Rialto bridge modules.
BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
Expand Down Expand Up @@ -603,6 +652,45 @@ impl_runtime_apis! {
}
}

impl beefy_primitives::BeefyApi<Block> for Runtime {
fn validator_set() -> ValidatorSet<BeefyId> {
Beefy::validator_set()
}
}

impl pallet_mmr_primitives::MmrApi<Block, MmrHash> for Runtime {
fn generate_proof(leaf_index: u64)
-> Result<(EncodableOpaqueLeaf, MmrProof<MmrHash>), MmrError>
{
Mmr::generate_proof(leaf_index)
.map(|(leaf, proof)| (EncodableOpaqueLeaf::from_leaf(&leaf), proof))
}

fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof<MmrHash>)
-> Result<(), MmrError>
{
pub type Leaf = <
<Runtime as pallet_mmr::Config>::LeafData as LeafDataProvider
>::LeafData;

let leaf: Leaf = leaf
.into_opaque_leaf()
.try_decode()
.ok_or(MmrError::Verify)?;
Mmr::verify_leaf(leaf, proof)
}

fn verify_proof_stateless(
root: MmrHash,
leaf: EncodableOpaqueLeaf,
proof: MmrProof<MmrHash>
) -> Result<(), MmrError> {
type MmrHashing = <Runtime as pallet_mmr::Config>::Hashing;
let node = DataOrHash::Data(leaf.into_opaque_leaf());
pallet_mmr::verify_leaf_proof::<MmrHashing, _>(root, node, proof)
}
}

impl fg_primitives::GrandpaApi<Block> for Runtime {
fn current_set_id() -> fg_primitives::SetId {
Grandpa::current_set_id()
Expand Down
9 changes: 9 additions & 0 deletions bridges/bin/rialto/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,15 @@ rialto-runtime = { path = "../runtime" }

# Substrate Dependencies

beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" }
Expand Down Expand Up @@ -70,6 +75,10 @@ sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "mast
substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }

# Polkadot Dependencies

polkadot-client = { git = "https://github.com/paritytech/polkadot", branch = "master" }

# Polkadot (parachain) Dependencies

polkadot-approval-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" }
Expand Down
Loading

0 comments on commit 1fb70c7

Please sign in to comment.