-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Validator side of the collation protocol. #295
Changes from 1 commit
e457a29
b04aa4e
e9a3ace
c152a0c
352565c
11875ec
0ba2c70
d236663
bd70053
2a03637
43e7f91
0f35d0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
collators to CollationPool
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,22 +43,22 @@ extern crate rhododendron; | |
| #[macro_use] | ||
| extern crate log; | ||
|
|
||
| mod collators; | ||
| mod collator_pool; | ||
| mod router; | ||
| pub mod consensus; | ||
|
|
||
| use codec::Slicable; | ||
| use futures::sync::oneshot; | ||
| use parking_lot::Mutex; | ||
| use polkadot_consensus::{Statement, SignedStatement, GenericStatement}; | ||
| use polkadot_primitives::{Block, SessionKey, Hash}; | ||
| use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt}; | ||
| use polkadot_primitives::{AccountId, Block, SessionKey, Hash}; | ||
| use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt, Collation}; | ||
| use substrate_network::{PeerId, RequestId, Context}; | ||
| use substrate_network::consensus_gossip::ConsensusGossip; | ||
| use substrate_network::{message, generic_message}; | ||
| use substrate_network::specialization::Specialization; | ||
| use substrate_network::StatusMessage as GenericFullStatus; | ||
| use self::collators::Collators; | ||
| use self::collator_pool::CollatorPool; | ||
|
|
||
| use std::collections::{HashMap, HashSet}; | ||
| use std::sync::Arc; | ||
|
|
@@ -199,6 +199,8 @@ pub enum Message { | |
| RequestBlockData(RequestId, Hash), | ||
| /// Provide block data by candidate hash or nothing if unknown. | ||
| BlockData(RequestId, Option<BlockData>), | ||
| /// A collation provided by a peer. Relay parent and collation. | ||
| Collation(Hash, Collation), | ||
| } | ||
|
|
||
| fn send_polkadot_message(ctx: &mut Context<Block>, to: PeerId, message: Message) { | ||
|
|
@@ -210,7 +212,7 @@ fn send_polkadot_message(ctx: &mut Context<Block>, to: PeerId, message: Message) | |
| pub struct PolkadotProtocol { | ||
| peers: HashMap<PeerId, PeerInfo>, | ||
| consensus_gossip: ConsensusGossip<Block>, | ||
| collators: Collators, | ||
| collators: CollatorPool, | ||
| live_consensus: Option<CurrentConsensus>, | ||
| in_flight: HashMap<(RequestId, PeerId), BlockDataRequest>, | ||
| pending: Vec<BlockDataRequest>, | ||
|
|
@@ -223,7 +225,7 @@ impl PolkadotProtocol { | |
| PolkadotProtocol { | ||
| peers: HashMap::new(), | ||
| consensus_gossip: ConsensusGossip::new(), | ||
| collators: Collators::new(), | ||
| collators: CollatorPool::new(), | ||
| live_consensus: None, | ||
| in_flight: HashMap::new(), | ||
| pending: Vec::new(), | ||
|
|
@@ -364,6 +366,7 @@ impl PolkadotProtocol { | |
| send_polkadot_message(ctx, peer_id, Message::BlockData(req_id, block_data)); | ||
| } | ||
| Message::BlockData(req_id, data) => self.on_block_data(ctx, peer_id, req_id, data), | ||
| Message::Collation(relay_parent, collation) => self.on_collation(ctx, peer_id, relay_parent, collation), | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -387,7 +390,7 @@ impl PolkadotProtocol { | |
|
|
||
| impl Specialization<Block> for PolkadotProtocol { | ||
| fn status(&self) -> Vec<u8> { | ||
| Status { collating_for: self.collating_for.clone() }.encode() | ||
| Status { collating_for: None }.encode() | ||
| } | ||
|
|
||
| fn on_connect(&mut self, ctx: &mut Context<Block>, peer_id: PeerId, status: FullStatus) { | ||
|
|
@@ -487,3 +490,25 @@ impl Specialization<Block> for PolkadotProtocol { | |
| self.dispatch_pending_requests(ctx); | ||
| } | ||
| } | ||
|
|
||
| impl PolkadotProtocol { | ||
| // we received a collation from a peer | ||
| fn on_collation(&mut self, ctx: &mut Context<Block>, from: PeerId, relay_parent: Hash, collation: Collation) { | ||
| let collation_para = collation.receipt.parachain_index; | ||
| let collated_acc = collation.receipt.collator; | ||
|
|
||
| match self.peers.get(&from) { | ||
| None => ctx.disconnect_peer(from), | ||
| Some(peer_info) => match peer_info.status.collating_for { | ||
| None => ctx.disable_peer(from), | ||
| Some((ref acc_id, ref para_id)) | ||
| if para_id != &collation_para || acc_id != &collated_acc || collation.receipt.check_signature().is_err() => ctx.disable_peer(from), | ||
|
||
| Some((ref acc_id, _)) => self.collators.on_collation(acc_id.clone(), relay_parent, collation), | ||
|
||
| }, | ||
| } | ||
| } | ||
|
|
||
| fn await_collation(&mut self, relay_parent: Hash, para_id: ParaId, sender: oneshot::Sender<Collation>) { | ||
| self.collators.await_collation(relay_parent, para_id, sender); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -144,7 +144,7 @@ pub struct CandidateReceipt { | |
| pub parachain_index: Id, | ||
| /// The collator's relay-chain account ID | ||
| pub collator: super::AccountId, | ||
| /// Signature on block data by collator. | ||
| /// Signature on blake2-256 of the block data by collator. | ||
| pub signature: CandidateSignature, | ||
| /// The head-data | ||
| pub head_data: HeadData, | ||
|
|
@@ -195,6 +195,17 @@ impl CandidateReceipt { | |
| use runtime_primitives::traits::{BlakeTwo256, Hashing}; | ||
| BlakeTwo256::hash_of(self) | ||
| } | ||
|
|
||
| /// Check integrity vs. provided block data. | ||
| pub fn check_signature(&self) -> Result<(), ()> { | ||
| use runtime_primitives::traits::Verify; | ||
|
|
||
| if self.signature.verify(&self.signature.0[..], &self.collator) { | ||
|
||
| Ok(()) | ||
| } else { | ||
| Err(()) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl PartialOrd for CandidateReceipt { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is guaranteed that any
AccountIdcan at most be part of one parachain collator group ever and not be part of two or more parachains in their lifetime? Like, also not switch parachains? Because we overwrite any potential entry here without updating the the correspondingParachainCollatorif it exists (which could lead to an incoherent state and cause locking, like when not removing a primaryAccountIdwhen it disconnects, because we aren't aware it is still stored there.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#271 will ensure that we are connected to only one peer ID with a claimed
AccountIdat a time, and eachAccountIdcan only collate for one parachain during the span of the connection in the current protocol.