Skip to content

Commit

Permalink
Westend Mock Runtime and Client (paritytech#874)
Browse files Browse the repository at this point in the history
* Copy-Pasta Call code from mock Rococo to mock Westend runtime

* Update Westend client to include signing and call related code

* Add missing part of license header

* Move `account_info_storage_key` to `polkadot-core` crate
  • Loading branch information
HCastano authored and serban300 committed Apr 8, 2024
1 parent 5f32cfe commit eee7f77
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 53 deletions.
5 changes: 0 additions & 5 deletions bridges/primitives/chain-rococo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,17 @@ bp-polkadot-core = { path = "../polkadot-core", default-features = false }
bp-runtime = { path = "../runtime", default-features = false }

# Substrate Based Dependencies
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }

[dev-dependencies]
hex = "0.4"

[features]
default = ["std"]
std = [
"bp-messages/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"frame-support/std",
"parity-scale-codec/std",
"sp-api/std",
"sp-runtime/std",
Expand Down
43 changes: 3 additions & 40 deletions bridges/primitives/chain-rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
#![allow(clippy::unnecessary_mut_passed)]

use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight};
use frame_support::{Blake2_128Concat, StorageHasher, Twox128};
use sp_std::prelude::*;
use sp_version::RuntimeVersion;

pub use bp_polkadot_core::*;

/// Rococo Chain
pub type Rococo = PolkadotLike;

pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic<Call>;

pub const VERSION: RuntimeVersion = RuntimeVersion {
Expand Down Expand Up @@ -55,29 +57,6 @@ impl sp_runtime::traits::Dispatchable for Call {
}
}

/// Return a storage key for account data.
///
/// This is based on FRAME storage-generation code from Substrate:
/// https://github.com/paritytech/substrate/blob/c939ceba381b6313462d47334f775e128ea4e95d/frame/support/src/storage/generator/map.rs#L74
/// The equivalent command to invoke in case full `Runtime` is known is this:
/// `let key = frame_system::Account::<Runtime>::storage_map_final_key(&account_id);`
pub fn account_info_storage_key(id: &AccountId) -> Vec<u8> {
let module_prefix_hashed = Twox128::hash(b"System");
let storage_prefix_hashed = Twox128::hash(b"Account");
let key_hashed = parity_scale_codec::Encode::using_encoded(id, Blake2_128Concat::hash);

let mut final_key = Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len());

final_key.extend_from_slice(&module_prefix_hashed[..]);
final_key.extend_from_slice(&storage_prefix_hashed[..]);
final_key.extend_from_slice(&key_hashed);

final_key
}

/// Rococo Chain
pub type Rococo = PolkadotLike;

// We use this to get the account on Rococo (target) which is derived from Westend's (source)
// account.
pub fn derive_account_from_westend_id(id: bp_runtime::SourceAccount<AccountId>) -> AccountId {
Expand Down Expand Up @@ -165,19 +144,3 @@ sp_api::decl_runtime_apis! {
fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState;
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn should_generate_storage_key() {
let acc = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32,
]
.into();
let key = account_info_storage_key(&acc);
assert_eq!(hex::encode(key), "26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da92dccd599abfe1920a1cff8a7358231430102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20");
}
}
4 changes: 4 additions & 0 deletions bridges/primitives/chain-westend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"

[dependencies]
parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] }

# Bridge Dependencies
bp-messages = { path = "../messages", default-features = false }
Expand All @@ -15,6 +16,7 @@ bp-runtime = { path = "../runtime", default-features = false }

# Substrate Based Dependencies
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }

Expand All @@ -24,7 +26,9 @@ std = [
"bp-messages/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"parity-scale-codec/std",
"sp-api/std",
"sp-runtime/std",
"sp-std/std",
"sp-version/std",
]
18 changes: 18 additions & 0 deletions bridges/primitives/chain-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub use bp_polkadot_core::*;
/// Westend Chain
pub type Westend = PolkadotLike;

pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic<Call>;

/// Runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: sp_version::create_runtime_str!("westend"),
Expand All @@ -40,6 +42,22 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
transaction_version: 5,
};

#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)]
pub enum Call {
MockModule,
}

impl sp_runtime::traits::Dispatchable for Call {
type Origin = ();
type Config = ();
type Info = ();
type PostInfo = ();

fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
unimplemented!("The Call is not expected to be dispatched.")
}
}

// We use this to get the account on Westend (target) which is derived from Rococo's (source)
// account.
pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount<AccountId>) -> AccountId {
Expand Down
3 changes: 3 additions & 0 deletions bridges/primitives/polkadot-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }

[dev-dependencies]
hex = "0.4"

[features]
default = ["std"]
std = [
Expand Down
34 changes: 33 additions & 1 deletion bridges/primitives/polkadot-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use frame_support::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND},
DispatchClass, Weight,
},
RuntimeDebug,
Blake2_128Concat, RuntimeDebug, StorageHasher, Twox128,
};
use frame_system::limits;
use sp_core::Hasher as HasherT;
Expand All @@ -34,6 +34,7 @@ use sp_runtime::{
traits::{BlakeTwo256, IdentifyAccount, Verify},
MultiSignature, OpaqueExtrinsic, Perbill,
};
use sp_std::prelude::Vec;

