mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 04:41:02 +00:00
Remove Parent Hash to Session mapping (#928)
* Adds a SigningContext type * Bump spec versions * Fixes requested changes * Bump ParachainHost api_version and guard signing_context call * Improve error message * If there is no signing_context api use default value Co-authored-by: Robert Habermeier <rphmeier@gmail.com>
This commit is contained in:
Generated
+1
@@ -3956,6 +3956,7 @@ dependencies = [
|
|||||||
"sp-inherents 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
"sp-inherents 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
||||||
"sp-runtime 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
"sp-runtime 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
||||||
"sp-serializer 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
"sp-serializer 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
||||||
|
"sp-staking 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
||||||
"sp-std 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
"sp-std 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
||||||
"sp-trie 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
"sp-trie 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
||||||
"sp-version 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
"sp-version 2.0.0-alpha.5 (git+https://github.com/paritytech/substrate)",
|
||||||
|
|||||||
@@ -131,9 +131,13 @@ impl View {
|
|||||||
///
|
///
|
||||||
/// This will be pruned later on a call to `prune_old_leaves`, when this leaf
|
/// This will be pruned later on a call to `prune_old_leaves`, when this leaf
|
||||||
/// is not a leaf anymore.
|
/// is not a leaf anymore.
|
||||||
pub(super) fn new_local_leaf(&mut self, relay_chain_leaf: Hash, validation_data: MessageValidationData) {
|
pub(super) fn new_local_leaf(
|
||||||
|
&mut self,
|
||||||
|
validation_data: MessageValidationData,
|
||||||
|
) {
|
||||||
|
let relay_chain_leaf = validation_data.signing_context.parent_hash.clone();
|
||||||
self.leaf_work.push((
|
self.leaf_work.push((
|
||||||
relay_chain_leaf,
|
validation_data.signing_context.parent_hash.clone(),
|
||||||
LeafView {
|
LeafView {
|
||||||
validation_data,
|
validation_data,
|
||||||
knowledge: Default::default(),
|
knowledge: Default::default(),
|
||||||
@@ -207,7 +211,6 @@ impl View {
|
|||||||
|
|
||||||
// validate signature.
|
// validate signature.
|
||||||
let res = view.validation_data.check_statement(
|
let res = view.validation_data.check_statement(
|
||||||
&message.relay_chain_leaf,
|
|
||||||
&message.signed_statement,
|
&message.signed_statement,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ use sc_network_gossip::{
|
|||||||
use polkadot_validation::{SignedStatement};
|
use polkadot_validation::{SignedStatement};
|
||||||
use polkadot_primitives::{Block, Hash};
|
use polkadot_primitives::{Block, Hash};
|
||||||
use polkadot_primitives::parachain::{
|
use polkadot_primitives::parachain::{
|
||||||
ParachainHost, ValidatorId, ErasureChunk as PrimitiveChunk
|
ParachainHost, ValidatorId, ErasureChunk as PrimitiveChunk, SigningContext,
|
||||||
};
|
};
|
||||||
use polkadot_erasure_coding::{self as erasure};
|
use polkadot_erasure_coding::{self as erasure};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
@@ -377,13 +377,12 @@ impl RegisteredMessageValidator {
|
|||||||
/// relevant to this leaf.
|
/// relevant to this leaf.
|
||||||
pub(crate) fn new_local_leaf(
|
pub(crate) fn new_local_leaf(
|
||||||
&self,
|
&self,
|
||||||
relay_chain_leaf: Hash,
|
|
||||||
validation: MessageValidationData,
|
validation: MessageValidationData,
|
||||||
) -> NewLeafActions {
|
) -> NewLeafActions {
|
||||||
// add an entry in attestation_view
|
// add an entry in attestation_view
|
||||||
// prune any entries from attestation_view which are no longer leaves
|
// prune any entries from attestation_view which are no longer leaves
|
||||||
let mut inner = self.inner.inner.write();
|
let mut inner = self.inner.inner.write();
|
||||||
inner.attestation_view.new_local_leaf(relay_chain_leaf, validation);
|
inner.attestation_view.new_local_leaf(validation);
|
||||||
|
|
||||||
let mut actions = Vec::new();
|
let mut actions = Vec::new();
|
||||||
|
|
||||||
@@ -460,11 +459,13 @@ impl GossipService for RegisteredMessageValidator {
|
|||||||
pub(crate) struct MessageValidationData {
|
pub(crate) struct MessageValidationData {
|
||||||
/// The authorities' parachain validation keys at a block.
|
/// The authorities' parachain validation keys at a block.
|
||||||
pub(crate) authorities: Vec<ValidatorId>,
|
pub(crate) authorities: Vec<ValidatorId>,
|
||||||
|
/// The signing context.
|
||||||
|
pub(crate) signing_context: SigningContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageValidationData {
|
impl MessageValidationData {
|
||||||
// check a statement's signature.
|
// check a statement's signature.
|
||||||
fn check_statement(&self, relay_chain_leaf: &Hash, statement: &SignedStatement) -> Result<(), ()> {
|
fn check_statement(&self, statement: &SignedStatement) -> Result<(), ()> {
|
||||||
let sender = match self.authorities.get(statement.sender as usize) {
|
let sender = match self.authorities.get(statement.sender as usize) {
|
||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
None => return Err(()),
|
None => return Err(()),
|
||||||
@@ -475,7 +476,7 @@ impl MessageValidationData {
|
|||||||
&statement.statement,
|
&statement.statement,
|
||||||
&statement.signature,
|
&statement.signature,
|
||||||
sender.clone(),
|
sender.clone(),
|
||||||
relay_chain_leaf,
|
&self.signing_context,
|
||||||
);
|
);
|
||||||
|
|
||||||
if good {
|
if good {
|
||||||
@@ -826,7 +827,9 @@ mod tests {
|
|||||||
let topic_c = attestation_topic(hash_c);
|
let topic_c = attestation_topic(hash_c);
|
||||||
|
|
||||||
// topic_a is in all 3 views -> succeed
|
// topic_a is in all 3 views -> succeed
|
||||||
validator.inner.write().attestation_view.new_local_leaf(hash_a, MessageValidationData::default());
|
let mut validation_data = MessageValidationData::default();
|
||||||
|
validation_data.signing_context.parent_hash = hash_a;
|
||||||
|
validator.inner.write().attestation_view.new_local_leaf(validation_data);
|
||||||
// topic_b is in the neighbor's view but not ours -> fail
|
// topic_b is in the neighbor's view but not ours -> fail
|
||||||
// topic_c is not in either -> fail
|
// topic_c is not in either -> fail
|
||||||
|
|
||||||
@@ -937,7 +940,9 @@ mod tests {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
let encoded = statement.encode();
|
let encoded = statement.encode();
|
||||||
validator.inner.write().attestation_view.new_local_leaf(hash_a, MessageValidationData::default());
|
let mut validation_data = MessageValidationData::default();
|
||||||
|
validation_data.signing_context.parent_hash = hash_a;
|
||||||
|
validator.inner.write().attestation_view.new_local_leaf(validation_data);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut message_allowed = validator.message_allowed();
|
let mut message_allowed = validator.message_allowed();
|
||||||
|
|||||||
@@ -162,7 +162,6 @@ impl NetworkServiceOps for PolkadotNetworkService {
|
|||||||
trait GossipOps: Clone + Send + crate::legacy::GossipService + 'static {
|
trait GossipOps: Clone + Send + crate::legacy::GossipService + 'static {
|
||||||
fn new_local_leaf(
|
fn new_local_leaf(
|
||||||
&self,
|
&self,
|
||||||
relay_parent: Hash,
|
|
||||||
validation_data: crate::legacy::gossip::MessageValidationData,
|
validation_data: crate::legacy::gossip::MessageValidationData,
|
||||||
) -> crate::legacy::gossip::NewLeafActions;
|
) -> crate::legacy::gossip::NewLeafActions;
|
||||||
|
|
||||||
@@ -177,10 +176,12 @@ trait GossipOps: Clone + Send + crate::legacy::GossipService + 'static {
|
|||||||
impl GossipOps for RegisteredMessageValidator {
|
impl GossipOps for RegisteredMessageValidator {
|
||||||
fn new_local_leaf(
|
fn new_local_leaf(
|
||||||
&self,
|
&self,
|
||||||
relay_parent: Hash,
|
|
||||||
validation_data: crate::legacy::gossip::MessageValidationData,
|
validation_data: crate::legacy::gossip::MessageValidationData,
|
||||||
) -> crate::legacy::gossip::NewLeafActions {
|
) -> crate::legacy::gossip::NewLeafActions {
|
||||||
RegisteredMessageValidator::new_local_leaf(self, relay_parent, validation_data)
|
RegisteredMessageValidator::new_local_leaf(
|
||||||
|
self,
|
||||||
|
validation_data,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_availability_store(
|
fn register_availability_store(
|
||||||
@@ -804,7 +805,6 @@ impl<Api, Sp, Gossip> Worker<Api, Sp, Gossip> where
|
|||||||
authorities: Vec<ValidatorId>,
|
authorities: Vec<ValidatorId>,
|
||||||
) {
|
) {
|
||||||
// glue: let gossip know about our new local leaf.
|
// glue: let gossip know about our new local leaf.
|
||||||
let relay_parent = table.consensus_parent_hash().clone();
|
|
||||||
let (signal, exit) = exit_future::signal();
|
let (signal, exit) = exit_future::signal();
|
||||||
|
|
||||||
let key = table.session_key();
|
let key = table.session_key();
|
||||||
@@ -814,19 +814,20 @@ impl<Api, Sp, Gossip> Worker<Api, Sp, Gossip> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let signing_context = table.signing_context().clone();
|
||||||
|
let relay_parent = signing_context.parent_hash.clone();
|
||||||
let new_leaf_actions = self.gossip_handle.new_local_leaf(
|
let new_leaf_actions = self.gossip_handle.new_local_leaf(
|
||||||
relay_parent,
|
crate::legacy::gossip::MessageValidationData { authorities, signing_context },
|
||||||
crate::legacy::gossip::MessageValidationData { authorities },
|
|
||||||
);
|
);
|
||||||
|
|
||||||
new_leaf_actions.perform(&self.gossip_handle);
|
new_leaf_actions.perform(&self.gossip_handle);
|
||||||
|
|
||||||
self.protocol_handler.consensus_instances.insert(
|
self.protocol_handler.consensus_instances.insert(
|
||||||
relay_parent,
|
relay_parent.clone(),
|
||||||
ConsensusNetworkingInstance {
|
ConsensusNetworkingInstance {
|
||||||
statement_table: table.clone(),
|
statement_table: table.clone(),
|
||||||
relay_parent,
|
relay_parent: relay_parent.clone(),
|
||||||
attestation_topic: crate::legacy::gossip::attestation_topic(relay_parent),
|
attestation_topic: crate::legacy::gossip::attestation_topic(relay_parent.clone()),
|
||||||
_drop_signal: signal,
|
_drop_signal: signal,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -1324,7 +1325,7 @@ impl ParachainNetwork for Service {
|
|||||||
) -> Self::BuildTableRouter {
|
) -> Self::BuildTableRouter {
|
||||||
let authorities = authorities.to_vec();
|
let authorities = authorities.to_vec();
|
||||||
let mut sender = self.sender.clone();
|
let mut sender = self.sender.clone();
|
||||||
let relay_parent = table.consensus_parent_hash().clone();
|
let relay_parent = table.signing_context().parent_hash.clone();
|
||||||
|
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
sender.send(
|
sender.send(
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use polkadot_primitives::{Block, Header, BlockId};
|
|||||||
use polkadot_primitives::parachain::{
|
use polkadot_primitives::parachain::{
|
||||||
Id as ParaId, Chain, DutyRoster, ParachainHost, ValidatorId,
|
Id as ParaId, Chain, DutyRoster, ParachainHost, ValidatorId,
|
||||||
Retriable, CollatorId, AbridgedCandidateReceipt,
|
Retriable, CollatorId, AbridgedCandidateReceipt,
|
||||||
GlobalValidationSchedule, LocalValidationData, ErasureChunk,
|
GlobalValidationSchedule, LocalValidationData, ErasureChunk, SigningContext,
|
||||||
};
|
};
|
||||||
use polkadot_validation::SharedTable;
|
use polkadot_validation::SharedTable;
|
||||||
|
|
||||||
@@ -114,7 +114,6 @@ impl crate::legacy::GossipService for MockGossip {
|
|||||||
impl GossipOps for MockGossip {
|
impl GossipOps for MockGossip {
|
||||||
fn new_local_leaf(
|
fn new_local_leaf(
|
||||||
&self,
|
&self,
|
||||||
_relay_parent: Hash,
|
|
||||||
_validation_data: crate::legacy::gossip::MessageValidationData,
|
_validation_data: crate::legacy::gossip::MessageValidationData,
|
||||||
) -> crate::legacy::gossip::NewLeafActions {
|
) -> crate::legacy::gossip::NewLeafActions {
|
||||||
crate::legacy::gossip::NewLeafActions::new()
|
crate::legacy::gossip::NewLeafActions::new()
|
||||||
@@ -294,6 +293,22 @@ impl ParachainHost<Block> for RuntimeApi {
|
|||||||
) -> ClientResult<NativeOrEncoded<Option<Vec<AbridgedCandidateReceipt>>>> {
|
) -> ClientResult<NativeOrEncoded<Option<Vec<AbridgedCandidateReceipt>>>> {
|
||||||
Ok(NativeOrEncoded::Native(Some(Vec::new())))
|
Ok(NativeOrEncoded::Native(Some(Vec::new())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ParachainHost_signing_context_runtime_api_impl(
|
||||||
|
&self,
|
||||||
|
_at: &BlockId,
|
||||||
|
_: ExecutionContext,
|
||||||
|
_: Option<()>,
|
||||||
|
_: Vec<u8>,
|
||||||
|
) -> ClientResult<NativeOrEncoded<SigningContext>> {
|
||||||
|
Ok(NativeOrEncoded::Native(
|
||||||
|
SigningContext {
|
||||||
|
session_index: Default::default(),
|
||||||
|
parent_hash: Default::default(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::Service {
|
impl super::Service {
|
||||||
@@ -389,11 +404,15 @@ fn consensus_instances_cleaned_up() {
|
|||||||
let relay_parent = [0; 32].into();
|
let relay_parent = [0; 32].into();
|
||||||
let authorities = Vec::new();
|
let authorities = Vec::new();
|
||||||
|
|
||||||
|
let signing_context = SigningContext {
|
||||||
|
session_index: Default::default(),
|
||||||
|
parent_hash: relay_parent,
|
||||||
|
};
|
||||||
let table = Arc::new(SharedTable::new(
|
let table = Arc::new(SharedTable::new(
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
HashMap::new(),
|
HashMap::new(),
|
||||||
None,
|
None,
|
||||||
relay_parent,
|
signing_context,
|
||||||
AvailabilityStore::new_in_memory(service.clone()),
|
AvailabilityStore::new_in_memory(service.clone()),
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ application-crypto = { package = "sp-application-crypto", git = "https://github.
|
|||||||
sp-api = { 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-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
|
sp-staking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
runtime_primitives = { package = "sp-runtime", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
runtime_primitives = { package = "sp-runtime", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
polkadot-parachain = { path = "../parachain", default-features = false }
|
polkadot-parachain = { path = "../parachain", default-features = false }
|
||||||
trie = { package = "sp-trie", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
trie = { package = "sp-trie", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
@@ -33,6 +34,7 @@ std = [
|
|||||||
"sp-api/std",
|
"sp-api/std",
|
||||||
"sp-std/std",
|
"sp-std/std",
|
||||||
"sp-version/std",
|
"sp-version/std",
|
||||||
|
"sp-staking/std",
|
||||||
"runtime_primitives/std",
|
"runtime_primitives/std",
|
||||||
"serde",
|
"serde",
|
||||||
"polkadot-parachain/std",
|
"polkadot-parachain/std",
|
||||||
|
|||||||
@@ -608,6 +608,15 @@ pub enum ValidityAttestation {
|
|||||||
Explicit(ValidatorSignature),
|
Explicit(ValidatorSignature),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A type returned by runtime with current session index and a parent hash.
|
||||||
|
#[derive(Clone, Eq, PartialEq, Default, Decode, Encode, RuntimeDebug)]
|
||||||
|
pub struct SigningContext {
|
||||||
|
/// Current session index.
|
||||||
|
pub session_index: sp_staking::SessionIndex,
|
||||||
|
/// Hash of the parent.
|
||||||
|
pub parent_hash: Hash,
|
||||||
|
}
|
||||||
|
|
||||||
/// An attested candidate. This is submitted to the relay chain by a block author.
|
/// An attested candidate. This is submitted to the relay chain by a block author.
|
||||||
#[derive(Clone, PartialEq, Decode, Encode, RuntimeDebug)]
|
#[derive(Clone, PartialEq, Decode, Encode, RuntimeDebug)]
|
||||||
pub struct AttestedCandidate {
|
pub struct AttestedCandidate {
|
||||||
@@ -655,7 +664,7 @@ impl FeeSchedule {
|
|||||||
|
|
||||||
sp_api::decl_runtime_apis! {
|
sp_api::decl_runtime_apis! {
|
||||||
/// The API for querying the state of parachains on-chain.
|
/// The API for querying the state of parachains on-chain.
|
||||||
#[api_version(2)]
|
#[api_version(3)]
|
||||||
pub trait ParachainHost {
|
pub trait ParachainHost {
|
||||||
/// Get the current validators.
|
/// Get the current validators.
|
||||||
fn validators() -> Vec<ValidatorId>;
|
fn validators() -> Vec<ValidatorId>;
|
||||||
@@ -673,6 +682,8 @@ sp_api::decl_runtime_apis! {
|
|||||||
/// Extract the abridged head that was set in the extrinsics.
|
/// Extract the abridged head that was set in the extrinsics.
|
||||||
fn get_heads(extrinsics: Vec<<Block as BlockT>::Extrinsic>)
|
fn get_heads(extrinsics: Vec<<Block as BlockT>::Extrinsic>)
|
||||||
-> Option<Vec<AbridgedCandidateReceipt>>;
|
-> Option<Vec<AbridgedCandidateReceipt>>;
|
||||||
|
/// Get a `SigningContext` with current `SessionIndex` and parent hash.
|
||||||
|
fn signing_context() -> SigningContext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ use primitives::{
|
|||||||
UpwardMessage, ValidatorId, ActiveParas, CollatorId, Retriable, OmittedValidationData,
|
UpwardMessage, ValidatorId, ActiveParas, CollatorId, Retriable, OmittedValidationData,
|
||||||
CandidateReceipt, GlobalValidationSchedule, AbridgedCandidateReceipt,
|
CandidateReceipt, GlobalValidationSchedule, AbridgedCandidateReceipt,
|
||||||
LocalValidationData, ValidityAttestation, NEW_HEADS_IDENTIFIER, PARACHAIN_KEY_TYPE_ID,
|
LocalValidationData, ValidityAttestation, NEW_HEADS_IDENTIFIER, PARACHAIN_KEY_TYPE_ID,
|
||||||
ValidatorSignature,
|
ValidatorSignature, SigningContext,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
@@ -121,7 +121,7 @@ pub struct ValidatorIdentities<T>(sp_std::marker::PhantomData<T>);
|
|||||||
/// `Hash` - a type of a hash used in the runtime.
|
/// `Hash` - a type of a hash used in the runtime.
|
||||||
#[derive(RuntimeDebug, Encode, Decode)]
|
#[derive(RuntimeDebug, Encode, Decode)]
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub struct DoubleVoteReport<Proof, Hash> {
|
pub struct DoubleVoteReport<Proof> {
|
||||||
/// Identity of the double-voter.
|
/// Identity of the double-voter.
|
||||||
pub identity: ValidatorId,
|
pub identity: ValidatorId,
|
||||||
/// First vote of the double-vote.
|
/// First vote of the double-vote.
|
||||||
@@ -130,11 +130,11 @@ pub struct DoubleVoteReport<Proof, Hash> {
|
|||||||
pub second: (Statement, ValidatorSignature),
|
pub second: (Statement, ValidatorSignature),
|
||||||
/// Proof that the validator with `identity` id was actually a validator at `parent_hash`.
|
/// Proof that the validator with `identity` id was actually a validator at `parent_hash`.
|
||||||
pub proof: Proof,
|
pub proof: Proof,
|
||||||
/// Parent hash of the block this offence was commited.
|
/// A `SigningContext` with a session and a parent hash of the moment this offence was commited.
|
||||||
pub parent_hash: Hash,
|
pub signing_context: SigningContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Proof: Parameter + GetSessionNumber, Hash: AsRef<[u8]>> DoubleVoteReport<Proof, Hash> {
|
impl<Proof: Parameter + GetSessionNumber> DoubleVoteReport<Proof> {
|
||||||
fn verify<T: Trait<Proof = Proof>>(
|
fn verify<T: Trait<Proof = Proof>>(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<(), DoubleVoteValidityError> {
|
) -> Result<(), DoubleVoteValidityError> {
|
||||||
@@ -145,9 +145,21 @@ impl<Proof: Parameter + GetSessionNumber, Hash: AsRef<[u8]>> DoubleVoteReport<Pr
|
|||||||
T::KeyOwnerProofSystem::check_proof((PARACHAIN_KEY_TYPE_ID, id), self.proof.clone())
|
T::KeyOwnerProofSystem::check_proof((PARACHAIN_KEY_TYPE_ID, id), self.proof.clone())
|
||||||
.ok_or(DoubleVoteValidityError::InvalidProof)?;
|
.ok_or(DoubleVoteValidityError::InvalidProof)?;
|
||||||
|
|
||||||
|
if self.proof.session() != self.signing_context.session_index {
|
||||||
|
return Err(DoubleVoteValidityError::InvalidReport);
|
||||||
|
}
|
||||||
|
|
||||||
// Check signatures.
|
// Check signatures.
|
||||||
Self::verify_vote(&first, &self.parent_hash, &self.identity)?;
|
Self::verify_vote(
|
||||||
Self::verify_vote(&second, &self.parent_hash, &self.identity)?;
|
&first,
|
||||||
|
&self.signing_context,
|
||||||
|
&self.identity,
|
||||||
|
)?;
|
||||||
|
Self::verify_vote(
|
||||||
|
&second,
|
||||||
|
&self.signing_context,
|
||||||
|
&self.identity,
|
||||||
|
)?;
|
||||||
|
|
||||||
match (&first.0, &second.0) {
|
match (&first.0, &second.0) {
|
||||||
// If issuing a `Candidate` message on a parachain block, neither a `Valid` or
|
// If issuing a `Candidate` message on a parachain block, neither a `Valid` or
|
||||||
@@ -173,10 +185,10 @@ impl<Proof: Parameter + GetSessionNumber, Hash: AsRef<[u8]>> DoubleVoteReport<Pr
|
|||||||
|
|
||||||
fn verify_vote(
|
fn verify_vote(
|
||||||
vote: &(Statement, ValidatorSignature),
|
vote: &(Statement, ValidatorSignature),
|
||||||
parent_hash: &Hash,
|
signing_context: &SigningContext,
|
||||||
authority: &ValidatorId,
|
authority: &ValidatorId,
|
||||||
) -> Result<(), DoubleVoteValidityError> {
|
) -> Result<(), DoubleVoteValidityError> {
|
||||||
let payload = localized_payload(vote.0.clone(), parent_hash);
|
let payload = localized_payload(vote.0.clone(), signing_context);
|
||||||
|
|
||||||
if !vote.1.verify(&payload[..], authority) {
|
if !vote.1.verify(&payload[..], authority) {
|
||||||
return Err(DoubleVoteValidityError::InvalidSignature);
|
return Err(DoubleVoteValidityError::InvalidSignature);
|
||||||
@@ -203,7 +215,7 @@ impl GetSessionNumber for session::historical::Proof {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Trait: attestations::Trait + session::historical::Trait + staking::Trait {
|
pub trait Trait: attestations::Trait + session::historical::Trait {
|
||||||
/// The outer origin type.
|
/// The outer origin type.
|
||||||
type Origin: From<Origin> + From<system::RawOrigin<Self::AccountId>>;
|
type Origin: From<Origin> + From<system::RawOrigin<Self::AccountId>>;
|
||||||
|
|
||||||
@@ -253,6 +265,9 @@ pub trait Trait: attestations::Trait + session::historical::Trait + staking::Tra
|
|||||||
Self::IdentificationTuple,
|
Self::IdentificationTuple,
|
||||||
DoubleVoteOffence<Self::IdentificationTuple>
|
DoubleVoteOffence<Self::IdentificationTuple>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
/// A type that converts the opaque hash type to exact one.
|
||||||
|
type BlockHashConversion: Convert<Self::Hash, primitives::Hash>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Origin for the parachains module.
|
/// Origin for the parachains module.
|
||||||
@@ -332,18 +347,6 @@ decl_storage! {
|
|||||||
///
|
///
|
||||||
/// `None` if not yet updated.
|
/// `None` if not yet updated.
|
||||||
pub DidUpdate: Option<Vec<ParaId>>;
|
pub DidUpdate: Option<Vec<ParaId>>;
|
||||||
|
|
||||||
/// The mapping from parent block hashes to session indexes.
|
|
||||||
///
|
|
||||||
/// Used for double vote report validation.
|
|
||||||
pub ParentToSessionIndex get(fn session_at_block):
|
|
||||||
map hasher(twox_64_concat) T::Hash => SessionIndex;
|
|
||||||
|
|
||||||
/// The era that is active currently.
|
|
||||||
///
|
|
||||||
/// Changes with the `ActiveEra` from `staking`. Upon these changes `ParentToSessionIndex`
|
|
||||||
/// is pruned.
|
|
||||||
ActiveEra get(fn active_era): Option<staking::EraIndex>;
|
|
||||||
}
|
}
|
||||||
add_extra_genesis {
|
add_extra_genesis {
|
||||||
config(authorities): Vec<ValidatorId>;
|
config(authorities): Vec<ValidatorId>;
|
||||||
@@ -484,7 +487,6 @@ decl_module! {
|
|||||||
origin,
|
origin,
|
||||||
report: DoubleVoteReport<
|
report: DoubleVoteReport<
|
||||||
<T::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::Proof,
|
<T::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::Proof,
|
||||||
T::Hash,
|
|
||||||
>,
|
>,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
let reporter = ensure_signed(origin)?;
|
let reporter = ensure_signed(origin)?;
|
||||||
@@ -519,26 +521,6 @@ decl_module! {
|
|||||||
fn on_initialize() -> Weight {
|
fn on_initialize() -> Weight {
|
||||||
<Self as Store>::DidUpdate::kill();
|
<Self as Store>::DidUpdate::kill();
|
||||||
|
|
||||||
let current_session = <session::Module<T>>::current_index();
|
|
||||||
let parent_hash = <system::Module<T>>::parent_hash();
|
|
||||||
|
|
||||||
match Self::active_era() {
|
|
||||||
Some(era) => {
|
|
||||||
if let Some(active_era) = <staking::Module<T>>::current_era() {
|
|
||||||
if era != active_era {
|
|
||||||
<Self as Store>::ActiveEra::put(active_era);
|
|
||||||
<ParentToSessionIndex<T>>::remove_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
if let Some(active_era) = <staking::Module<T>>::current_era() {
|
|
||||||
<Self as Store>::ActiveEra::set(Some(active_era));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
<ParentToSessionIndex<T>>::insert(parent_hash, current_session);
|
|
||||||
|
|
||||||
SimpleDispatchInfo::default().weigh_data(())
|
SimpleDispatchInfo::default().weigh_data(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,9 +534,12 @@ fn majority_of(list_len: usize) -> usize {
|
|||||||
list_len / 2 + list_len % 2
|
list_len / 2 + list_len % 2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn localized_payload<H: AsRef<[u8]>>(statement: Statement, parent_hash: H) -> Vec<u8> {
|
fn localized_payload(
|
||||||
|
statement: Statement,
|
||||||
|
signing_context: &SigningContext,
|
||||||
|
) -> Vec<u8> {
|
||||||
let mut encoded = statement.encode();
|
let mut encoded = statement.encode();
|
||||||
encoded.extend(parent_hash.as_ref());
|
signing_context.using_encoded(|s| encoded.extend(s));
|
||||||
encoded
|
encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,6 +561,17 @@ impl<T: Trait> Module<T> {
|
|||||||
<Heads>::remove(id);
|
<Heads>::remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a `SigningContext` with a current `SessionIndex` and parent hash.
|
||||||
|
pub fn signing_context() -> SigningContext {
|
||||||
|
let session_index = <session::Module<T>>::current_index();
|
||||||
|
let parent_hash = <system::Module<T>>::parent_hash();
|
||||||
|
|
||||||
|
SigningContext {
|
||||||
|
session_index,
|
||||||
|
parent_hash: T::BlockHashConversion::convert(parent_hash),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Dispatch some messages from a parachain.
|
/// Dispatch some messages from a parachain.
|
||||||
fn dispatch_message(
|
fn dispatch_message(
|
||||||
id: ParaId,
|
id: ParaId,
|
||||||
@@ -912,7 +908,8 @@ impl<T: Trait> Module<T> {
|
|||||||
let sorted_validators = make_sorted_duties(&duty_roster.validator_duty);
|
let sorted_validators = make_sorted_duties(&duty_roster.validator_duty);
|
||||||
|
|
||||||
let parent_hash = <system::Module<T>>::parent_hash();
|
let parent_hash = <system::Module<T>>::parent_hash();
|
||||||
let localized_payload = |statement: Statement| localized_payload(statement, parent_hash);
|
let signing_context = Self::signing_context();
|
||||||
|
let localized_payload = |statement: Statement| localized_payload(statement, &signing_context);
|
||||||
|
|
||||||
let mut validator_groups = GroupedDutyIter::new(&sorted_validators[..]);
|
let mut validator_groups = GroupedDutyIter::new(&sorted_validators[..]);
|
||||||
|
|
||||||
@@ -1160,9 +1157,8 @@ impl<T: Trait + Send + Sync> SignedExtension for ValidateDoubleVoteReports<T> wh
|
|||||||
if let Some(local_call) = call.is_sub_type() {
|
if let Some(local_call) = call.is_sub_type() {
|
||||||
if let Call::report_double_vote(report) = local_call {
|
if let Call::report_double_vote(report) = local_call {
|
||||||
let validators = <session::Module<T>>::validators();
|
let validators = <session::Module<T>>::validators();
|
||||||
let parent_hash = report.parent_hash;
|
|
||||||
|
|
||||||
let expected_session = Module::<T>::session_at_block(parent_hash);
|
let expected_session = report.signing_context.session_index;
|
||||||
let session = report.proof.session();
|
let session = report.proof.session();
|
||||||
|
|
||||||
if session != expected_session {
|
if session != expected_session {
|
||||||
@@ -1467,6 +1463,7 @@ mod tests {
|
|||||||
type Proof = <Historical as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::Proof;
|
type Proof = <Historical as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::Proof;
|
||||||
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
|
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
|
||||||
type ReportOffence = Offences;
|
type ReportOffence = Offences;
|
||||||
|
type BlockHashConversion = sp_runtime::traits::Identity;
|
||||||
type KeyOwnerProofSystem = Historical;
|
type KeyOwnerProofSystem = Historical;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1559,7 +1556,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn report_double_vote(
|
fn report_double_vote(
|
||||||
report: DoubleVoteReport<session::historical::Proof, <Test as system::Trait>::Hash>,
|
report: DoubleVoteReport<session::historical::Proof>,
|
||||||
) -> Result<ParachainsCall<Test>, TransactionValidityError> {
|
) -> Result<ParachainsCall<Test>, TransactionValidityError> {
|
||||||
let inner = ParachainsCall::report_double_vote(report);
|
let inner = ParachainsCall::report_double_vote(report);
|
||||||
let call = Call::Parachains(inner.clone());
|
let call = Call::Parachains(inner.clone());
|
||||||
@@ -1604,7 +1601,6 @@ mod tests {
|
|||||||
|
|
||||||
fn make_attestations(candidate: &mut AttestedCandidate) {
|
fn make_attestations(candidate: &mut AttestedCandidate) {
|
||||||
let mut vote_implicit = false;
|
let mut vote_implicit = false;
|
||||||
let parent_hash = <system::Module<Test>>::parent_hash();
|
|
||||||
|
|
||||||
let (duty_roster, _) = Parachains::calculate_duty_roster();
|
let (duty_roster, _) = Parachains::calculate_duty_roster();
|
||||||
let candidate_hash = candidate.candidate.hash();
|
let candidate_hash = candidate.candidate.hash();
|
||||||
@@ -1632,7 +1628,8 @@ mod tests {
|
|||||||
Statement::Valid(candidate_hash.clone())
|
Statement::Valid(candidate_hash.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
let payload = localized_payload(statement, parent_hash);
|
let signing_context = Parachains::signing_context();
|
||||||
|
let payload = localized_payload(statement, &signing_context);
|
||||||
let signature = key.sign(&payload[..]).into();
|
let signature = key.sign(&payload[..]).into();
|
||||||
|
|
||||||
candidate.validity_votes.push(if vote_implicit {
|
candidate.validity_votes.push(if vote_implicit {
|
||||||
@@ -2209,10 +2206,10 @@ mod tests {
|
|||||||
|
|
||||||
let statement_candidate = Statement::Candidate(candidate_hash.clone());
|
let statement_candidate = Statement::Candidate(candidate_hash.clone());
|
||||||
let statement_valid = Statement::Valid(candidate_hash.clone());
|
let statement_valid = Statement::Valid(candidate_hash.clone());
|
||||||
let parent_hash = System::parent_hash();
|
|
||||||
|
|
||||||
let payload_1 = localized_payload(statement_candidate.clone(), parent_hash);
|
let signing_context = Parachains::signing_context();
|
||||||
let payload_2 = localized_payload(statement_valid.clone(), parent_hash);
|
let payload_1 = localized_payload(statement_candidate.clone(), &signing_context);
|
||||||
|
let payload_2 = localized_payload(statement_valid.clone(), &signing_context);
|
||||||
|
|
||||||
let signature_1 = key.sign(&payload_1[..]).into();
|
let signature_1 = key.sign(&payload_1[..]).into();
|
||||||
let signature_2 = key.sign(&payload_2[..]).into();
|
let signature_2 = key.sign(&payload_2[..]).into();
|
||||||
@@ -2240,7 +2237,7 @@ mod tests {
|
|||||||
first: (statement_candidate, signature_1),
|
first: (statement_candidate, signature_1),
|
||||||
second: (statement_valid, signature_2),
|
second: (statement_valid, signature_2),
|
||||||
proof,
|
proof,
|
||||||
parent_hash,
|
signing_context,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inner = report_double_vote(report).unwrap();
|
let inner = report_double_vote(report).unwrap();
|
||||||
@@ -2304,10 +2301,10 @@ mod tests {
|
|||||||
|
|
||||||
let statement_candidate = Statement::Candidate(candidate_hash);
|
let statement_candidate = Statement::Candidate(candidate_hash);
|
||||||
let statement_invalid = Statement::Invalid(candidate_hash.clone());
|
let statement_invalid = Statement::Invalid(candidate_hash.clone());
|
||||||
let parent_hash = System::parent_hash();
|
|
||||||
|
|
||||||
let payload_1 = localized_payload(statement_candidate.clone(), parent_hash);
|
let signing_context = Parachains::signing_context();
|
||||||
let payload_2 = localized_payload(statement_invalid.clone(), parent_hash);
|
let payload_1 = localized_payload(statement_candidate.clone(), &signing_context);
|
||||||
|
let payload_2 = localized_payload(statement_invalid.clone(), &signing_context);
|
||||||
|
|
||||||
let signature_1 = key.sign(&payload_1[..]).into();
|
let signature_1 = key.sign(&payload_1[..]).into();
|
||||||
let signature_2 = key.sign(&payload_2[..]).into();
|
let signature_2 = key.sign(&payload_2[..]).into();
|
||||||
@@ -2335,7 +2332,7 @@ mod tests {
|
|||||||
first: (statement_candidate, signature_1),
|
first: (statement_candidate, signature_1),
|
||||||
second: (statement_invalid, signature_2),
|
second: (statement_invalid, signature_2),
|
||||||
proof,
|
proof,
|
||||||
parent_hash,
|
signing_context,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ok!(Parachains::dispatch(
|
assert_ok!(Parachains::dispatch(
|
||||||
@@ -2401,10 +2398,10 @@ mod tests {
|
|||||||
|
|
||||||
let statement_invalid = Statement::Invalid(candidate_hash.clone());
|
let statement_invalid = Statement::Invalid(candidate_hash.clone());
|
||||||
let statement_valid = Statement::Valid(candidate_hash.clone());
|
let statement_valid = Statement::Valid(candidate_hash.clone());
|
||||||
let parent_hash = System::parent_hash();
|
|
||||||
|
|
||||||
let payload_1 = localized_payload(statement_invalid.clone(), parent_hash);
|
let signing_context = Parachains::signing_context();
|
||||||
let payload_2 = localized_payload(statement_valid.clone(), parent_hash);
|
let payload_1 = localized_payload(statement_invalid.clone(), &signing_context);
|
||||||
|
let payload_2 = localized_payload(statement_valid.clone(), &signing_context);
|
||||||
|
|
||||||
let signature_1 = key.sign(&payload_1[..]).into();
|
let signature_1 = key.sign(&payload_1[..]).into();
|
||||||
let signature_2 = key.sign(&payload_2[..]).into();
|
let signature_2 = key.sign(&payload_2[..]).into();
|
||||||
@@ -2432,7 +2429,7 @@ mod tests {
|
|||||||
first: (statement_invalid, signature_1),
|
first: (statement_invalid, signature_1),
|
||||||
second: (statement_valid, signature_2),
|
second: (statement_valid, signature_2),
|
||||||
proof,
|
proof,
|
||||||
parent_hash,
|
signing_context,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ok!(Parachains::dispatch(
|
assert_ok!(Parachains::dispatch(
|
||||||
@@ -2501,10 +2498,10 @@ mod tests {
|
|||||||
|
|
||||||
let statement_candidate = Statement::Candidate(candidate_hash.clone());
|
let statement_candidate = Statement::Candidate(candidate_hash.clone());
|
||||||
let statement_valid = Statement::Valid(candidate_hash.clone());
|
let statement_valid = Statement::Valid(candidate_hash.clone());
|
||||||
let parent_hash = System::parent_hash();
|
|
||||||
|
|
||||||
let payload_1 = localized_payload(statement_candidate.clone(), parent_hash);
|
let signing_context = Parachains::signing_context();
|
||||||
let payload_2 = localized_payload(statement_valid.clone(), parent_hash);
|
let payload_1 = localized_payload(statement_candidate.clone(), &signing_context);
|
||||||
|
let payload_2 = localized_payload(statement_valid.clone(), &signing_context);
|
||||||
|
|
||||||
let signature_1 = key.sign(&payload_1[..]).into();
|
let signature_1 = key.sign(&payload_1[..]).into();
|
||||||
let signature_2 = key.sign(&payload_2[..]).into();
|
let signature_2 = key.sign(&payload_2[..]).into();
|
||||||
@@ -2532,7 +2529,7 @@ mod tests {
|
|||||||
first: (statement_candidate, signature_1),
|
first: (statement_candidate, signature_1),
|
||||||
second: (statement_valid, signature_2),
|
second: (statement_valid, signature_2),
|
||||||
proof,
|
proof,
|
||||||
parent_hash,
|
signing_context,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ok!(Parachains::dispatch(
|
assert_ok!(Parachains::dispatch(
|
||||||
@@ -2609,10 +2606,10 @@ mod tests {
|
|||||||
|
|
||||||
let statement_candidate = Statement::Candidate(candidate_hash.clone());
|
let statement_candidate = Statement::Candidate(candidate_hash.clone());
|
||||||
let statement_valid = Statement::Valid(candidate_hash.clone());
|
let statement_valid = Statement::Valid(candidate_hash.clone());
|
||||||
let parent_hash = System::parent_hash();
|
|
||||||
|
|
||||||
let payload_1 = localized_payload(statement_candidate.clone(), parent_hash);
|
let signing_context = Parachains::signing_context();
|
||||||
let payload_2 = localized_payload(statement_valid.clone(), parent_hash);
|
let payload_1 = localized_payload(statement_candidate.clone(), &signing_context);
|
||||||
|
let payload_2 = localized_payload(statement_valid.clone(), &signing_context);
|
||||||
|
|
||||||
let signature_1 = key_1.sign(&payload_1[..]).into();
|
let signature_1 = key_1.sign(&payload_1[..]).into();
|
||||||
let signature_2 = key_2.sign(&payload_2[..]).into();
|
let signature_2 = key_2.sign(&payload_2[..]).into();
|
||||||
@@ -2625,7 +2622,7 @@ mod tests {
|
|||||||
first: (statement_candidate, signature_1),
|
first: (statement_candidate, signature_1),
|
||||||
second: (statement_valid, signature_2),
|
second: (statement_valid, signature_2),
|
||||||
proof,
|
proof,
|
||||||
parent_hash,
|
signing_context,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -2669,8 +2666,12 @@ mod tests {
|
|||||||
let statement_valid = Statement::Valid(candidate_hash.clone());
|
let statement_valid = Statement::Valid(candidate_hash.clone());
|
||||||
let parent_hash = System::parent_hash();
|
let parent_hash = System::parent_hash();
|
||||||
|
|
||||||
let payload_1 = localized_payload(statement_candidate.clone(), parent_hash);
|
let signing_context = SigningContext {
|
||||||
let payload_2 = localized_payload(statement_valid.clone(), parent_hash);
|
session_index: Session::current_index() - 1,
|
||||||
|
parent_hash,
|
||||||
|
};
|
||||||
|
let payload_1 = localized_payload(statement_candidate.clone(), &signing_context);
|
||||||
|
let payload_2 = localized_payload(statement_valid.clone(), &signing_context);
|
||||||
|
|
||||||
let signature_1 = key.sign(&payload_1[..]).into();
|
let signature_1 = key.sign(&payload_1[..]).into();
|
||||||
let signature_2 = key.sign(&payload_2[..]).into();
|
let signature_2 = key.sign(&payload_2[..]).into();
|
||||||
@@ -2700,7 +2701,7 @@ mod tests {
|
|||||||
first: (statement_candidate, signature_1),
|
first: (statement_candidate, signature_1),
|
||||||
second: (statement_valid, signature_2),
|
second: (statement_valid, signature_2),
|
||||||
proof,
|
proof,
|
||||||
parent_hash,
|
signing_context,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(report_double_vote(report.clone()).is_err());
|
assert!(report_double_vote(report.clone()).is_err());
|
||||||
@@ -2723,29 +2724,4 @@ mod tests {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn double_vote_hash_to_session_gets_pruned() {
|
|
||||||
let parachains = vec![
|
|
||||||
(1u32.into(), vec![], vec![]),
|
|
||||||
];
|
|
||||||
|
|
||||||
// Test that `ParentToSessionIndex` is pruned upon eras turn.
|
|
||||||
new_test_ext(parachains.clone()).execute_with(|| {
|
|
||||||
start_era(1);
|
|
||||||
|
|
||||||
let parent_hash_1 = System::parent_hash();
|
|
||||||
// The mapping should know about the session at this block.
|
|
||||||
assert_eq!(Parachains::session_at_block(parent_hash_1), 3);
|
|
||||||
|
|
||||||
start_era(2);
|
|
||||||
|
|
||||||
let parent_hash_2 = System::parent_hash();
|
|
||||||
|
|
||||||
// Info about a block from pevious era is removed.
|
|
||||||
assert_eq!(Parachains::session_at_block(parent_hash_1), 0);
|
|
||||||
// Info about a block form this era is present.
|
|
||||||
assert_eq!(Parachains::session_at_block(parent_hash_2), 6);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -827,6 +827,7 @@ mod tests {
|
|||||||
type KeyOwnerProofSystem = session::historical::Module<Test>;
|
type KeyOwnerProofSystem = session::historical::Module<Test>;
|
||||||
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
|
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
|
||||||
type ReportOffence = ();
|
type ReportOffence = ();
|
||||||
|
type BlockHashConversion = sp_runtime::traits::Identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
@@ -973,7 +974,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
let (candidate, _) = candidate.abridge();
|
let (candidate, _) = candidate.abridge();
|
||||||
let candidate_hash = candidate.hash();
|
let candidate_hash = candidate.hash();
|
||||||
let payload = (Statement::Valid(candidate_hash), System::parent_hash()).encode();
|
let payload = (Statement::Valid(candidate_hash), session::Module::<Test>::current_index(), System::parent_hash()).encode();
|
||||||
let roster = Parachains::calculate_duty_roster().0.validator_duty;
|
let roster = Parachains::calculate_duty_roster().0.validator_duty;
|
||||||
AttestedCandidate {
|
AttestedCandidate {
|
||||||
candidate,
|
candidate,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use sp_core::u32_trait::{_1, _2, _3, _4, _5};
|
|||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
use primitives::{
|
use primitives::{
|
||||||
AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, Signature, Moment,
|
AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, Signature, Moment,
|
||||||
parachain::{self, ActiveParas, AbridgedCandidateReceipt}, ValidityError,
|
parachain::{self, ActiveParas, AbridgedCandidateReceipt, SigningContext}, ValidityError,
|
||||||
};
|
};
|
||||||
use runtime_common::{attestations, claims, parachains, registrar, slots,
|
use runtime_common::{attestations, claims, parachains, registrar, slots,
|
||||||
impls::{CurrencyToVoteHandler, TargetedFeeAdjustment, ToAuthor},
|
impls::{CurrencyToVoteHandler, TargetedFeeAdjustment, ToAuthor},
|
||||||
@@ -496,6 +496,7 @@ impl parachains::Trait for Runtime {
|
|||||||
type KeyOwnerProofSystem = session::historical::Module<Self>;
|
type KeyOwnerProofSystem = session::historical::Module<Self>;
|
||||||
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
|
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
|
||||||
type ReportOffence = Offences;
|
type ReportOffence = Offences;
|
||||||
|
type BlockHashConversion = sp_runtime::traits::Identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
@@ -816,6 +817,9 @@ sp_api::impl_runtime_apis! {
|
|||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fn signing_context() -> SigningContext {
|
||||||
|
Parachains::signing_context()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ use sp_core::u32_trait::{_1, _2, _3, _4, _5};
|
|||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
use primitives::{
|
use primitives::{
|
||||||
AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, Signature, Moment,
|
AccountId, AccountIndex, Balance, BlockNumber, Hash, Nonce, Signature, Moment,
|
||||||
parachain::{self, ActiveParas, AbridgedCandidateReceipt}, ValidityError,
|
parachain::{self, ActiveParas, AbridgedCandidateReceipt, SigningContext}, ValidityError,
|
||||||
};
|
};
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
create_runtime_str, generic, impl_opaque_keys,
|
create_runtime_str, generic, impl_opaque_keys,
|
||||||
@@ -504,6 +504,7 @@ impl parachains::Trait for Runtime {
|
|||||||
type KeyOwnerProofSystem = session::historical::Module<Self>;
|
type KeyOwnerProofSystem = session::historical::Module<Self>;
|
||||||
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
|
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
|
||||||
type ReportOffence = Offences;
|
type ReportOffence = Offences;
|
||||||
|
type BlockHashConversion = sp_runtime::traits::Identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
@@ -738,6 +739,9 @@ sp_api::impl_runtime_apis! {
|
|||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fn signing_context() -> SigningContext {
|
||||||
|
Parachains::signing_context()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ use rstd::prelude::*;
|
|||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
use primitives::{
|
use primitives::{
|
||||||
AccountId, AccountIndex, Balance, BlockNumber, Hash as HashT, Nonce, Signature, Moment,
|
AccountId, AccountIndex, Balance, BlockNumber, Hash as HashT, Nonce, Signature, Moment,
|
||||||
parachain::{self, ActiveParas, AbridgedCandidateReceipt}, ValidityError,
|
parachain::{self, ActiveParas, AbridgedCandidateReceipt, SigningContext}, ValidityError,
|
||||||
};
|
};
|
||||||
use runtime_common::{attestations, claims, parachains, registrar, slots,
|
use runtime_common::{attestations, claims, parachains, registrar, slots,
|
||||||
impls::{CurrencyToVoteHandler, TargetedFeeAdjustment},
|
impls::{CurrencyToVoteHandler, TargetedFeeAdjustment},
|
||||||
@@ -319,6 +319,7 @@ impl parachains::Trait for Runtime {
|
|||||||
Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>
|
Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>
|
||||||
>::IdentificationTuple;
|
>::IdentificationTuple;
|
||||||
type ReportOffence = Offences;
|
type ReportOffence = Offences;
|
||||||
|
type BlockHashConversion = sp_runtime::traits::Identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl offences::Trait for Runtime {
|
impl offences::Trait for Runtime {
|
||||||
@@ -536,6 +537,9 @@ sp_api::impl_runtime_apis! {
|
|||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fn signing_context() -> SigningContext {
|
||||||
|
Parachains::signing_context()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
||||||
|
|||||||
@@ -34,12 +34,11 @@ use std::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use polkadot_primitives::Hash;
|
|
||||||
use polkadot_primitives::parachain::{
|
use polkadot_primitives::parachain::{
|
||||||
Id as ParaId, Chain, DutyRoster, AbridgedCandidateReceipt,
|
Id as ParaId, Chain, DutyRoster, AbridgedCandidateReceipt,
|
||||||
Statement as PrimitiveStatement,
|
Statement as PrimitiveStatement,
|
||||||
PoVBlock, ErasureChunk, ValidatorSignature, ValidatorIndex,
|
PoVBlock, ErasureChunk, ValidatorSignature, ValidatorIndex,
|
||||||
ValidatorPair, ValidatorId,
|
ValidatorPair, ValidatorId, SigningContext,
|
||||||
};
|
};
|
||||||
use primitives::Pair;
|
use primitives::Pair;
|
||||||
|
|
||||||
@@ -135,9 +134,13 @@ pub struct GroupInfo {
|
|||||||
/// Sign a table statement against a parent hash.
|
/// Sign a table statement against a parent hash.
|
||||||
/// The actual message signed is the encoded statement concatenated with the
|
/// The actual message signed is the encoded statement concatenated with the
|
||||||
/// parent hash.
|
/// parent hash.
|
||||||
pub fn sign_table_statement(statement: &Statement, key: &ValidatorPair, parent_hash: &Hash) -> ValidatorSignature {
|
pub fn sign_table_statement(
|
||||||
|
statement: &Statement,
|
||||||
|
key: &ValidatorPair,
|
||||||
|
signing_context: &SigningContext,
|
||||||
|
) -> ValidatorSignature {
|
||||||
let mut encoded = PrimitiveStatement::from(statement).encode();
|
let mut encoded = PrimitiveStatement::from(statement).encode();
|
||||||
encoded.extend(parent_hash.as_ref());
|
encoded.extend(signing_context.encode());
|
||||||
|
|
||||||
key.sign(&encoded)
|
key.sign(&encoded)
|
||||||
}
|
}
|
||||||
@@ -147,12 +150,12 @@ pub fn check_statement(
|
|||||||
statement: &Statement,
|
statement: &Statement,
|
||||||
signature: &ValidatorSignature,
|
signature: &ValidatorSignature,
|
||||||
signer: ValidatorId,
|
signer: ValidatorId,
|
||||||
parent_hash: &Hash,
|
signing_context: &SigningContext,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
use runtime_primitives::traits::AppVerify;
|
use runtime_primitives::traits::AppVerify;
|
||||||
|
|
||||||
let mut encoded = PrimitiveStatement::from(statement).encode();
|
let mut encoded = PrimitiveStatement::from(statement).encode();
|
||||||
encoded.extend(parent_hash.as_ref());
|
encoded.extend(signing_context.encode());
|
||||||
|
|
||||||
signature.verify(&encoded[..], &signer)
|
signature.verify(&encoded[..], &signer)
|
||||||
}
|
}
|
||||||
@@ -214,11 +217,19 @@ mod tests {
|
|||||||
fn sign_and_check_statement() {
|
fn sign_and_check_statement() {
|
||||||
let statement: Statement = GenericStatement::Valid([1; 32].into());
|
let statement: Statement = GenericStatement::Valid([1; 32].into());
|
||||||
let parent_hash = [2; 32].into();
|
let parent_hash = [2; 32].into();
|
||||||
|
let signing_context = SigningContext {
|
||||||
|
session_index: Default::default(),
|
||||||
|
parent_hash,
|
||||||
|
};
|
||||||
|
|
||||||
let sig = sign_table_statement(&statement, &Sr25519Keyring::Alice.pair().into(), &parent_hash);
|
let sig = sign_table_statement(&statement, &Sr25519Keyring::Alice.pair().into(), &signing_context);
|
||||||
|
|
||||||
assert!(check_statement(&statement, &sig, Sr25519Keyring::Alice.public().into(), &parent_hash));
|
let wrong_signing_context = SigningContext {
|
||||||
assert!(!check_statement(&statement, &sig, Sr25519Keyring::Alice.public().into(), &[0xff; 32].into()));
|
session_index: Default::default(),
|
||||||
assert!(!check_statement(&statement, &sig, Sr25519Keyring::Bob.public().into(), &parent_hash));
|
parent_hash: [0xff; 32].into(),
|
||||||
|
};
|
||||||
|
assert!(check_statement(&statement, &sig, Sr25519Keyring::Alice.public().into(), &signing_context));
|
||||||
|
assert!(!check_statement(&statement, &sig, Sr25519Keyring::Alice.public().into(), &wrong_signing_context));
|
||||||
|
assert!(!check_statement(&statement, &sig, Sr25519Keyring::Bob.public().into(), &signing_context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use table::{self, Table, Context as TableContextTrait};
|
|||||||
use polkadot_primitives::{Block, Hash};
|
use polkadot_primitives::{Block, Hash};
|
||||||
use polkadot_primitives::parachain::{
|
use polkadot_primitives::parachain::{
|
||||||
Id as ParaId, AbridgedCandidateReceipt, ValidatorPair, ValidatorId,
|
Id as ParaId, AbridgedCandidateReceipt, ValidatorPair, ValidatorId,
|
||||||
AttestedCandidate, ParachainHost, PoVBlock, ValidatorIndex,
|
AttestedCandidate, ParachainHost, PoVBlock, ValidatorIndex, SigningContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -48,7 +48,7 @@ pub use table::{SignedStatement, Statement};
|
|||||||
pub use table::generic::Statement as GenericStatement;
|
pub use table::generic::Statement as GenericStatement;
|
||||||
|
|
||||||
struct TableContext {
|
struct TableContext {
|
||||||
parent_hash: Hash,
|
signing_context: SigningContext,
|
||||||
key: Option<Arc<ValidatorPair>>,
|
key: Option<Arc<ValidatorPair>>,
|
||||||
groups: HashMap<ParaId, GroupInfo>,
|
groups: HashMap<ParaId, GroupInfo>,
|
||||||
validators: Vec<ValidatorId>,
|
validators: Vec<ValidatorId>,
|
||||||
@@ -87,7 +87,12 @@ impl TableContext {
|
|||||||
fn sign_statement(&self, statement: table::Statement) -> Option<table::SignedStatement> {
|
fn sign_statement(&self, statement: table::Statement) -> Option<table::SignedStatement> {
|
||||||
self.local_index().and_then(move |sender|
|
self.local_index().and_then(move |sender|
|
||||||
self.key.as_ref()
|
self.key.as_ref()
|
||||||
.map(|key| crate::sign_table_statement(&statement, key, &self.parent_hash).into())
|
.map(|key| crate::sign_table_statement(
|
||||||
|
&statement,
|
||||||
|
key,
|
||||||
|
&self.signing_context,
|
||||||
|
).into()
|
||||||
|
)
|
||||||
.map(move |signature| table::SignedStatement { statement, signature, sender })
|
.map(move |signature| table::SignedStatement { statement, signature, sender })
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -189,7 +194,7 @@ impl SharedTableInner {
|
|||||||
|
|
||||||
work.map(|work| ParachainWork {
|
work.map(|work| ParachainWork {
|
||||||
availability_store: self.availability_store.clone(),
|
availability_store: self.availability_store.clone(),
|
||||||
relay_parent: context.parent_hash.clone(),
|
relay_parent: context.signing_context.parent_hash.clone(),
|
||||||
work,
|
work,
|
||||||
max_block_data_size,
|
max_block_data_size,
|
||||||
n_validators: context.validators.len(),
|
n_validators: context.validators.len(),
|
||||||
@@ -408,12 +413,12 @@ impl SharedTable {
|
|||||||
validators: Vec<ValidatorId>,
|
validators: Vec<ValidatorId>,
|
||||||
groups: HashMap<ParaId, GroupInfo>,
|
groups: HashMap<ParaId, GroupInfo>,
|
||||||
key: Option<Arc<ValidatorPair>>,
|
key: Option<Arc<ValidatorPair>>,
|
||||||
parent_hash: Hash,
|
signing_context: SigningContext,
|
||||||
availability_store: AvailabilityStore,
|
availability_store: AvailabilityStore,
|
||||||
max_block_data_size: Option<u64>,
|
max_block_data_size: Option<u64>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
SharedTable {
|
SharedTable {
|
||||||
context: Arc::new(TableContext { groups, key, parent_hash, validators: validators.clone(), }),
|
context: Arc::new(TableContext { groups, key, signing_context, validators: validators.clone(), }),
|
||||||
max_block_data_size,
|
max_block_data_size,
|
||||||
inner: Arc::new(Mutex::new(SharedTableInner {
|
inner: Arc::new(Mutex::new(SharedTableInner {
|
||||||
table: Table::default(),
|
table: Table::default(),
|
||||||
@@ -425,8 +430,8 @@ impl SharedTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the parent hash this table should hold statements localized to.
|
/// Get the parent hash this table should hold statements localized to.
|
||||||
pub fn consensus_parent_hash(&self) -> &Hash {
|
pub fn signing_context(&self) -> &SigningContext {
|
||||||
&self.context.parent_hash
|
&self.context.signing_context
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the local validator session key.
|
/// Get the local validator session key.
|
||||||
@@ -654,7 +659,11 @@ mod tests {
|
|||||||
let mut groups = HashMap::new();
|
let mut groups = HashMap::new();
|
||||||
|
|
||||||
let para_id = ParaId::from(1);
|
let para_id = ParaId::from(1);
|
||||||
let parent_hash = Default::default();
|
let parent_hash = Hash::default();
|
||||||
|
let signing_context = SigningContext {
|
||||||
|
session_index: Default::default(),
|
||||||
|
parent_hash: parent_hash.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
let local_key = Sr25519Keyring::Alice.pair();
|
let local_key = Sr25519Keyring::Alice.pair();
|
||||||
let local_id: ValidatorId = local_key.public().into();
|
let local_id: ValidatorId = local_key.public().into();
|
||||||
@@ -673,7 +682,7 @@ mod tests {
|
|||||||
[local_id, validity_other].to_vec(),
|
[local_id, validity_other].to_vec(),
|
||||||
groups,
|
groups,
|
||||||
Some(local_key.clone()),
|
Some(local_key.clone()),
|
||||||
parent_hash,
|
signing_context.clone(),
|
||||||
AvailabilityStore::new_in_memory(DummyErasureNetworking),
|
AvailabilityStore::new_in_memory(DummyErasureNetworking),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@@ -684,7 +693,11 @@ mod tests {
|
|||||||
|
|
||||||
let candidate_statement = GenericStatement::Candidate(candidate);
|
let candidate_statement = GenericStatement::Candidate(candidate);
|
||||||
|
|
||||||
let signature = crate::sign_table_statement(&candidate_statement, &validity_other_key.into(), &parent_hash);
|
let signature = crate::sign_table_statement(
|
||||||
|
&candidate_statement,
|
||||||
|
&validity_other_key.into(),
|
||||||
|
&signing_context,
|
||||||
|
);
|
||||||
let signed_statement = ::table::generic::SignedStatement {
|
let signed_statement = ::table::generic::SignedStatement {
|
||||||
statement: candidate_statement,
|
statement: candidate_statement,
|
||||||
signature: signature.into(),
|
signature: signature.into(),
|
||||||
@@ -702,7 +715,11 @@ mod tests {
|
|||||||
let mut groups = HashMap::new();
|
let mut groups = HashMap::new();
|
||||||
|
|
||||||
let para_id = ParaId::from(1);
|
let para_id = ParaId::from(1);
|
||||||
let parent_hash = Default::default();
|
let parent_hash = Hash::default();
|
||||||
|
let signing_context = SigningContext {
|
||||||
|
session_index: Default::default(),
|
||||||
|
parent_hash: parent_hash.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
let local_key = Sr25519Keyring::Alice.pair();
|
let local_key = Sr25519Keyring::Alice.pair();
|
||||||
let local_id: ValidatorId = local_key.public().into();
|
let local_id: ValidatorId = local_key.public().into();
|
||||||
@@ -721,7 +738,7 @@ mod tests {
|
|||||||
[local_id, validity_other].to_vec(),
|
[local_id, validity_other].to_vec(),
|
||||||
groups,
|
groups,
|
||||||
Some(local_key.clone()),
|
Some(local_key.clone()),
|
||||||
parent_hash,
|
signing_context.clone(),
|
||||||
AvailabilityStore::new_in_memory(DummyErasureNetworking),
|
AvailabilityStore::new_in_memory(DummyErasureNetworking),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@@ -732,7 +749,11 @@ mod tests {
|
|||||||
|
|
||||||
let candidate_statement = GenericStatement::Candidate(candidate);
|
let candidate_statement = GenericStatement::Candidate(candidate);
|
||||||
|
|
||||||
let signature = crate::sign_table_statement(&candidate_statement, &validity_other_key.into(), &parent_hash);
|
let signature = crate::sign_table_statement(
|
||||||
|
&candidate_statement,
|
||||||
|
&validity_other_key.into(),
|
||||||
|
&signing_context,
|
||||||
|
);
|
||||||
let signed_statement = ::table::generic::SignedStatement {
|
let signed_statement = ::table::generic::SignedStatement {
|
||||||
statement: candidate_statement,
|
statement: candidate_statement,
|
||||||
signature: signature.into(),
|
signature: signature.into(),
|
||||||
@@ -874,7 +895,11 @@ mod tests {
|
|||||||
let mut groups = HashMap::new();
|
let mut groups = HashMap::new();
|
||||||
|
|
||||||
let para_id = ParaId::from(1);
|
let para_id = ParaId::from(1);
|
||||||
let parent_hash = Default::default();
|
let parent_hash = Hash::default();
|
||||||
|
let signing_context = SigningContext {
|
||||||
|
session_index: Default::default(),
|
||||||
|
parent_hash: parent_hash.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
let local_key = Sr25519Keyring::Alice.pair();
|
let local_key = Sr25519Keyring::Alice.pair();
|
||||||
let local_id: ValidatorId = local_key.public().into();
|
let local_id: ValidatorId = local_key.public().into();
|
||||||
@@ -893,7 +918,7 @@ mod tests {
|
|||||||
[local_id, validity_other].to_vec(),
|
[local_id, validity_other].to_vec(),
|
||||||
groups,
|
groups,
|
||||||
Some(local_key.clone()),
|
Some(local_key.clone()),
|
||||||
parent_hash,
|
signing_context.clone(),
|
||||||
AvailabilityStore::new_in_memory(DummyErasureNetworking),
|
AvailabilityStore::new_in_memory(DummyErasureNetworking),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@@ -905,7 +930,11 @@ mod tests {
|
|||||||
let candidate_hash = candidate.hash();
|
let candidate_hash = candidate.hash();
|
||||||
let candidate_statement = GenericStatement::Candidate(candidate);
|
let candidate_statement = GenericStatement::Candidate(candidate);
|
||||||
|
|
||||||
let signature = crate::sign_table_statement(&candidate_statement, &validity_other_key.into(), &parent_hash);
|
let signature = crate::sign_table_statement(
|
||||||
|
&candidate_statement,
|
||||||
|
&validity_other_key.into(),
|
||||||
|
&signing_context,
|
||||||
|
);
|
||||||
let signed_statement = ::table::generic::SignedStatement {
|
let signed_statement = ::table::generic::SignedStatement {
|
||||||
statement: candidate_statement,
|
statement: candidate_statement,
|
||||||
signature: signature.into(),
|
signature: signature.into(),
|
||||||
@@ -934,7 +963,11 @@ mod tests {
|
|||||||
|
|
||||||
let para_id = ParaId::from(1);
|
let para_id = ParaId::from(1);
|
||||||
let pov_block = pov_block_with_data(vec![1, 2, 3]);
|
let pov_block = pov_block_with_data(vec![1, 2, 3]);
|
||||||
let parent_hash = Default::default();
|
let parent_hash = Hash::default();
|
||||||
|
let signing_context = SigningContext {
|
||||||
|
session_index: Default::default(),
|
||||||
|
parent_hash: parent_hash.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
let local_key = Sr25519Keyring::Alice.pair();
|
let local_key = Sr25519Keyring::Alice.pair();
|
||||||
let local_id: ValidatorId = local_key.public().into();
|
let local_id: ValidatorId = local_key.public().into();
|
||||||
@@ -952,7 +985,7 @@ mod tests {
|
|||||||
[local_id, validity_other].to_vec(),
|
[local_id, validity_other].to_vec(),
|
||||||
groups,
|
groups,
|
||||||
Some(local_key.clone()),
|
Some(local_key.clone()),
|
||||||
parent_hash,
|
signing_context.clone(),
|
||||||
AvailabilityStore::new_in_memory(DummyErasureNetworking),
|
AvailabilityStore::new_in_memory(DummyErasureNetworking),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ use consensus::SelectChain;
|
|||||||
use futures::{future::ready, prelude::*, task::{Spawn, SpawnExt}};
|
use futures::{future::ready, prelude::*, task::{Spawn, SpawnExt}};
|
||||||
use polkadot_primitives::{Block, Hash, BlockId};
|
use polkadot_primitives::{Block, Hash, BlockId};
|
||||||
use polkadot_primitives::parachain::{
|
use polkadot_primitives::parachain::{
|
||||||
Chain, ParachainHost, Id as ParaId, ValidatorIndex, ValidatorId, ValidatorPair,
|
Chain, ParachainHost, Id as ParaId, ValidatorIndex, ValidatorId, ValidatorPair, SigningContext,
|
||||||
};
|
};
|
||||||
use babe_primitives::BabeApi;
|
use babe_primitives::BabeApi;
|
||||||
use keystore::KeyStorePtr;
|
use keystore::KeyStorePtr;
|
||||||
@@ -44,7 +44,7 @@ use sp_api::{ApiExt, ProvideRuntimeApi};
|
|||||||
use runtime_primitives::traits::HashFor;
|
use runtime_primitives::traits::HashFor;
|
||||||
use availability_store::Store as AvailabilityStore;
|
use availability_store::Store as AvailabilityStore;
|
||||||
|
|
||||||
use log::{warn, error, info, debug};
|
use log::{warn, error, info, debug, trace};
|
||||||
|
|
||||||
use super::{Network, Collators, SharedTable, TableRouter};
|
use super::{Network, Collators, SharedTable, TableRouter};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
@@ -334,11 +334,29 @@ impl<C, N, P, SP> ParachainValidationInstances<C, N, P, SP> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let api = self.client.runtime_api();
|
||||||
|
|
||||||
|
let signing_context = if api.has_api_with::<dyn ParachainHost<Block, Error = ()>, _>(
|
||||||
|
&BlockId::hash(parent_hash),
|
||||||
|
|version| version >= 3,
|
||||||
|
)? {
|
||||||
|
api.signing_context(&id)?
|
||||||
|
} else {
|
||||||
|
trace!(
|
||||||
|
target: "validation",
|
||||||
|
"Expected runtime with ParachainHost version >= 3",
|
||||||
|
);
|
||||||
|
SigningContext {
|
||||||
|
session_index: 0,
|
||||||
|
parent_hash,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let table = Arc::new(SharedTable::new(
|
let table = Arc::new(SharedTable::new(
|
||||||
validators.clone(),
|
validators.clone(),
|
||||||
group_info,
|
group_info,
|
||||||
sign_with,
|
sign_with,
|
||||||
parent_hash,
|
signing_context,
|
||||||
self.availability_store.clone(),
|
self.availability_store.clone(),
|
||||||
max_block_data_size,
|
max_block_data_size,
|
||||||
));
|
));
|
||||||
|
|||||||
Reference in New Issue
Block a user