mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 20:17:57 +00:00
Check signatures as "Compact" in statement distribution (#5071)
* allow converting payloads _up_ * convert to superpayload in statement-distribution * Update primitives/src/v2/signed.rs Co-authored-by: Andronik <write@reusable.software> Co-authored-by: Andronik <write@reusable.software>
This commit is contained in:
committed by
GitHub
parent
22a7fad75f
commit
8a17c614f0
@@ -36,7 +36,8 @@ use polkadot_node_subsystem_util::{self as util, MIN_GOSSIP_PEERS};
|
||||
|
||||
use polkadot_primitives::v2::{
|
||||
AuthorityDiscoveryId, CandidateHash, CommittedCandidateReceipt, CompactStatement, Hash,
|
||||
SigningContext, ValidatorId, ValidatorIndex, ValidatorSignature,
|
||||
SignedStatement, SigningContext, UncheckedSignedStatement, ValidatorId, ValidatorIndex,
|
||||
ValidatorSignature,
|
||||
};
|
||||
use polkadot_subsystem::{
|
||||
jaeger,
|
||||
@@ -780,10 +781,10 @@ impl ActiveHeadData {
|
||||
/// without modifying the internal state.
|
||||
fn check_useful_or_unknown(
|
||||
&self,
|
||||
statement: &UncheckedSignedFullStatement,
|
||||
statement: &UncheckedSignedStatement,
|
||||
) -> std::result::Result<(), DeniedStatement> {
|
||||
let validator_index = statement.unchecked_validator_index();
|
||||
let compact = statement.unchecked_payload().to_compact();
|
||||
let compact = statement.unchecked_payload();
|
||||
let comparator = StoredStatementComparator {
|
||||
compact: compact.clone(),
|
||||
validator_index,
|
||||
@@ -857,8 +858,8 @@ impl ActiveHeadData {
|
||||
fn check_statement_signature(
|
||||
head: &ActiveHeadData,
|
||||
relay_parent: Hash,
|
||||
statement: UncheckedSignedFullStatement,
|
||||
) -> std::result::Result<SignedFullStatement, UncheckedSignedFullStatement> {
|
||||
statement: UncheckedSignedStatement,
|
||||
) -> std::result::Result<SignedStatement, UncheckedSignedStatement> {
|
||||
let signing_context =
|
||||
SigningContext { session_index: head.session_index, parent_hash: relay_parent };
|
||||
|
||||
@@ -1387,24 +1388,57 @@ async fn handle_incoming_message<'a>(
|
||||
return None
|
||||
}
|
||||
|
||||
let checked_compact = {
|
||||
let (compact, validator_index) = message.get_fingerprint();
|
||||
let signature = message.get_signature();
|
||||
|
||||
let unchecked_compact = UncheckedSignedStatement::new(compact, validator_index, signature);
|
||||
|
||||
match active_head.check_useful_or_unknown(&unchecked_compact) {
|
||||
Ok(()) => {},
|
||||
Err(DeniedStatement::NotUseful) => return None,
|
||||
Err(DeniedStatement::UsefulButKnown) => {
|
||||
report_peer(ctx, peer, BENEFIT_VALID_STATEMENT).await;
|
||||
return None
|
||||
},
|
||||
}
|
||||
|
||||
// check the signature on the statement.
|
||||
match check_statement_signature(&active_head, relay_parent, unchecked_compact) {
|
||||
Err(statement) => {
|
||||
tracing::debug!(
|
||||
target: LOG_TARGET,
|
||||
?peer,
|
||||
?statement,
|
||||
"Invalid statement signature"
|
||||
);
|
||||
report_peer(ctx, peer, COST_INVALID_SIGNATURE).await;
|
||||
return None
|
||||
},
|
||||
Ok(statement) => statement,
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch from the network only after signature and usefulness checks are completed.
|
||||
let is_large_statement = message.is_large_statement();
|
||||
let statement =
|
||||
retrieve_statement_from_message(peer, message, active_head, ctx, req_sender, metrics)
|
||||
.await?;
|
||||
|
||||
match active_head.check_useful_or_unknown(&statement) {
|
||||
Ok(()) => {},
|
||||
Err(DeniedStatement::NotUseful) => return None,
|
||||
Err(DeniedStatement::UsefulButKnown) => {
|
||||
report_peer(ctx, peer, BENEFIT_VALID_STATEMENT).await;
|
||||
return None
|
||||
},
|
||||
}
|
||||
let payload = statement.unchecked_into_payload();
|
||||
|
||||
// check the signature on the statement.
|
||||
let statement = match check_statement_signature(&active_head, relay_parent, statement) {
|
||||
Err(statement) => {
|
||||
tracing::debug!(target: LOG_TARGET, ?peer, ?statement, "Invalid statement signature");
|
||||
report_peer(ctx, peer, COST_INVALID_SIGNATURE).await;
|
||||
// Upgrade the `Signed` wrapper from the compact payload to the full payload.
|
||||
// This fails if the payload doesn't encode correctly.
|
||||
let statement: SignedFullStatement = match checked_compact.convert_to_superpayload(payload) {
|
||||
Err((compact, _)) => {
|
||||
tracing::debug!(
|
||||
target: LOG_TARGET,
|
||||
?peer,
|
||||
?compact,
|
||||
is_large_statement,
|
||||
"Full statement had bad payload."
|
||||
);
|
||||
report_peer(ctx, peer, COST_WRONG_HASH).await;
|
||||
return None
|
||||
},
|
||||
Ok(statement) => statement,
|
||||
|
||||
@@ -105,14 +105,16 @@ fn active_head_accepts_only_2_seconded_per_validator() {
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("should be signed");
|
||||
assert!(head_data.check_useful_or_unknown(&a_seconded_val_0.clone().into()).is_ok());
|
||||
assert!(head_data
|
||||
.check_useful_or_unknown(&a_seconded_val_0.clone().convert_payload().into())
|
||||
.is_ok());
|
||||
let noted = head_data.note_statement(a_seconded_val_0.clone());
|
||||
|
||||
assert_matches!(noted, NotedStatement::Fresh(_));
|
||||
|
||||
// note A (duplicate)
|
||||
assert_eq!(
|
||||
head_data.check_useful_or_unknown(&a_seconded_val_0.clone().into()),
|
||||
head_data.check_useful_or_unknown(&a_seconded_val_0.clone().convert_payload().into()),
|
||||
Err(DeniedStatement::UsefulButKnown),
|
||||
);
|
||||
let noted = head_data.note_statement(a_seconded_val_0);
|
||||
@@ -130,7 +132,9 @@ fn active_head_accepts_only_2_seconded_per_validator() {
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("should be signed");
|
||||
assert!(head_data.check_useful_or_unknown(&statement.clone().into()).is_ok());
|
||||
assert!(head_data
|
||||
.check_useful_or_unknown(&statement.clone().convert_payload().into())
|
||||
.is_ok());
|
||||
let noted = head_data.note_statement(statement);
|
||||
assert_matches!(noted, NotedStatement::Fresh(_));
|
||||
|
||||
@@ -146,7 +150,7 @@ fn active_head_accepts_only_2_seconded_per_validator() {
|
||||
.flatten()
|
||||
.expect("should be signed");
|
||||
assert_eq!(
|
||||
head_data.check_useful_or_unknown(&statement.clone().into()),
|
||||
head_data.check_useful_or_unknown(&statement.clone().convert_payload().into()),
|
||||
Err(DeniedStatement::NotUseful),
|
||||
);
|
||||
let noted = head_data.note_statement(statement);
|
||||
@@ -163,7 +167,9 @@ fn active_head_accepts_only_2_seconded_per_validator() {
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("should be signed");
|
||||
assert!(head_data.check_useful_or_unknown(&statement.clone().into()).is_ok());
|
||||
assert!(head_data
|
||||
.check_useful_or_unknown(&statement.clone().convert_payload().into())
|
||||
.is_ok());
|
||||
let noted = head_data.note_statement(statement);
|
||||
assert_matches!(noted, NotedStatement::Fresh(_));
|
||||
|
||||
@@ -178,7 +184,9 @@ fn active_head_accepts_only_2_seconded_per_validator() {
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("should be signed");
|
||||
assert!(head_data.check_useful_or_unknown(&statement.clone().into()).is_ok());
|
||||
assert!(head_data
|
||||
.check_useful_or_unknown(&statement.clone().convert_payload().into())
|
||||
.is_ok());
|
||||
let noted = head_data.note_statement(statement);
|
||||
assert_matches!(noted, NotedStatement::Fresh(_));
|
||||
}
|
||||
@@ -428,7 +436,9 @@ fn peer_view_update_sends_messages() {
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("should be signed");
|
||||
assert!(data.check_useful_or_unknown(&statement.clone().into()).is_ok());
|
||||
assert!(data
|
||||
.check_useful_or_unknown(&statement.clone().convert_payload().into())
|
||||
.is_ok());
|
||||
let noted = data.note_statement(statement);
|
||||
|
||||
assert_matches!(noted, NotedStatement::Fresh(_));
|
||||
@@ -443,7 +453,9 @@ fn peer_view_update_sends_messages() {
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("should be signed");
|
||||
assert!(data.check_useful_or_unknown(&statement.clone().into()).is_ok());
|
||||
assert!(data
|
||||
.check_useful_or_unknown(&statement.clone().convert_payload().into())
|
||||
.is_ok());
|
||||
let noted = data.note_statement(statement);
|
||||
|
||||
assert_matches!(noted, NotedStatement::Fresh(_));
|
||||
@@ -458,7 +470,9 @@ fn peer_view_update_sends_messages() {
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("should be signed");
|
||||
assert!(data.check_useful_or_unknown(&statement.clone().into()).is_ok());
|
||||
assert!(data
|
||||
.check_useful_or_unknown(&statement.clone().convert_payload().into())
|
||||
.is_ok());
|
||||
let noted = data.note_statement(statement);
|
||||
assert_matches!(noted, NotedStatement::Fresh(_));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user