// Re-export's to avoid extra substrate dependencies in chain-specific crates.
pub use frame_support::Parameter;
Expand Down Expand Up @@ -290,6 +291,26 @@ impl Convert<sp_core::H256, AccountId> for AccountIdConverter {
}
}

/// Return a storage key for account data.
///
/// This is based on FRAME storage-generation code from Substrate:
/// https://github.com/paritytech/substrate/blob/c939ceba381b6313462d47334f775e128ea4e95d/frame/support/src/storage/generator/map.rs#L74
/// The equivalent command to invoke in case full `Runtime` is known is this:
/// `let key = frame_system::Account::<Runtime>::storage_map_final_key(&account_id);`
pub fn account_info_storage_key(id: &AccountId) -> Vec<u8> {
let module_prefix_hashed = Twox128::hash(b"System");
let storage_prefix_hashed = Twox128::hash(b"Account");
let key_hashed = parity_scale_codec::Encode::using_encoded(id, Blake2_128Concat::hash);

let mut final_key = Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len());

final_key.extend_from_slice(&module_prefix_hashed[..]);
final_key.extend_from_slice(&storage_prefix_hashed[..]);
final_key.extend_from_slice(&key_hashed);

final_key
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -305,4 +326,15 @@ mod tests {
MAXIMAL_ENCODED_ACCOUNT_ID_SIZE,
);
}

#[test]
fn should_generate_storage_key() {
let acc = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32,
]
.into();
let key = account_info_storage_key(&acc);
assert_eq!(hex::encode(key), "26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da92dccd599abfe1920a1cff8a7358231430102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20");
}
}
9 changes: 6 additions & 3 deletions bridges/relays/client-rococo/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright 2019-2021 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
Expand All @@ -22,6 +25,9 @@ use std::time::Duration;
/// Rococo header id.
pub type HeaderId = relay_utils::HeaderId<bp_rococo::Hash, bp_rococo::BlockNumber>;

/// Rococo header type used in headers sync.
pub type SyncHeader = relay_substrate_client::SyncHeader<bp_rococo::Header>;

/// Rococo chain definition
#[derive(Debug, Clone, Copy)]
pub struct Rococo;
Expand Down Expand Up @@ -111,6 +117,3 @@ impl Default for SigningParams {
}
}
}

/// Rococo header type used in headers sync.
pub type SyncHeader = relay_substrate_client::SyncHeader<bp_rococo::Header>;
80 changes: 76 additions & 4 deletions bridges/relays/client-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@

//! Types used to connect to the Westend chain.

use relay_substrate_client::{Chain, ChainBase};
use codec::Encode;
use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme};
use sp_core::{storage::StorageKey, Pair};
use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount};
use std::time::Duration;

/// Westend header id.
pub type HeaderId = relay_utils::HeaderId<bp_westend::Hash, bp_westend::BlockNumber>;

/// Westend header type used in headers sync.
pub type SyncHeader = relay_substrate_client::SyncHeader<bp_westend::Header>;

/// Westend chain definition
#[derive(Debug, Clone, Copy)]
pub struct Westend;
Expand All @@ -40,8 +46,74 @@ impl Chain for Westend {
type AccountId = bp_westend::AccountId;
type Index = bp_westend::Nonce;
type SignedBlock = bp_westend::SignedBlock;
type Call = ();
type Call = bp_westend::Call;
}

/// Westend header type used in headers sync.
pub type SyncHeader = relay_substrate_client::SyncHeader<bp_westend::Header>;
impl ChainWithBalances for Westend {
type NativeBalance = bp_westend::Balance;

fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey {
StorageKey(bp_westend::account_info_storage_key(account_id))
}
}

impl TransactionSignScheme for Westend {
type Chain = Westend;
type AccountKeyPair = sp_core::sr25519::Pair;
type SignedTransaction = bp_westend::UncheckedExtrinsic;

fn sign_transaction(
genesis_hash: <Self::Chain as ChainBase>::Hash,
signer: &Self::AccountKeyPair,
signer_nonce: <Self::Chain as Chain>::Index,
call: <Self::Chain as Chain>::Call,
) -> Self::SignedTransaction {
let raw_payload = SignedPayload::new(
call,
bp_westend::SignedExtensions::new(
bp_westend::VERSION,
sp_runtime::generic::Era::Immortal,
genesis_hash,
signer_nonce,
0,
),
)
.expect("SignedExtension never fails.");

let signature = raw_payload.using_encoded(|payload| signer.sign(payload));
let signer: sp_runtime::MultiSigner = signer.public().into();
let (call, extra, _) = raw_payload.deconstruct();

bp_westend::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra)
}
}

/// Westend signing params.
#[derive(Clone)]
pub struct SigningParams {
/// Substrate transactions signer.
pub signer: sp_core::sr25519::Pair,
}

impl SigningParams {
/// Create signing params from SURI and password.
pub fn from_suri(suri: &str, password: Option<&str>) -> Result<Self, sp_core::crypto::SecretStringError> {
Ok(SigningParams {
signer: sp_core::sr25519::Pair::from_string(suri, password)?,
})
}
}

impl std::fmt::Debug for SigningParams {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.signer.public())
}
}

impl Default for SigningParams {
fn default() -> Self {
SigningParams {
signer: sp_keyring::AccountKeyring::Alice.pair(),
}
}
}

0 comments on commit eee7f77

Please sign in to comment.