Unverified Commit 7ab51d45 authored by Andreas Doerr's avatar Andreas Doerr Committed by GitHub
Browse files

Bump BEEFY (#3302)

parent b1d60a8a
Pipeline #143221 passed with stages
in 35 minutes and 31 seconds
...@@ -481,7 +481,7 @@ dependencies = [ ...@@ -481,7 +481,7 @@ dependencies = [
[[package]] [[package]]
name = "beefy-gadget" name = "beefy-gadget"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=master#a58179d4f59f4c31c7a09d5b0ce14df8450743a3" source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=master#29244671a1db0ee9c30b04f9a56f6bf2489522a5"
dependencies = [ dependencies = [
"beefy-primitives", "beefy-primitives",
"futures 0.3.15", "futures 0.3.15",
...@@ -509,7 +509,7 @@ dependencies = [ ...@@ -509,7 +509,7 @@ dependencies = [
[[package]] [[package]]
name = "beefy-gadget-rpc" name = "beefy-gadget-rpc"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=master#a58179d4f59f4c31c7a09d5b0ce14df8450743a3" source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=master#29244671a1db0ee9c30b04f9a56f6bf2489522a5"
dependencies = [ dependencies = [
"beefy-gadget", "beefy-gadget",
"beefy-primitives", "beefy-primitives",
...@@ -530,7 +530,7 @@ dependencies = [ ...@@ -530,7 +530,7 @@ dependencies = [
[[package]] [[package]]
name = "beefy-primitives" name = "beefy-primitives"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=master#a58179d4f59f4c31c7a09d5b0ce14df8450743a3" source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=master#29244671a1db0ee9c30b04f9a56f6bf2489522a5"
dependencies = [ dependencies = [
"parity-scale-codec", "parity-scale-codec",
"sp-api", "sp-api",
...@@ -4632,7 +4632,7 @@ dependencies = [ ...@@ -4632,7 +4632,7 @@ dependencies = [
[[package]] [[package]]
name = "pallet-beefy" name = "pallet-beefy"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=master#a58179d4f59f4c31c7a09d5b0ce14df8450743a3" source = "git+https://github.com/paritytech/grandpa-bridge-gadget?branch=master#29244671a1db0ee9c30b04f9a56f6bf2489522a5"
dependencies = [ dependencies = [
"beefy-primitives", "beefy-primitives",
"frame-support", "frame-support",
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
//! There is also the [`Client`] enum that combines all the different clients into one common structure. //! There is also the [`Client`] enum that combines all the different clients into one common structure.
use std::sync::Arc; use std::sync::Arc;
use beefy_primitives::ecdsa::AuthorityId as BeefyId;
use sp_api::{ProvideRuntimeApi, CallApiAt, NumberFor}; use sp_api::{ProvideRuntimeApi, CallApiAt, NumberFor};
use sp_blockchain::HeaderBackend; use sp_blockchain::HeaderBackend;
use sp_runtime::{ use sp_runtime::{
...@@ -82,7 +81,7 @@ pub trait RuntimeApiCollection: ...@@ -82,7 +81,7 @@ pub trait RuntimeApiCollection:
+ sp_offchain::OffchainWorkerApi<Block> + sp_offchain::OffchainWorkerApi<Block>
+ sp_session::SessionKeys<Block> + sp_session::SessionKeys<Block>
+ sp_authority_discovery::AuthorityDiscoveryApi<Block> + sp_authority_discovery::AuthorityDiscoveryApi<Block>
+ beefy_primitives::BeefyApi<Block, BeefyId> + beefy_primitives::BeefyApi<Block>
where where
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>, <Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
{} {}
...@@ -102,7 +101,7 @@ where ...@@ -102,7 +101,7 @@ where
+ sp_offchain::OffchainWorkerApi<Block> + sp_offchain::OffchainWorkerApi<Block>
+ sp_session::SessionKeys<Block> + sp_session::SessionKeys<Block>
+ sp_authority_discovery::AuthorityDiscoveryApi<Block> + sp_authority_discovery::AuthorityDiscoveryApi<Block>
+ beefy_primitives::BeefyApi<Block, BeefyId>, + beefy_primitives::BeefyApi<Block>,
<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>, <Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
{} {}
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_babe::AuthorityId as BabeId; use sp_consensus_babe::AuthorityId as BabeId;
use beefy_primitives::ecdsa::AuthorityId as BeefyId; use beefy_primitives::crypto::AuthorityId as BeefyId;
use grandpa::AuthorityId as GrandpaId; use grandpa::AuthorityId as GrandpaId;
#[cfg(feature = "kusama-native")] #[cfg(feature = "kusama-native")]
use kusama_runtime as kusama; use kusama_runtime as kusama;
......
...@@ -45,7 +45,6 @@ use { ...@@ -45,7 +45,6 @@ use {
sp_trie::PrefixedMemoryDB, sp_trie::PrefixedMemoryDB,
sc_client_api::ExecutorProvider, sc_client_api::ExecutorProvider,
grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}, grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider},
beefy_primitives::ecdsa::AuthoritySignature as BeefySignature,
sp_runtime::traits::Header as HeaderT, sp_runtime::traits::Header as HeaderT,
}; };
...@@ -248,7 +247,7 @@ fn new_partial<RuntimeApi, Executor>( ...@@ -248,7 +247,7 @@ fn new_partial<RuntimeApi, Executor>(
>, >,
grandpa::LinkHalf<Block, FullClient<RuntimeApi, Executor>, FullSelectChain>, grandpa::LinkHalf<Block, FullClient<RuntimeApi, Executor>, FullSelectChain>,
babe::BabeLink<Block>, babe::BabeLink<Block>,
beefy_gadget::notification::BeefySignedCommitmentSender<Block, BeefySignature>, beefy_gadget::notification::BeefySignedCommitmentSender<Block>,
), ),
grandpa::SharedVoterState, grandpa::SharedVoterState,
std::time::Duration, // slot-duration std::time::Duration, // slot-duration
...@@ -848,7 +847,7 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>( ...@@ -848,7 +847,7 @@ pub fn new_full<RuntimeApi, Executor, OverseerGenerator>(
prometheus_registry: prometheus_registry.clone(), prometheus_registry: prometheus_registry.clone(),
}; };
let gadget = beefy_gadget::start_beefy_gadget::<_, beefy_primitives::ecdsa::AuthorityPair, _, _, _>( let gadget = beefy_gadget::start_beefy_gadget::<_, _, _, _>(
beefy_params beefy_params
); );
......
...@@ -75,15 +75,15 @@ pub struct GrandpaDeps<B> { ...@@ -75,15 +75,15 @@ pub struct GrandpaDeps<B> {
} }
/// Dependencies for BEEFY /// Dependencies for BEEFY
pub struct BeefyDeps<BeefySignature> { pub struct BeefyDeps {
/// Receives notifications about signed commitment events from BEEFY. /// Receives notifications about signed commitment events from BEEFY.
pub beefy_commitment_stream: beefy_gadget::notification::BeefySignedCommitmentStream<Block, BeefySignature>, pub beefy_commitment_stream: beefy_gadget::notification::BeefySignedCommitmentStream<Block>,
/// Executor to drive the subscription manager in the BEEFY RPC handler. /// Executor to drive the subscription manager in the BEEFY RPC handler.
pub subscription_executor: sc_rpc::SubscriptionTaskExecutor, pub subscription_executor: sc_rpc::SubscriptionTaskExecutor,
} }
/// Full client dependencies /// Full client dependencies
pub struct FullDeps<C, P, SC, B, BS> { pub struct FullDeps<C, P, SC, B> {
/// The client instance to use. /// The client instance to use.
pub client: Arc<C>, pub client: Arc<C>,
/// Transaction pool instance. /// Transaction pool instance.
...@@ -99,11 +99,11 @@ pub struct FullDeps<C, P, SC, B, BS> { ...@@ -99,11 +99,11 @@ pub struct FullDeps<C, P, SC, B, BS> {
/// GRANDPA specific dependencies. /// GRANDPA specific dependencies.
pub grandpa: GrandpaDeps<B>, pub grandpa: GrandpaDeps<B>,
/// BEEFY specific dependencies. /// BEEFY specific dependencies.
pub beefy: BeefyDeps<BS>, pub beefy: BeefyDeps,
} }
/// Instantiate all RPC extensions. /// Instantiate all RPC extensions.
pub fn create_full<C, P, SC, B, BS>(deps: FullDeps<C, P, SC, B, BS>) -> RpcExtension where pub fn create_full<C, P, SC, B>(deps: FullDeps<C, P, SC, B>) -> RpcExtension where
C: ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore + C: ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore +
HeaderMetadata<Block, Error=BlockChainError> + Send + Sync + 'static, HeaderMetadata<Block, Error=BlockChainError> + Send + Sync + 'static,
C::Api: frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>, C::Api: frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
...@@ -115,7 +115,6 @@ pub fn create_full<C, P, SC, B, BS>(deps: FullDeps<C, P, SC, B, BS>) -> RpcExten ...@@ -115,7 +115,6 @@ pub fn create_full<C, P, SC, B, BS>(deps: FullDeps<C, P, SC, B, BS>) -> RpcExten
SC: SelectChain<Block> + 'static, SC: SelectChain<Block> + 'static,
B: sc_client_api::Backend<Block> + Send + Sync + 'static, B: sc_client_api::Backend<Block> + Send + Sync + 'static,
B::State: sc_client_api::StateBackend<sp_runtime::traits::HashFor<Block>>, B::State: sc_client_api::StateBackend<sp_runtime::traits::HashFor<Block>>,
BS: Clone + Send + parity_scale_codec::Encode + 'static,
{ {
use frame_rpc_system::{FullSystem, SystemApi}; use frame_rpc_system::{FullSystem, SystemApi};
use pallet_mmr_rpc::{MmrApi, Mmr}; use pallet_mmr_rpc::{MmrApi, Mmr};
......
...@@ -36,7 +36,7 @@ mod mock; ...@@ -36,7 +36,7 @@ mod mock;
#[cfg(test)] #[cfg(test)]
mod integration_tests; mod integration_tests;
use beefy_primitives::ecdsa::AuthorityId as BeefyId; use beefy_primitives::crypto::AuthorityId as BeefyId;
use primitives::v1::{AccountId, AssignmentId, BlockNumber, ValidatorId}; use primitives::v1::{AccountId, AssignmentId, BlockNumber, ValidatorId};
use sp_runtime::{Perquintill, Perbill, FixedPointNumber}; use sp_runtime::{Perquintill, Perbill, FixedPointNumber};
use frame_system::limits; use frame_system::limits;
......
...@@ -37,7 +37,7 @@ impl<T> pallet_mmr::primitives::OnNewRoot<beefy_primitives::MmrRootHash> for Dep ...@@ -37,7 +37,7 @@ impl<T> pallet_mmr::primitives::OnNewRoot<beefy_primitives::MmrRootHash> for Dep
let digest = sp_runtime::generic::DigestItem::Consensus( let digest = sp_runtime::generic::DigestItem::Consensus(
beefy_primitives::BEEFY_ENGINE_ID, beefy_primitives::BEEFY_ENGINE_ID,
parity_scale_codec::Encode::encode( parity_scale_codec::Encode::encode(
&beefy_primitives::ConsensusLog::<<T as pallet_beefy::Config>::AuthorityId>::MmrRoot(*root) &beefy_primitives::ConsensusLog::<<T as pallet_beefy::Config>::BeefyId>::MmrRoot(*root)
), ),
); );
<frame_system::Pallet<T>>::deposit_log(digest); <frame_system::Pallet<T>>::deposit_log(digest);
...@@ -46,8 +46,8 @@ impl<T> pallet_mmr::primitives::OnNewRoot<beefy_primitives::MmrRootHash> for Dep ...@@ -46,8 +46,8 @@ impl<T> pallet_mmr::primitives::OnNewRoot<beefy_primitives::MmrRootHash> for Dep
/// Convert BEEFY secp256k1 public keys into uncompressed form /// Convert BEEFY secp256k1 public keys into uncompressed form
pub struct UncompressBeefyEcdsaKeys; pub struct UncompressBeefyEcdsaKeys;
impl Convert<beefy_primitives::ecdsa::AuthorityId, Vec<u8>> for UncompressBeefyEcdsaKeys { impl Convert<beefy_primitives::crypto::AuthorityId, Vec<u8>> for UncompressBeefyEcdsaKeys {
fn convert(a: beefy_primitives::ecdsa::AuthorityId) -> Vec<u8> { fn convert(a: beefy_primitives::crypto::AuthorityId) -> Vec<u8> {
use sp_core::crypto::Public; use sp_core::crypto::Public;
let compressed_key = a.as_slice(); let compressed_key = a.as_slice();
// TODO [ToDr] Temporary workaround until we have a better way to get uncompressed keys. // TODO [ToDr] Temporary workaround until we have a better way to get uncompressed keys.
...@@ -137,7 +137,7 @@ pub mod pallet { ...@@ -137,7 +137,7 @@ pub mod pallet {
/// For instance for ECDSA (secp256k1) we want to store uncompressed public keys (65 bytes) /// For instance for ECDSA (secp256k1) we want to store uncompressed public keys (65 bytes)
/// to simplify using them on Ethereum chain, but the rest of the Substrate codebase /// to simplify using them on Ethereum chain, but the rest of the Substrate codebase
/// is storing them compressed (33 bytes) for efficiency reasons. /// is storing them compressed (33 bytes) for efficiency reasons.
type BeefyAuthorityToMerkleLeaf: Convert<<Self as pallet_beefy::Config>::AuthorityId, Vec<u8>>; type BeefyAuthorityToMerkleLeaf: Convert<<Self as pallet_beefy::Config>::BeefyId, Vec<u8>>;
/// Retrieve a list of current parachain heads. /// Retrieve a list of current parachain heads.
/// ///
...@@ -179,7 +179,7 @@ impl<T: Config> LeafDataProvider for Pallet<T> where ...@@ -179,7 +179,7 @@ impl<T: Config> LeafDataProvider for Pallet<T> where
impl<T: Config> Pallet<T> where impl<T: Config> Pallet<T> where
MerkleRootOf<T>: From<H256>, MerkleRootOf<T>: From<H256>,
<T as pallet_beefy::Config>::AuthorityId: <T as pallet_beefy::Config>::BeefyId:
{ {
/// Returns latest root hash of a merkle tree constructed from all registered parachain headers. /// Returns latest root hash of a merkle tree constructed from all registered parachain headers.
/// ///
......
...@@ -91,7 +91,7 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; ...@@ -91,7 +91,7 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
use pallet_session::historical as session_historical; use pallet_session::historical as session_historical;
use static_assertions::const_assert; use static_assertions::const_assert;
use beefy_primitives::ecdsa::AuthorityId as BeefyId; use beefy_primitives::crypto::AuthorityId as BeefyId;
use pallet_mmr_primitives as mmr; use pallet_mmr_primitives as mmr;
#[cfg(feature = "std")] #[cfg(feature = "std")]
...@@ -1664,7 +1664,7 @@ sp_api::impl_runtime_apis! { ...@@ -1664,7 +1664,7 @@ sp_api::impl_runtime_apis! {
} }
} }
impl beefy_primitives::BeefyApi<Block, BeefyId> for Runtime { impl beefy_primitives::BeefyApi<Block> for Runtime {
fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> { fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> {
// dummy implementation due to lack of BEEFY pallet. // dummy implementation due to lack of BEEFY pallet.
beefy_primitives::ValidatorSet { validators: Vec::new(), id: 0 } beefy_primitives::ValidatorSet { validators: Vec::new(), id: 0 }
......
...@@ -67,7 +67,7 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; ...@@ -67,7 +67,7 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
use pallet_session::historical as session_historical; use pallet_session::historical as session_historical;
use static_assertions::const_assert; use static_assertions::const_assert;
use beefy_primitives::ecdsa::AuthorityId as BeefyId; use beefy_primitives::crypto::AuthorityId as BeefyId;
use pallet_mmr_primitives as mmr; use pallet_mmr_primitives as mmr;
#[cfg(feature = "std")] #[cfg(feature = "std")]
...@@ -1241,7 +1241,7 @@ sp_api::impl_runtime_apis! { ...@@ -1241,7 +1241,7 @@ sp_api::impl_runtime_apis! {
} }
} }
impl beefy_primitives::BeefyApi<Block, BeefyId> for Runtime { impl beefy_primitives::BeefyApi<Block> for Runtime {
fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> { fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> {
// dummy implementation due to lack of BEEFY pallet. // dummy implementation due to lack of BEEFY pallet.
beefy_primitives::ValidatorSet { validators: Vec::new(), id: 0 } beefy_primitives::ValidatorSet { validators: Vec::new(), id: 0 }
......
...@@ -64,7 +64,7 @@ use pallet_grandpa::{AuthorityId as GrandpaId, fg_primitives}; ...@@ -64,7 +64,7 @@ use pallet_grandpa::{AuthorityId as GrandpaId, fg_primitives};
use sp_core::{OpaqueMetadata, RuntimeDebug}; use sp_core::{OpaqueMetadata, RuntimeDebug};
use sp_staking::SessionIndex; use sp_staking::SessionIndex;
use pallet_session::historical as session_historical; use pallet_session::historical as session_historical;
use beefy_primitives::ecdsa::AuthorityId as BeefyId; use beefy_primitives::crypto::AuthorityId as BeefyId;
use pallet_mmr_primitives as mmr; use pallet_mmr_primitives as mmr;
use frame_system::EnsureRoot; use frame_system::EnsureRoot;
use runtime_common::{paras_sudo_wrapper, paras_registrar, xcm_sender, auctions, crowdloan, slots}; use runtime_common::{paras_sudo_wrapper, paras_registrar, xcm_sender, auctions, crowdloan, slots};
...@@ -812,7 +812,7 @@ impl paras_registrar::Config for Runtime { ...@@ -812,7 +812,7 @@ impl paras_registrar::Config for Runtime {
pub struct ParentHashRandomness; pub struct ParentHashRandomness;
impl pallet_beefy::Config for Runtime { impl pallet_beefy::Config for Runtime {
type AuthorityId = BeefyId; type BeefyId = BeefyId;
} }
impl pallet_mmr::Config for Runtime { impl pallet_mmr::Config for Runtime {
...@@ -1244,7 +1244,7 @@ sp_api::impl_runtime_apis! { ...@@ -1244,7 +1244,7 @@ sp_api::impl_runtime_apis! {
} }
} }
impl beefy_primitives::BeefyApi<Block, BeefyId> for Runtime { impl beefy_primitives::BeefyApi<Block> for Runtime {
fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> { fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> {
Beefy::validator_set() Beefy::validator_set()
} }
......
...@@ -69,7 +69,7 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; ...@@ -69,7 +69,7 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
use pallet_session::historical as session_historical; use pallet_session::historical as session_historical;
use polkadot_runtime_parachains::reward_points::RewardValidatorsWithEraPoints; use polkadot_runtime_parachains::reward_points::RewardValidatorsWithEraPoints;
use beefy_primitives::ecdsa::AuthorityId as BeefyId; use beefy_primitives::crypto::AuthorityId as BeefyId;
use pallet_mmr_primitives as mmr; use pallet_mmr_primitives as mmr;
#[cfg(feature = "std")] #[cfg(feature = "std")]
...@@ -704,7 +704,7 @@ sp_api::impl_runtime_apis! { ...@@ -704,7 +704,7 @@ sp_api::impl_runtime_apis! {
} }
} }
impl beefy_primitives::BeefyApi<Block, BeefyId> for Runtime { impl beefy_primitives::BeefyApi<Block> for Runtime {
fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> { fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> {
// dummy implementation due to lack of BEEFY pallet. // dummy implementation due to lack of BEEFY pallet.
beefy_primitives::ValidatorSet { validators: Vec::new(), id: 0 } beefy_primitives::ValidatorSet { validators: Vec::new(), id: 0 }
......
...@@ -90,7 +90,7 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; ...@@ -90,7 +90,7 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
use pallet_session::historical as session_historical; use pallet_session::historical as session_historical;
use frame_system::{EnsureRoot}; use frame_system::{EnsureRoot};
use beefy_primitives::ecdsa::AuthorityId as BeefyId; use beefy_primitives::crypto::AuthorityId as BeefyId;
use pallet_mmr_primitives as mmr; use pallet_mmr_primitives as mmr;
#[cfg(feature = "std")] #[cfg(feature = "std")]
...@@ -1248,7 +1248,7 @@ sp_api::impl_runtime_apis! { ...@@ -1248,7 +1248,7 @@ sp_api::impl_runtime_apis! {
} }
} }
impl beefy_primitives::BeefyApi<Block, BeefyId> for Runtime { impl beefy_primitives::BeefyApi<Block> for Runtime {
fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> { fn validator_set() -> beefy_primitives::ValidatorSet<BeefyId> {
// dummy implementation due to lack of BEEFY pallet. // dummy implementation due to lack of BEEFY pallet.
beefy_primitives::ValidatorSet { validators: Vec::new(), id: 0 } beefy_primitives::ValidatorSet { validators: Vec::new(), id: 0 }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment