mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-17 10:05:41 +00:00
Erasure encoding availability (#345)
* Erasure encoding availability initial commit * Modifications to availability store to keep chunks as well as reconstructed blocks and extrinsics. * Gossip messages containig signed erasure chunks. * Requesting eraure chunks with polkadot-specific messages. * Validation of erasure chunk messages. * Apply suggestions from code review Co-Authored-By: Luke Schoen <ltfschoen@users.noreply.github.com> * Fix build after a merge * Gossip erasure chunk messages under their own topic * erasure_chunks should use the appropriate topic * Updates Cargo.lock * Fixes after merge * Removes a couple of leftover pieces of code * Fixes simple stuff from review * Updates erasure and storage for more flexible logic * Changes validation and candidate receipt production. * Adds add_erasure_chunks method * Fixes most of the nits * Better validate_collation and validate_receipt functions * Fixes the tests * Apply suggestions from code review Co-Authored-By: Robert Habermeier <rphmeier@gmail.com> * Removes unwrap() calls * Removes ErasureChunks primitive * Removes redundant fields from ErasureChunk struct * AvailabilityStore should store CandidateReceipt * Changes the way chunk messages are imported and validated. * Availability store now stores a validator_index and n_validators for each relay_parent. * Availability store now also stores candidate receipts. * Removes importing chunks in the table and moves it into network gossip validation. * Validation of erasure messages id done against receipts that are stored in the availability store. * Correctly compute topics for erasure messages * Removes an unused parameter * Refactors availability db querying into a helper * Adds the apis described in the writeup * Adds a runtime api to extract erasure roots form raw extrinsics. * Adds a barebone BlockImport impl for avalability store * Adds the implementation of the availability worker * Fix build after the merge with master. * Make availability store API async * Bring back the default wasmtime feature * Lines width * Bump runtime version * Formatting and dead code elimination * some style nits (#1) * More nits and api cleanup * Disable wasm CI for availability-store * Another nit * Formatting
This commit is contained in:
committed by
Robert Habermeier
parent
ec54d5b1e4
commit
99d164b5e7
@@ -49,16 +49,19 @@
|
||||
//! Peers who send information which was not allowed under a recent neighbor packet
|
||||
//! will be noted as non-beneficial to Substrate's peer-set management utility.
|
||||
|
||||
use sp_runtime::{generic::BlockId, traits::ProvideRuntimeApi};
|
||||
use sp_runtime::{generic::BlockId, traits::{ProvideRuntimeApi, BlakeTwo256, Hash as HashT}};
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use sc_network::{config::Roles, PeerId, ReputationChange};
|
||||
use sc_network::consensus_gossip::{
|
||||
self as network_gossip, ValidationResult as GossipValidationResult,
|
||||
ValidatorContext, MessageIntent, ConsensusMessage,
|
||||
};
|
||||
use polkadot_validation::SignedStatement;
|
||||
use polkadot_validation::{SignedStatement};
|
||||
use polkadot_primitives::{Block, Hash};
|
||||
use polkadot_primitives::parachain::{ParachainHost, ValidatorId, Message as ParachainMessage};
|
||||
use polkadot_primitives::parachain::{
|
||||
ParachainHost, ValidatorId, Message as ParachainMessage, ErasureChunk as PrimitiveChunk
|
||||
};
|
||||
use polkadot_erasure_coding::{self as erasure};
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
use std::collections::HashMap;
|
||||
@@ -92,6 +95,8 @@ mod benefit {
|
||||
pub const NEW_CANDIDATE: Rep = Rep::new(100, "Polkadot: New candidate");
|
||||
/// When a peer sends us a previously-unknown attestation.
|
||||
pub const NEW_ATTESTATION: Rep = Rep::new(50, "Polkadot: New attestation");
|
||||
/// When a peer sends us a previously-unknown erasure chunk.
|
||||
pub const NEW_ERASURE_CHUNK: Rep = Rep::new(10, "Polkadot: New erasure chunk");
|
||||
/// When a peer sends us a previously-unknown message packet.
|
||||
pub const NEW_ICMP_MESSAGES: Rep = Rep::new(50, "Polkadot: New ICMP messages");
|
||||
}
|
||||
@@ -114,6 +119,10 @@ mod cost {
|
||||
pub const BAD_NEIGHBOR_PACKET: Rep = Rep::new(-300, "Polkadot: Bad neighbor");
|
||||
/// A peer sent us an ICMP queue we haven't advertised a need for.
|
||||
pub const UNNEEDED_ICMP_MESSAGES: Rep = Rep::new(-100, "Polkadot: Unexpected ICMP message");
|
||||
/// A peer sent us an erasure chunk referring to a candidate that we are not aware of.
|
||||
pub const ORPHANED_ERASURE_CHUNK: Rep = Rep::new(-10, "An erasure chunk from unknown candidate");
|
||||
/// A peer sent us an erasure chunk that does not match candidate's erasure root.
|
||||
pub const ERASURE_CHUNK_WRONG_ROOT: Rep = Rep::new(-100, "Chunk doesn't match encoding root");
|
||||
|
||||
/// A peer sent us an ICMP queue with a bad root.
|
||||
pub fn icmp_messages_root_mismatch(n_messages: usize) -> Rep {
|
||||
@@ -137,7 +146,9 @@ pub enum GossipMessage {
|
||||
#[codec(index = "3")]
|
||||
ParachainMessages(GossipParachainMessages),
|
||||
// TODO: https://github.com/paritytech/polkadot/issues/253
|
||||
// erasure-coded chunks.
|
||||
/// A packet containing one of the erasure-coding chunks of one candidate.
|
||||
#[codec(index = "4")]
|
||||
ErasureChunk(ErasureChunkMessage),
|
||||
}
|
||||
|
||||
impl GossipMessage {
|
||||
@@ -187,6 +198,24 @@ impl GossipStatement {
|
||||
}
|
||||
}
|
||||
|
||||
/// A gossip message containing one erasure chunk of a candidate block.
|
||||
/// For each chunk of block erasure encoding one of this messages is constructed.
|
||||
#[derive(Encode, Decode, Clone, Debug)]
|
||||
pub struct ErasureChunkMessage {
|
||||
/// The chunk itself.
|
||||
pub chunk: PrimitiveChunk,
|
||||
/// The relay parent of the block this chunk belongs to.
|
||||
pub relay_parent: Hash,
|
||||
/// The hash of the candidate receipt of the block this chunk belongs to.
|
||||
pub candidate_hash: Hash,
|
||||
}
|
||||
|
||||
impl From<ErasureChunkMessage> for GossipMessage {
|
||||
fn from(chk: ErasureChunkMessage) -> Self {
|
||||
GossipMessage::ErasureChunk(chk)
|
||||
}
|
||||
}
|
||||
|
||||
/// A packet of messages from one parachain to another.
|
||||
///
|
||||
/// These are all the messages posted from one parachain to another during the
|
||||
@@ -303,6 +332,7 @@ pub fn register_validator<C: ChainContext + 'static>(
|
||||
peers: HashMap::new(),
|
||||
attestation_view: Default::default(),
|
||||
message_routing_view: Default::default(),
|
||||
availability_store: None,
|
||||
chain,
|
||||
})
|
||||
});
|
||||
@@ -368,6 +398,10 @@ impl RegisteredMessageValidator {
|
||||
RegisteredMessageValidator { inner: validator as _ }
|
||||
}
|
||||
|
||||
pub fn register_availability_store(&mut self, availability_store: av_store::Store) {
|
||||
self.inner.inner.write().availability_store = Some(availability_store);
|
||||
}
|
||||
|
||||
/// Note that we perceive a new leaf of the block-DAG. We will notify our neighbors that
|
||||
/// we now accept parachain candidate attestations and incoming message queues
|
||||
/// relevant to this leaf.
|
||||
@@ -475,6 +509,7 @@ struct Inner<C: ?Sized> {
|
||||
peers: HashMap<PeerId, PeerData>,
|
||||
attestation_view: AttestationView,
|
||||
message_routing_view: MessageRoutingView,
|
||||
availability_store: Option<av_store::Store>,
|
||||
chain: C,
|
||||
}
|
||||
|
||||
@@ -504,6 +539,52 @@ impl<C: ?Sized + ChainContext> Inner<C> {
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_erasure_chunk_packet(&mut self, msg: ErasureChunkMessage)
|
||||
-> (GossipValidationResult<Hash>, ReputationChange)
|
||||
{
|
||||
if let Some(store) = &self.availability_store {
|
||||
if let Some(receipt) = store.get_candidate(&msg.candidate_hash) {
|
||||
let chunk_hash = erasure::branch_hash(
|
||||
&receipt.erasure_root,
|
||||
&msg.chunk.proof,
|
||||
msg.chunk.index as usize
|
||||
);
|
||||
|
||||
if chunk_hash != Ok(BlakeTwo256::hash(&msg.chunk.chunk)) {
|
||||
(
|
||||
GossipValidationResult::Discard,
|
||||
cost::ERASURE_CHUNK_WRONG_ROOT
|
||||
)
|
||||
} else {
|
||||
if let Some(awaited_chunks) = store.awaited_chunks() {
|
||||
if awaited_chunks.contains(&(
|
||||
msg.relay_parent,
|
||||
receipt.erasure_root,
|
||||
receipt.hash(),
|
||||
msg.chunk.index,
|
||||
)) {
|
||||
let topic = av_store::erasure_coding_topic(
|
||||
msg.relay_parent,
|
||||
receipt.erasure_root,
|
||||
msg.chunk.index,
|
||||
);
|
||||
|
||||
return (
|
||||
GossipValidationResult::ProcessAndKeep(topic),
|
||||
benefit::NEW_ERASURE_CHUNK,
|
||||
);
|
||||
}
|
||||
}
|
||||
(GossipValidationResult::Discard, cost::NONE)
|
||||
}
|
||||
} else {
|
||||
(GossipValidationResult::Discard, cost::ORPHANED_ERASURE_CHUNK)
|
||||
}
|
||||
} else {
|
||||
(GossipValidationResult::Discard, cost::NONE)
|
||||
}
|
||||
}
|
||||
|
||||
fn multicast_neighbor_packet<F: FnMut(&PeerId, ConsensusMessage)>(
|
||||
&self,
|
||||
mut send_neighbor_packet: F,
|
||||
@@ -536,6 +617,7 @@ impl<C: ChainContext + ?Sized> MessageValidator<C> {
|
||||
peers: HashMap::new(),
|
||||
attestation_view: Default::default(),
|
||||
message_routing_view: Default::default(),
|
||||
availability_store: None,
|
||||
chain,
|
||||
}),
|
||||
}
|
||||
@@ -594,6 +676,9 @@ impl<C: ChainContext + ?Sized> network_gossip::Validator<Block> for MessageValid
|
||||
}
|
||||
(res, cb)
|
||||
}
|
||||
Ok(GossipMessage::ErasureChunk(chunk)) => {
|
||||
self.inner.write().validate_erasure_chunk_packet(chunk)
|
||||
}
|
||||
};
|
||||
|
||||
self.report(sender, cost_benefit);
|
||||
@@ -775,6 +860,7 @@ mod tests {
|
||||
fees: 1_000_000,
|
||||
block_data_hash: [20u8; 32].into(),
|
||||
upward_messages: Vec::new(),
|
||||
erasure_root: [1u8; 32].into(),
|
||||
};
|
||||
|
||||
let statement = GossipMessage::Statement(GossipStatement {
|
||||
|
||||
Reference in New Issue
Block a user