mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 09:21:04 +00:00
Introduce a Proof-of-Validation block type and use that in place of BlockData (#227)
* validators expect collators to give them parachain messages * mostly port network to use pov_block * network tests pass * verify ingress when fetching pov block * fix runtime compilation * all tests build * fix some grumbles * Update validation/src/collation.rs Co-Authored-By: rphmeier <rphmeier@gmail.com> * Update primitives/src/parachain.rs Co-Authored-By: rphmeier <rphmeier@gmail.com> * Update network/src/lib.rs Co-Authored-By: rphmeier <rphmeier@gmail.com>
This commit is contained in:
committed by
GitHub
parent
2bbfa0ae98
commit
1437c8e224
+77
-21
@@ -56,7 +56,10 @@ pub mod gossip;
|
||||
use codec::{Decode, Encode};
|
||||
use futures::sync::oneshot;
|
||||
use polkadot_primitives::{Block, SessionKey, Hash, Header};
|
||||
use polkadot_primitives::parachain::{Id as ParaId, CollatorId, BlockData, CandidateReceipt, Collation};
|
||||
use polkadot_primitives::parachain::{
|
||||
Id as ParaId, BlockData, CollatorId, CandidateReceipt, Collation, PoVBlock,
|
||||
ConsolidatedIngressRoots,
|
||||
};
|
||||
use substrate_network::{PeerId, RequestId, Context, Severity};
|
||||
use substrate_network::{message, generic_message};
|
||||
use substrate_network::specialization::NetworkSpecialization as Specialization;
|
||||
@@ -84,12 +87,33 @@ pub struct Status {
|
||||
collating_for: Option<(CollatorId, ParaId)>,
|
||||
}
|
||||
|
||||
struct BlockDataRequest {
|
||||
struct PoVBlockRequest {
|
||||
attempted_peers: HashSet<SessionKey>,
|
||||
validation_session_parent: Hash,
|
||||
candidate_hash: Hash,
|
||||
block_data_hash: Hash,
|
||||
sender: oneshot::Sender<BlockData>,
|
||||
sender: oneshot::Sender<PoVBlock>,
|
||||
canon_roots: ConsolidatedIngressRoots,
|
||||
}
|
||||
|
||||
impl PoVBlockRequest {
|
||||
// Attempt to process a response. If the provided block is invalid,
|
||||
// this returns an error result containing the unmodified request.
|
||||
//
|
||||
// If `Ok(())` is returned, that indicates that the request has been processed.
|
||||
fn process_response(self, pov_block: PoVBlock) -> Result<(), Self> {
|
||||
if pov_block.block_data.hash() != self.block_data_hash {
|
||||
return Err(self);
|
||||
}
|
||||
|
||||
match polkadot_validation::validate_incoming(&self.canon_roots, &pov_block.ingress) {
|
||||
Ok(()) => {
|
||||
let _ = self.sender.send(pov_block);
|
||||
Ok(())
|
||||
}
|
||||
Err(_) => Err(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensures collator-protocol messages are sent in correct order.
|
||||
@@ -147,9 +171,13 @@ pub enum Message {
|
||||
// TODO: do this with a cryptographic proof of some kind
|
||||
// https://github.com/paritytech/polkadot/issues/47
|
||||
SessionKey(SessionKey),
|
||||
/// Requesting parachain block data by (relay_parent, candidate_hash).
|
||||
/// Requesting parachain proof-of-validation block (relay_parent, candidate_hash).
|
||||
RequestPovBlock(RequestId, Hash, Hash),
|
||||
/// Provide requested proof-of-validation block data by candidate hash or nothing if unknown.
|
||||
PovBlock(RequestId, Option<PoVBlock>),
|
||||
/// Request block data (relay_parent, candidate_hash)
|
||||
RequestBlockData(RequestId, Hash, Hash),
|
||||
/// Provide block data by candidate hash or nothing if unknown.
|
||||
/// Provide requested block data by candidate hash or nothing.
|
||||
BlockData(RequestId, Option<BlockData>),
|
||||
/// Tell a collator their role.
|
||||
CollatorRole(Role),
|
||||
@@ -171,8 +199,8 @@ pub struct PolkadotProtocol {
|
||||
validators: HashMap<SessionKey, PeerId>,
|
||||
local_collations: LocalCollations<Collation>,
|
||||
live_validation_sessions: LiveValidationSessions,
|
||||
in_flight: HashMap<(RequestId, PeerId), BlockDataRequest>,
|
||||
pending: Vec<BlockDataRequest>,
|
||||
in_flight: HashMap<(RequestId, PeerId), PoVBlockRequest>,
|
||||
pending: Vec<PoVBlockRequest>,
|
||||
extrinsic_store: Option<::av_store::Store>,
|
||||
next_req_id: u64,
|
||||
}
|
||||
@@ -195,15 +223,22 @@ impl PolkadotProtocol {
|
||||
}
|
||||
|
||||
/// Fetch block data by candidate receipt.
|
||||
fn fetch_block_data(&mut self, ctx: &mut Context<Block>, candidate: &CandidateReceipt, relay_parent: Hash) -> oneshot::Receiver<BlockData> {
|
||||
fn fetch_pov_block(
|
||||
&mut self,
|
||||
ctx: &mut Context<Block>,
|
||||
candidate: &CandidateReceipt,
|
||||
relay_parent: Hash,
|
||||
canon_roots: ConsolidatedIngressRoots,
|
||||
) -> oneshot::Receiver<PoVBlock> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
self.pending.push(BlockDataRequest {
|
||||
self.pending.push(PoVBlockRequest {
|
||||
attempted_peers: Default::default(),
|
||||
validation_session_parent: relay_parent,
|
||||
candidate_hash: candidate.hash(),
|
||||
block_data_hash: candidate.block_data_hash,
|
||||
sender: tx,
|
||||
canon_roots,
|
||||
});
|
||||
|
||||
self.dispatch_pending_requests(ctx);
|
||||
@@ -250,7 +285,7 @@ impl PolkadotProtocol {
|
||||
let parent = pending.validation_session_parent;
|
||||
let c_hash = pending.candidate_hash;
|
||||
|
||||
let still_pending = self.live_validation_sessions.with_block_data(&parent, &c_hash, |x| match x {
|
||||
let still_pending = self.live_validation_sessions.with_pov_block(&parent, &c_hash, |x| match x {
|
||||
Ok(data @ &_) => {
|
||||
// answer locally.
|
||||
let _ = pending.sender.send(data.clone());
|
||||
@@ -270,7 +305,7 @@ impl PolkadotProtocol {
|
||||
send_polkadot_message(
|
||||
ctx,
|
||||
who.clone(),
|
||||
Message::RequestBlockData(req_id, parent, c_hash),
|
||||
Message::RequestPovBlock(req_id, parent, c_hash),
|
||||
);
|
||||
|
||||
in_flight.insert((req_id, who), pending);
|
||||
@@ -295,12 +330,21 @@ impl PolkadotProtocol {
|
||||
trace!(target: "p_net", "Polkadot message from {}: {:?}", who, msg);
|
||||
match msg {
|
||||
Message::SessionKey(key) => self.on_session_key(ctx, who, key),
|
||||
Message::RequestPovBlock(req_id, relay_parent, candidate_hash) => {
|
||||
let pov_block = self.live_validation_sessions.with_pov_block(
|
||||
&relay_parent,
|
||||
&candidate_hash,
|
||||
|res| res.ok().map(|b| b.clone()),
|
||||
);
|
||||
|
||||
send_polkadot_message(ctx, who, Message::PovBlock(req_id, pov_block));
|
||||
}
|
||||
Message::RequestBlockData(req_id, relay_parent, candidate_hash) => {
|
||||
let block_data = self.live_validation_sessions
|
||||
.with_block_data(
|
||||
.with_pov_block(
|
||||
&relay_parent,
|
||||
&candidate_hash,
|
||||
|res| res.ok().map(|b| b.clone()),
|
||||
|res| res.ok().map(|b| b.block_data.clone()),
|
||||
)
|
||||
.or_else(|| self.extrinsic_store.as_ref()
|
||||
.and_then(|s| s.block_data(relay_parent, candidate_hash))
|
||||
@@ -308,7 +352,11 @@ impl PolkadotProtocol {
|
||||
|
||||
send_polkadot_message(ctx, who, Message::BlockData(req_id, block_data));
|
||||
}
|
||||
Message::BlockData(req_id, data) => self.on_block_data(ctx, who, req_id, data),
|
||||
Message::PovBlock(req_id, data) => self.on_pov_block(ctx, who, req_id, data),
|
||||
Message::BlockData(_req_id, _data) => {
|
||||
// current block data is never requested bare by the node.
|
||||
ctx.report_peer(who, Severity::Bad("Peer sent un-requested block data".to_string()));
|
||||
}
|
||||
Message::Collation(relay_parent, collation) => self.on_collation(ctx, who, relay_parent, collation),
|
||||
Message::CollatorRole(role) => self.on_new_role(ctx, who, role),
|
||||
}
|
||||
@@ -355,13 +403,19 @@ impl PolkadotProtocol {
|
||||
self.dispatch_pending_requests(ctx);
|
||||
}
|
||||
|
||||
fn on_block_data(&mut self, ctx: &mut Context<Block>, who: PeerId, req_id: RequestId, data: Option<BlockData>) {
|
||||
fn on_pov_block(
|
||||
&mut self,
|
||||
ctx: &mut Context<Block>,
|
||||
who: PeerId,
|
||||
req_id: RequestId,
|
||||
pov_block: Option<PoVBlock>,
|
||||
) {
|
||||
match self.in_flight.remove(&(req_id, who.clone())) {
|
||||
Some(req) => {
|
||||
if let Some(data) = data {
|
||||
if data.hash() == req.block_data_hash {
|
||||
let _ = req.sender.send(data);
|
||||
return
|
||||
Some(mut req) => {
|
||||
if let Some(pov_block) = pov_block {
|
||||
match req.process_response(pov_block) {
|
||||
Ok(()) => return,
|
||||
Err(r) => { req = r; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,12 +540,14 @@ impl Specialization<Block> for PolkadotProtocol {
|
||||
self.in_flight.retain(|&(_, ref peer), val| {
|
||||
let retain = peer != &who;
|
||||
if !retain {
|
||||
// swap with a dummy value which will be dropped immediately.
|
||||
let (sender, _) = oneshot::channel();
|
||||
pending.push(::std::mem::replace(val, BlockDataRequest {
|
||||
pending.push(::std::mem::replace(val, PoVBlockRequest {
|
||||
attempted_peers: Default::default(),
|
||||
validation_session_parent: Default::default(),
|
||||
candidate_hash: Default::default(),
|
||||
block_data_hash: Default::default(),
|
||||
canon_roots: ConsolidatedIngressRoots(Vec::new()),
|
||||
sender,
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user