Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ use parking_lot::Mutex;
use polkadot_primitives::{Hash, Block, BlockId, BlockNumber, Header, Timestamp, SessionKey};
use polkadot_primitives::{Compact, UncheckedExtrinsic};
use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic as ParachainExtrinsic, CandidateReceipt, CandidateSignature};
use polkadot_primitives::parachain::ParachainHost;
use polkadot_primitives::parachain::{AttestedCandidate, ParachainHost, Statement as PrimitiveStatement};
use primitives::{AuthorityId, ed25519};
use runtime_primitives::traits::ProvideRuntimeApi;
use tokio::runtime::TaskExecutor;
Expand Down Expand Up @@ -156,7 +156,10 @@ pub struct GroupInfo {
/// The actual message signed is the encoded statement concatenated with the
/// parent hash.
pub fn sign_table_statement(statement: &Statement, key: &ed25519::Pair, parent_hash: &Hash) -> CandidateSignature {
let mut encoded = statement.encode();
// we sign using the primitive statement type because that's what the runtime
// expects. These types probably encode the same way so this clone could be optimized
// out in the future.
let mut encoded = PrimitiveStatement::from(statement.clone()).encode();
encoded.extend(parent_hash.as_ref());

key.sign(&encoded).into()
Expand All @@ -166,7 +169,7 @@ pub fn sign_table_statement(statement: &Statement, key: &ed25519::Pair, parent_h
pub fn check_statement(statement: &Statement, signature: &CandidateSignature, signer: SessionKey, parent_hash: &Hash) -> bool {
use runtime_primitives::traits::Verify;

let mut encoded = statement.encode();
let mut encoded = PrimitiveStatement::from(statement.clone()).encode();
encoded.extend(parent_hash.as_ref());

signature.verify(&encoded[..], &signer.into())
Expand Down Expand Up @@ -640,7 +643,7 @@ impl<C, TxApi> CreateProposal<C, TxApi> where
C: ProvideRuntimeApi + HeaderBackend<Block> + Send + Sync,
C::Api: ParachainHost<Block> + BlockBuilder<Block>,
{
fn propose_with(&self, candidates: Vec<CandidateReceipt>) -> Result<Block, Error> {
fn propose_with(&self, candidates: Vec<AttestedCandidate>) -> Result<Block, Error> {
use client::block_builder::BlockBuilder;
use runtime_primitives::traits::{Hash as HashT, BlakeTwo256};
use polkadot_primitives::InherentData;
Expand Down Expand Up @@ -726,9 +729,7 @@ impl<C, TxApi> Future for CreateProposal<C, TxApi> where
try_ready!(self.timing.poll(included));

// 2. propose
let proposed_candidates = self.table.with_proposal(|proposed_set| {
proposed_set.into_iter().cloned().collect()
});
let proposed_candidates = self.table.proposed_set();

self.propose_with(proposed_candidates).map(Async::Ready)
}
Expand All @@ -738,6 +739,7 @@ impl<C, TxApi> Future for CreateProposal<C, TxApi> where
mod tests {
use super::*;
use substrate_keyring::Keyring;
use polkadot_primitives::parachain::Statement as PStatement;

#[test]
fn sign_and_check_statement() {
Expand Down
2 changes: 1 addition & 1 deletion consensus/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn prune_unneeded_availability<C>(client: Arc<C>, extrinsic_store: ExtrinsicStor
.iter()
.filter_map(|ex| match ex.function {
Call::Parachains(ParachainsCall::set_heads(ref heads)) =>
Some(heads.iter().map(|c| c.hash()).collect()),
Some(heads.iter().map(|c| c.candidate.hash()).collect()),
_ => None,
})
.next()
Expand Down
32 changes: 23 additions & 9 deletions consensus/src/shared_table/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ use std::sync::Arc;
use extrinsic_store::{Data, Store as ExtrinsicStore};
use table::{self, Table, Context as TableContextTrait};
use polkadot_primitives::{Hash, SessionKey};
use polkadot_primitives::parachain::{Id as ParaId, BlockData, Collation, Extrinsic, CandidateReceipt};
use polkadot_primitives::parachain::{
Id as ParaId, BlockData, Collation, Extrinsic, CandidateReceipt,
AttestedCandidate,
};

use parking_lot::Mutex;
use futures::{future, prelude::*};
Expand Down Expand Up @@ -439,14 +442,25 @@ impl SharedTable {
f(inner.table.get_candidate(digest))
}

/// Execute a closure using the current proposed set.
///
/// Deadlocks if called recursively.
pub fn with_proposal<F, U>(&self, f: F) -> U
where F: FnOnce(Vec<&CandidateReceipt>) -> U
{
let inner = self.inner.lock();
f(inner.table.proposed_candidates(&*self.context))
/// Get a set of candidates that can be proposed.
pub fn proposed_set(&self) -> Vec<AttestedCandidate> {
use table::generic::{ValidityAttestation as GAttestation};
use polkadot_primitives::parachain::ValidityAttestation;

// we transform the types of the attestations gathered from the table
// into the type expected by the runtime. This may do signature
// aggregation in the future.
let table_attestations = self.inner.lock().table.proposed_candidates(&*self.context);
table_attestations.into_iter()
.map(|attested| AttestedCandidate {
candidate: attested.candidate,
availability_votes: attested.availability_votes,
validity_votes: attested.validity_votes.into_iter().map(|(a, v)| match v {
GAttestation::Implicit(s) => (a, ValidityAttestation::Implicit(s)),
GAttestation::Explicit(s) => (a, ValidityAttestation::Explicit(s)),
}).collect(),
})
.collect()
}

/// Get the number of total parachains.
Expand Down
4 changes: 2 additions & 2 deletions primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,6 @@ impl Extrinsic for UncheckedExtrinsic {}
pub struct InherentData {
/// Current timestamp.
pub timestamp: Timestamp,
/// Parachain heads update.
pub parachain_heads: Vec<::parachain::CandidateReceipt>,
/// Parachain heads update. This contains fully-attested candidates.
pub parachain_heads: Vec<::parachain::AttestedCandidate>,
}
56 changes: 49 additions & 7 deletions primitives/src/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use rstd::prelude::*;
use rstd::cmp::Ordering;
use super::Hash;
use super::{Hash, SessionKey};

use {AccountId};

Expand Down Expand Up @@ -102,7 +102,6 @@ pub struct CandidateReceipt {

impl CandidateReceipt {
/// Get the blake2_256 hash
#[cfg(feature = "std")]
pub fn hash(&self) -> Hash {
use runtime_primitives::traits::{BlakeTwo256, Hash};
BlakeTwo256::hash_of(self)
Expand Down Expand Up @@ -189,25 +188,68 @@ pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);

/// Activitiy bit field
/// Activity bit field
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);

/// Statements which can be made about parachain candidates.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
#[derive(Clone, PartialEq, Eq, Encode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Statement {
/// Proposal of a parachain candidate.
#[codec(index = "1")]
Candidate(CandidateReceipt),
/// State that a parachain candidate is valid.
#[codec(index = "2")]
Valid(Hash),
/// Vote to commit to a candidate.
/// State a candidate is invalid.
#[codec(index = "3")]
Invalid(Hash),
/// Vote to advance round after inactive primary.
/// State a candidate's associated data is unavailable.
#[codec(index = "4")]
Available(Hash),
}

/// An either implicit or explicit attestation to the validity of a parachain
/// candidate.
#[derive(Clone, PartialEq, Decode, Encode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum ValidityAttestation {
/// implicit validity attestation by issuing.
/// This corresponds to issuance of a `Candidate` statement.
#[codec(index = "1")]
Implicit(CandidateSignature),
/// An explicit attestation. This corresponds to issuance of a
/// `Valid` statement.
#[codec(index = "2")]
Explicit(CandidateSignature),
}

/// An attested candidate.
#[derive(Clone, PartialEq, Decode, Encode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct AttestedCandidate {
/// The candidate data.
pub candidate: CandidateReceipt,
/// Validity attestations.
pub validity_votes: Vec<(SessionKey, ValidityAttestation)>,
/// Availability attestations.
pub availability_votes: Vec<(SessionKey, CandidateSignature)>,
}

impl AttestedCandidate {
/// Get the candidate.
pub fn candidate(&self) -> &CandidateReceipt {
&self.candidate
}

/// Get the group ID of the candidate.
pub fn parachain_index(&self) -> Id {
self.candidate.parachain_index
}
}

decl_runtime_apis! {
/// The API for querying the state of parachains on-chain.
pub trait ParachainHost {
Expand Down
4 changes: 3 additions & 1 deletion runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]

[dependencies]
bitvec = { version = "0.8", default-features = false, features = ["alloc"] }
rustc-hex = "1.0"
log = { version = "0.3", optional = true }
serde = { version = "1.0", default-features = false }
Expand All @@ -17,7 +18,6 @@ sr-std = { git = "https://github.com/paritytech/substrate" }
sr-io = { git = "https://github.com/paritytech/substrate" }
srml-support = { git = "https://github.com/paritytech/substrate" }
substrate-primitives = { git = "https://github.com/paritytech/substrate" }
substrate-keyring = { git = "https://github.com/paritytech/substrate" }
substrate-client = { git = "https://github.com/paritytech/substrate" }
srml-balances = { git = "https://github.com/paritytech/substrate" }
srml-consensus = { git = "https://github.com/paritytech/substrate" }
Expand All @@ -34,10 +34,12 @@ sr-version = { git = "https://github.com/paritytech/substrate" }

[dev-dependencies]
hex-literal = "0.1.0"
substrate-keyring = { git = "https://github.com/paritytech/substrate" }

[features]
default = ["std"]
std = [
"bitvec/std",
"polkadot-primitives/std",
"parity-codec/std",
"parity-codec-derive/std",
Expand Down
6 changes: 6 additions & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit="256"]

#[macro_use]
extern crate bitvec;

#[macro_use]
extern crate parity_codec_derive;
extern crate parity_codec as codec;
Expand Down Expand Up @@ -52,6 +55,9 @@ extern crate srml_treasury as treasury;

extern crate polkadot_primitives as primitives;

#[cfg(test)]
extern crate substrate_keyring as keyring;

mod parachains;

#[cfg(feature = "std")]
Expand Down
Loading