Downward Message Processing implementation (#1859)

* DMP: data structures and plumbing

* DMP: Implement DMP logic in the router module

DMP: Integrate DMP parts into the inclusion module

* DMP: Introduce the max size limit for the size of a downward message

* DMP: Runtime API for accessing inbound messages

* OCD

Small clean ups

* DMP: fix the naming of the error

* DMP: add caution about a non-existent recipient
This commit is contained in:
Sergei Shulepov
2020-10-28 11:41:42 +01:00
committed by GitHub
parent 1a25c41277
commit 9903bca259
26 changed files with 556 additions and 36 deletions
+1
View File
@@ -70,6 +70,7 @@ impl Default for TestState {
parent_head: HeadData(vec![7, 8, 9]),
block_number: 5,
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
};
let pruning_config = PruningConfig {
+7
View File
@@ -682,6 +682,7 @@ impl CandidateBackingJob {
erasure_root,
new_validation_code: outputs.new_validation_code,
head_data: outputs.head_data,
processed_downward_messages: outputs.processed_downward_messages,
};
let res = match with_commitments(commitments) {
@@ -977,12 +978,14 @@ mod tests {
parent_head: HeadData(vec![7, 8, 9]),
block_number: Default::default(),
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
},
transient: TransientValidationData {
max_code_size: 1000,
max_head_data_size: 1000,
balance: Default::default(),
code_upgrade_allowed: None,
dmq_length: 0,
},
};
@@ -1159,6 +1162,7 @@ mod tests {
upward_messages: Vec::new(),
fees: Default::default(),
new_validation_code: None,
processed_downward_messages: 0,
}, test_state.validation_data.persisted),
)).unwrap();
}
@@ -1278,6 +1282,7 @@ mod tests {
upward_messages: Vec::new(),
fees: Default::default(),
new_validation_code: None,
processed_downward_messages: 0,
}, test_state.validation_data.persisted),
)).unwrap();
}
@@ -1416,6 +1421,7 @@ mod tests {
upward_messages: Vec::new(),
fees: Default::default(),
new_validation_code: None,
processed_downward_messages: 0,
}, test_state.validation_data.persisted),
)).unwrap();
}
@@ -1571,6 +1577,7 @@ mod tests {
upward_messages: Vec::new(),
fees: Default::default(),
new_validation_code: None,
processed_downward_messages: 0,
}, test_state.validation_data.persisted),
)).unwrap();
}
@@ -494,11 +494,13 @@ mod tests {
upward_messages: Vec::new(),
fees: 0,
new_validation_code: None,
processed_downward_messages: 0,
},
PersistedValidationData {
parent_head: HeadData(parent_head_data),
block_number: 123,
hrmp_mqc_heads: Vec::new(),
dmq_mqc_head: Default::default(),
},
)
}
@@ -468,6 +468,7 @@ fn validate_candidate_exhaustive<B: ValidationBackend, S: SpawnNamed + 'static>(
parent_head: persisted_validation_data.parent_head.clone(),
block_data: pov.block_data.clone(),
relay_chain_height: persisted_validation_data.block_number,
dmq_mqc_head: persisted_validation_data.dmq_mqc_head,
hrmp_mqc_heads: persisted_validation_data.hrmp_mqc_heads.clone(),
};
@@ -491,6 +492,7 @@ fn validate_candidate_exhaustive<B: ValidationBackend, S: SpawnNamed + 'static>(
upward_messages: res.upward_messages,
fees: 0,
new_validation_code: res.new_validation_code,
processed_downward_messages: res.processed_downward_messages,
};
Ok(ValidationResult::Valid(outputs, persisted_validation_data))
}
+60 -1
View File
@@ -127,6 +127,7 @@ fn make_runtime_api_request<Client>(
query!(candidate_pending_availability(para), sender),
Request::CandidateEvents(sender) => query!(candidate_events(), sender),
Request::ValidatorDiscovery(ids, sender) => query!(validator_discovery(ids), sender),
Request::DmqContents(id, sender) => query!(dmq_contents(id), sender),
}
}
@@ -176,7 +177,7 @@ mod tests {
use polkadot_primitives::v1::{
ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, PersistedValidationData,
Id as ParaId, OccupiedCoreAssumption, ValidationData, SessionIndex, ValidationCode,
CommittedCandidateReceipt, CandidateEvent, AuthorityDiscoveryId,
CommittedCandidateReceipt, CandidateEvent, AuthorityDiscoveryId, InboundDownwardMessage,
};
use polkadot_node_subsystem_test_helpers as test_helpers;
use sp_core::testing::TaskExecutor;
@@ -195,6 +196,7 @@ mod tests {
validation_outputs_results: HashMap<ParaId, bool>,
candidate_pending_availability: HashMap<ParaId, CommittedCandidateReceipt>,
candidate_events: Vec<CandidateEvent>,
dmq_contents: HashMap<ParaId, Vec<InboundDownwardMessage>>,
}
impl ProvideRuntimeApi<Block> for MockRuntimeApi {
@@ -283,6 +285,13 @@ mod tests {
fn validator_discovery(ids: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>> {
vec![None; ids.len()]
}
fn dmq_contents(
&self,
recipient: ParaId,
) -> Vec<polkadot_primitives::v1::InboundDownwardMessage> {
self.dmq_contents.get(&recipient).map(|q| q.clone()).unwrap_or_default()
}
}
}
@@ -619,4 +628,54 @@ mod tests {
futures::executor::block_on(future::join(subsystem_task, test_task));
}
#[test]
fn requests_dmq_contents() {
let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new());
let mut runtime_api = MockRuntimeApi::default();
let relay_parent = [1; 32].into();
let para_a = 5.into();
let para_b = 6.into();
runtime_api.dmq_contents.insert(para_a, vec![]);
runtime_api.dmq_contents.insert(
para_b,
vec![InboundDownwardMessage {
sent_at: 228,
msg: b"Novus Ordo Seclorum".to_vec(),
}],
);
let subsystem = RuntimeApiSubsystem::new(runtime_api.clone(), Metrics(None));
let subsystem_task = run(ctx, subsystem).map(|x| x.unwrap());
let test_task = async move {
let (tx, rx) = oneshot::channel();
ctx_handle
.send(FromOverseer::Communication {
msg: RuntimeApiMessage::Request(relay_parent, Request::DmqContents(para_a, tx)),
})
.await;
assert_eq!(rx.await.unwrap().unwrap(), vec![]);
let (tx, rx) = oneshot::channel();
ctx_handle
.send(FromOverseer::Communication {
msg: RuntimeApiMessage::Request(relay_parent, Request::DmqContents(para_b, tx)),
})
.await;
assert_eq!(
rx.await.unwrap().unwrap(),
vec![InboundDownwardMessage {
sent_at: 228,
msg: b"Novus Ordo Seclorum".to_vec(),
}]
);
ctx_handle
.send(FromOverseer::Signal(OverseerSignal::Conclude))
.await;
};
futures::executor::block_on(future::join(subsystem_task, test_task));
}
}