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:
Fedor Sakharov
2020-03-26 00:04:05 +03:00
committed by GitHub
parent 62cddd6fcb
commit dbb4e987fa
15 changed files with 252 additions and 159 deletions
+21 -10
View File
@@ -34,12 +34,11 @@ use std::{
sync::Arc,
};
use codec::Encode;
use polkadot_primitives::Hash;
use polkadot_primitives::parachain::{
Id as ParaId, Chain, DutyRoster, AbridgedCandidateReceipt,
Statement as PrimitiveStatement,
PoVBlock, ErasureChunk, ValidatorSignature, ValidatorIndex,
ValidatorPair, ValidatorId,
ValidatorPair, ValidatorId, SigningContext,
};
use primitives::Pair;
@@ -135,9 +134,13 @@ pub struct GroupInfo {
/// Sign a table statement against a parent hash.
/// The actual message signed is the encoded statement concatenated with the
/// 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();
encoded.extend(parent_hash.as_ref());
encoded.extend(signing_context.encode());
key.sign(&encoded)
}
@@ -147,12 +150,12 @@ pub fn check_statement(
statement: &Statement,
signature: &ValidatorSignature,
signer: ValidatorId,
parent_hash: &Hash,
signing_context: &SigningContext,
) -> bool {
use runtime_primitives::traits::AppVerify;
let mut encoded = PrimitiveStatement::from(statement).encode();
encoded.extend(parent_hash.as_ref());
encoded.extend(signing_context.encode());
signature.verify(&encoded[..], &signer)
}
@@ -214,11 +217,19 @@ mod tests {
fn sign_and_check_statement() {
let statement: Statement = GenericStatement::Valid([1; 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));
assert!(!check_statement(&statement, &sig, Sr25519Keyring::Alice.public().into(), &[0xff; 32].into()));
assert!(!check_statement(&statement, &sig, Sr25519Keyring::Bob.public().into(), &parent_hash));
let wrong_signing_context = SigningContext {
session_index: Default::default(),
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));
}
}
+52 -19
View File
@@ -25,7 +25,7 @@ use table::{self, Table, Context as TableContextTrait};
use polkadot_primitives::{Block, Hash};
use polkadot_primitives::parachain::{
Id as ParaId, AbridgedCandidateReceipt, ValidatorPair, ValidatorId,
AttestedCandidate, ParachainHost, PoVBlock, ValidatorIndex,
AttestedCandidate, ParachainHost, PoVBlock, ValidatorIndex, SigningContext,
};
use parking_lot::Mutex;
@@ -48,7 +48,7 @@ pub use table::{SignedStatement, Statement};
pub use table::generic::Statement as GenericStatement;
struct TableContext {
parent_hash: Hash,
signing_context: SigningContext,
key: Option<Arc<ValidatorPair>>,
groups: HashMap<ParaId, GroupInfo>,
validators: Vec<ValidatorId>,
@@ -87,7 +87,12 @@ impl TableContext {
fn sign_statement(&self, statement: table::Statement) -> Option<table::SignedStatement> {
self.local_index().and_then(move |sender|
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 })
)
}
@@ -189,7 +194,7 @@ impl SharedTableInner {
work.map(|work| ParachainWork {
availability_store: self.availability_store.clone(),
relay_parent: context.parent_hash.clone(),
relay_parent: context.signing_context.parent_hash.clone(),
work,
max_block_data_size,
n_validators: context.validators.len(),
@@ -408,12 +413,12 @@ impl SharedTable {
validators: Vec<ValidatorId>,
groups: HashMap<ParaId, GroupInfo>,
key: Option<Arc<ValidatorPair>>,
parent_hash: Hash,
signing_context: SigningContext,
availability_store: AvailabilityStore,
max_block_data_size: Option<u64>,
) -> Self {
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,
inner: Arc::new(Mutex::new(SharedTableInner {
table: Table::default(),
@@ -425,8 +430,8 @@ impl SharedTable {
}
/// Get the parent hash this table should hold statements localized to.
pub fn consensus_parent_hash(&self) -> &Hash {
&self.context.parent_hash
pub fn signing_context(&self) -> &SigningContext {
&self.context.signing_context
}
/// Get the local validator session key.
@@ -654,7 +659,11 @@ mod tests {
let mut groups = HashMap::new();
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_id: ValidatorId = local_key.public().into();
@@ -673,7 +682,7 @@ mod tests {
[local_id, validity_other].to_vec(),
groups,
Some(local_key.clone()),
parent_hash,
signing_context.clone(),
AvailabilityStore::new_in_memory(DummyErasureNetworking),
None,
);
@@ -684,7 +693,11 @@ mod tests {
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 {
statement: candidate_statement,
signature: signature.into(),
@@ -702,7 +715,11 @@ mod tests {
let mut groups = HashMap::new();
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_id: ValidatorId = local_key.public().into();
@@ -721,7 +738,7 @@ mod tests {
[local_id, validity_other].to_vec(),
groups,
Some(local_key.clone()),
parent_hash,
signing_context.clone(),
AvailabilityStore::new_in_memory(DummyErasureNetworking),
None,
);
@@ -732,7 +749,11 @@ mod tests {
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 {
statement: candidate_statement,
signature: signature.into(),
@@ -874,7 +895,11 @@ mod tests {
let mut groups = HashMap::new();
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_id: ValidatorId = local_key.public().into();
@@ -893,7 +918,7 @@ mod tests {
[local_id, validity_other].to_vec(),
groups,
Some(local_key.clone()),
parent_hash,
signing_context.clone(),
AvailabilityStore::new_in_memory(DummyErasureNetworking),
None,
);
@@ -905,7 +930,11 @@ mod tests {
let candidate_hash = candidate.hash();
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 {
statement: candidate_statement,
signature: signature.into(),
@@ -934,7 +963,11 @@ mod tests {
let para_id = ParaId::from(1);
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_id: ValidatorId = local_key.public().into();
@@ -952,7 +985,7 @@ mod tests {
[local_id, validity_other].to_vec(),
groups,
Some(local_key.clone()),
parent_hash,
signing_context.clone(),
AvailabilityStore::new_in_memory(DummyErasureNetworking),
None,
);
@@ -36,7 +36,7 @@ use consensus::SelectChain;
use futures::{future::ready, prelude::*, task::{Spawn, SpawnExt}};
use polkadot_primitives::{Block, Hash, BlockId};
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 keystore::KeyStorePtr;
@@ -44,7 +44,7 @@ use sp_api::{ApiExt, ProvideRuntimeApi};
use runtime_primitives::traits::HashFor;
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 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(
validators.clone(),
group_info,
sign_with,
parent_hash,
signing_context,
self.availability_store.clone(),
max_block_data_size,
));