Add some magic to signed statements and approval votes (#2585)

* add a magic number to backing statements encoded

* fix fallout in statement table

* fix some fallout in backing

* add magic to approval votes

* remove last references to Candidate variant

* update size-hint
This commit is contained in:
Robert Habermeier
2021-03-09 11:17:30 -06:00
committed by GitHub
parent d859734ed9
commit 30e4a67f0c
7 changed files with 93 additions and 44 deletions
@@ -697,7 +697,9 @@ fn approval_signing_payload(
approval_vote: ApprovalVote, approval_vote: ApprovalVote,
session_index: SessionIndex, session_index: SessionIndex,
) -> Vec<u8> { ) -> Vec<u8> {
(approval_vote, session_index).encode() const MAGIC: [u8; 4] = *b"APPR";
(MAGIC, approval_vote, session_index).encode()
} }
// `Option::cmp` treats `None` as less than `Some`. // `Option::cmp` treats `None` as less than `Some`.
+2 -2
View File
@@ -195,7 +195,7 @@ struct InvalidErasureRoot;
// the code. So this does the necessary conversion. // the code. So this does the necessary conversion.
fn primitive_statement_to_table(s: &SignedFullStatement) -> TableSignedStatement { fn primitive_statement_to_table(s: &SignedFullStatement) -> TableSignedStatement {
let statement = match s.payload() { let statement = match s.payload() {
Statement::Seconded(c) => TableStatement::Candidate(c.clone()), Statement::Seconded(c) => TableStatement::Seconded(c.clone()),
Statement::Valid(h) => TableStatement::Valid(h.clone()), Statement::Valid(h) => TableStatement::Valid(h.clone()),
Statement::Invalid(h) => TableStatement::Invalid(h.clone()), Statement::Invalid(h) => TableStatement::Invalid(h.clone()),
}; };
@@ -1239,7 +1239,7 @@ mod tests {
statement: TableStatement, statement: TableStatement,
) -> Statement { ) -> Statement {
match statement { match statement {
TableStatement::Candidate(committed_candidate_receipt) => Statement::Seconded(committed_candidate_receipt), TableStatement::Seconded(committed_candidate_receipt) => Statement::Seconded(committed_candidate_receipt),
TableStatement::Valid(candidate_hash) => Statement::Valid(candidate_hash), TableStatement::Valid(candidate_hash) => Statement::Valid(candidate_hash),
TableStatement::Invalid(candidate_hash) => Statement::Invalid(candidate_hash), TableStatement::Invalid(candidate_hash) => Statement::Invalid(candidate_hash),
} }
@@ -172,7 +172,7 @@ impl PeerRelayParentKnowledge {
} }
let new_known = match fingerprint.0 { let new_known = match fingerprint.0 {
CompactStatement::Candidate(ref h) => { CompactStatement::Seconded(ref h) => {
self.seconded_counts.entry(fingerprint.1) self.seconded_counts.entry(fingerprint.1)
.or_default() .or_default()
.note_local(h.clone()); .note_local(h.clone());
@@ -224,7 +224,7 @@ impl PeerRelayParentKnowledge {
} }
let candidate_hash = match fingerprint.0 { let candidate_hash = match fingerprint.0 {
CompactStatement::Candidate(ref h) => { CompactStatement::Seconded(ref h) => {
let allowed_remote = self.seconded_counts.entry(fingerprint.1) let allowed_remote = self.seconded_counts.entry(fingerprint.1)
.or_insert_with(Default::default) .or_insert_with(Default::default)
.note_remote(h.clone()); .note_remote(h.clone());
@@ -437,7 +437,7 @@ impl ActiveHeadData {
}; };
match comparator.compact { match comparator.compact {
CompactStatement::Candidate(h) => { CompactStatement::Seconded(h) => {
let seconded_so_far = self.seconded_counts.entry(validator_index).or_insert(0); let seconded_so_far = self.seconded_counts.entry(validator_index).or_insert(0);
if *seconded_so_far >= VC_THRESHOLD { if *seconded_so_far >= VC_THRESHOLD {
return NotedStatement::NotUseful; return NotedStatement::NotUseful;
@@ -1241,8 +1241,8 @@ mod tests {
assert!(knowledge.received_message_count.is_empty()); assert!(knowledge.received_message_count.is_empty());
// Make the peer aware of the candidate. // Make the peer aware of the candidate.
assert_eq!(knowledge.send(&(CompactStatement::Candidate(hash_a), ValidatorIndex(0))), Some(true)); assert_eq!(knowledge.send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0))), Some(true));
assert_eq!(knowledge.send(&(CompactStatement::Candidate(hash_a), ValidatorIndex(1))), Some(false)); assert_eq!(knowledge.send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(1))), Some(false));
assert!(knowledge.known_candidates.contains(&hash_a)); assert!(knowledge.known_candidates.contains(&hash_a));
assert_eq!(knowledge.sent_statements.len(), 2); assert_eq!(knowledge.sent_statements.len(), 2);
assert!(knowledge.received_statements.is_empty()); assert!(knowledge.received_statements.is_empty());
@@ -1263,8 +1263,8 @@ mod tests {
let mut knowledge = PeerRelayParentKnowledge::default(); let mut knowledge = PeerRelayParentKnowledge::default();
let hash_a = CandidateHash([1; 32].into()); let hash_a = CandidateHash([1; 32].into());
assert!(knowledge.receive(&(CompactStatement::Candidate(hash_a), ValidatorIndex(0)), 3).unwrap()); assert!(knowledge.receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3).unwrap());
assert!(knowledge.send(&(CompactStatement::Candidate(hash_a), ValidatorIndex(0))).is_none()); assert!(knowledge.send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0))).is_none());
} }
#[test] #[test]
@@ -1279,7 +1279,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
knowledge.receive(&(CompactStatement::Candidate(hash_a), ValidatorIndex(0)), 3), knowledge.receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3),
Ok(true), Ok(true),
); );
@@ -1312,12 +1312,12 @@ mod tests {
let hash_c = CandidateHash([3; 32].into()); let hash_c = CandidateHash([3; 32].into());
assert_eq!( assert_eq!(
knowledge.receive(&(CompactStatement::Candidate(hash_b), ValidatorIndex(0)), 3), knowledge.receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3),
Ok(true), Ok(true),
); );
assert_eq!( assert_eq!(
knowledge.receive(&(CompactStatement::Candidate(hash_c), ValidatorIndex(0)), 3), knowledge.receive(&(CompactStatement::Seconded(hash_c), ValidatorIndex(0)), 3),
Err(COST_UNEXPECTED_STATEMENT), Err(COST_UNEXPECTED_STATEMENT),
); );
@@ -1328,7 +1328,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
knowledge.receive(&(CompactStatement::Candidate(hash_b), ValidatorIndex(0)), 3), knowledge.receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3),
Err(COST_DUPLICATE_STATEMENT), Err(COST_DUPLICATE_STATEMENT),
); );
} }
@@ -1451,7 +1451,7 @@ mod tests {
assert!(c_knowledge.known_candidates.contains(&candidate_hash)); assert!(c_knowledge.known_candidates.contains(&candidate_hash));
assert!(c_knowledge.sent_statements.contains( assert!(c_knowledge.sent_statements.contains(
&(CompactStatement::Candidate(candidate_hash), ValidatorIndex(0)) &(CompactStatement::Seconded(candidate_hash), ValidatorIndex(0))
)); ));
assert!(c_knowledge.sent_statements.contains( assert!(c_knowledge.sent_statements.contains(
&(CompactStatement::Valid(candidate_hash), ValidatorIndex(1)) &(CompactStatement::Valid(candidate_hash), ValidatorIndex(1))
+1 -1
View File
@@ -71,7 +71,7 @@ impl Statement {
/// of the candidate. /// of the candidate.
pub fn to_compact(&self) -> CompactStatement { pub fn to_compact(&self) -> CompactStatement {
match *self { match *self {
Statement::Seconded(ref c) => CompactStatement::Candidate(c.hash()), Statement::Seconded(ref c) => CompactStatement::Seconded(c.hash()),
Statement::Valid(hash) => CompactStatement::Valid(hash), Statement::Valid(hash) => CompactStatement::Valid(hash),
Statement::Invalid(hash) => CompactStatement::Invalid(hash), Statement::Invalid(hash) => CompactStatement::Invalid(hash),
} }
+53 -6
View File
@@ -677,27 +677,74 @@ pub struct ErasureChunk {
pub proof: Vec<Vec<u8>>, pub proof: Vec<Vec<u8>>,
} }
const BACKING_STATEMENT_MAGIC: [u8; 4] = *b"BKNG";
/// Statements that can be made about parachain candidates. These are the /// Statements that can be made about parachain candidates. These are the
/// actual values that are signed. /// actual values that are signed.
#[derive(Clone, PartialEq, Eq, Encode, Decode)] #[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Hash))] #[cfg_attr(feature = "std", derive(Debug, Hash))]
pub enum CompactStatement { pub enum CompactStatement {
/// Proposal of a parachain candidate. /// Proposal of a parachain candidate.
#[codec(index = 1)] Seconded(CandidateHash),
Candidate(CandidateHash),
/// State that a parachain candidate is valid. /// State that a parachain candidate is valid.
#[codec(index = 2)]
Valid(CandidateHash), Valid(CandidateHash),
/// State that a parachain candidate is invalid. /// State that a parachain candidate is invalid.
Invalid(CandidateHash),
}
// Inner helper for codec on `CompactStatement`.
#[derive(Encode, Decode)]
enum CompactStatementInner {
#[codec(index = 1)]
Seconded(CandidateHash),
#[codec(index = 2)]
Valid(CandidateHash),
#[codec(index = 3)] #[codec(index = 3)]
Invalid(CandidateHash), Invalid(CandidateHash),
} }
impl From<CompactStatement> for CompactStatementInner {
fn from(s: CompactStatement) -> Self {
match s {
CompactStatement::Seconded(h) => CompactStatementInner::Seconded(h),
CompactStatement::Valid(h) => CompactStatementInner::Valid(h),
CompactStatement::Invalid(h) => CompactStatementInner::Invalid(h),
}
}
}
impl parity_scale_codec::Encode for CompactStatement {
fn size_hint(&self) -> usize {
// magic + discriminant + payload
4 + 1 + 32
}
fn encode_to<T: parity_scale_codec::Output + ?Sized>(&self, dest: &mut T) {
dest.write(&BACKING_STATEMENT_MAGIC);
CompactStatementInner::from(self.clone()).encode_to(dest)
}
}
impl parity_scale_codec::Decode for CompactStatement {
fn decode<I: parity_scale_codec::Input>(input: &mut I) -> Result<Self, parity_scale_codec::Error> {
let maybe_magic = <[u8; 4]>::decode(input)?;
if maybe_magic != BACKING_STATEMENT_MAGIC {
return Err(parity_scale_codec::Error::from("invalid magic string"));
}
Ok(match CompactStatementInner::decode(input)? {
CompactStatementInner::Seconded(h) => CompactStatement::Seconded(h),
CompactStatementInner::Valid(h) => CompactStatement::Valid(h),
CompactStatementInner::Invalid(h) => CompactStatement::Invalid(h),
})
}
}
impl CompactStatement { impl CompactStatement {
/// Get the underlying candidate hash this references. /// Get the underlying candidate hash this references.
pub fn candidate_hash(&self) -> &CandidateHash { pub fn candidate_hash(&self) -> &CandidateHash {
match *self { match *self {
CompactStatement::Candidate(ref h) CompactStatement::Seconded(ref h)
| CompactStatement::Valid(ref h) | CompactStatement::Valid(ref h)
| CompactStatement::Invalid(ref h) | CompactStatement::Invalid(ref h)
=> h => h
@@ -740,7 +787,7 @@ impl ValidityAttestation {
) -> Vec<u8> { ) -> Vec<u8> {
match *self { match *self {
ValidityAttestation::Implicit(_) => ( ValidityAttestation::Implicit(_) => (
CompactStatement::Candidate(candidate_hash), CompactStatement::Seconded(candidate_hash),
signing_context, signing_context,
).encode(), ).encode(),
ValidityAttestation::Explicit(_) => ( ValidityAttestation::Explicit(_) => (
+21 -21
View File
@@ -66,7 +66,7 @@ pub enum Statement<Candidate, Digest> {
/// ///
/// Broadcasting two different candidate messages per round is not allowed. /// Broadcasting two different candidate messages per round is not allowed.
#[codec(index = 1)] #[codec(index = 1)]
Candidate(Candidate), Seconded(Candidate),
/// Broadcast by a authority to attest that the candidate with given digest is valid. /// Broadcast by a authority to attest that the candidate with given digest is valid.
#[codec(index = 2)] #[codec(index = 2)]
Valid(Digest), Valid(Digest),
@@ -115,10 +115,10 @@ impl<Candidate, Digest, Signature> ValidityDoubleVote<Candidate, Digest, Signatu
{ {
match self { match self {
Self::IssuedAndValidity((c, s1), (d, s2)) => { Self::IssuedAndValidity((c, s1), (d, s2)) => {
((Statement::Candidate(c), s1), (Statement::Valid(d), s2)) ((Statement::Seconded(c), s1), (Statement::Valid(d), s2))
} }
Self::IssuedAndInvalidity((c, s1), (d, s2)) => { Self::IssuedAndInvalidity((c, s1), (d, s2)) => {
((Statement::Candidate(c), s1), (Statement::Invalid(d), s2)) ((Statement::Seconded(c), s1), (Statement::Invalid(d), s2))
} }
Self::ValidityAndInvalidity(c, s1, s2) => { Self::ValidityAndInvalidity(c, s1, s2) => {
( (
@@ -134,7 +134,7 @@ impl<Candidate, Digest, Signature> ValidityDoubleVote<Candidate, Digest, Signatu
#[derive(PartialEq, Eq, Debug, Clone)] #[derive(PartialEq, Eq, Debug, Clone)]
pub enum DoubleSign<Candidate, Digest, Signature> { pub enum DoubleSign<Candidate, Digest, Signature> {
/// On candidate. /// On candidate.
Candidate(Candidate, Signature, Signature), Seconded(Candidate, Signature, Signature),
/// On validity. /// On validity.
Validity(Digest, Signature, Signature), Validity(Digest, Signature, Signature),
/// On invalidity. /// On invalidity.
@@ -146,7 +146,7 @@ impl<Candidate, Digest, Signature> DoubleSign<Candidate, Digest, Signature> {
/// precisely where in the process the issue was detected. /// precisely where in the process the issue was detected.
pub fn deconstruct(self) -> (Statement<Candidate, Digest>, Signature, Signature) { pub fn deconstruct(self) -> (Statement<Candidate, Digest>, Signature, Signature) {
match self { match self {
Self::Candidate(candidate, a, b) => (Statement::Candidate(candidate), a, b), Self::Seconded(candidate, a, b) => (Statement::Seconded(candidate), a, b),
Self::Validity(digest, a, b) => (Statement::Valid(digest), a, b), Self::Validity(digest, a, b) => (Statement::Valid(digest), a, b),
Self::Invalidity(digest, a, b) => (Statement::Invalid(digest), a, b), Self::Invalidity(digest, a, b) => (Statement::Invalid(digest), a, b),
} }
@@ -365,7 +365,7 @@ impl<Ctx: Context> Table<Ctx> {
let SignedStatement { statement, signature, sender: signer } = statement; let SignedStatement { statement, signature, sender: signer } = statement;
let res = match statement { let res = match statement {
Statement::Candidate(candidate) => self.import_candidate( Statement::Seconded(candidate) => self.import_candidate(
context, context,
signer.clone(), signer.clone(),
candidate, candidate,
@@ -429,7 +429,7 @@ impl<Ctx: Context> Table<Ctx> {
return Err(Misbehavior::UnauthorizedStatement(UnauthorizedStatement { return Err(Misbehavior::UnauthorizedStatement(UnauthorizedStatement {
statement: SignedStatement { statement: SignedStatement {
signature, signature,
statement: Statement::Candidate(candidate), statement: Statement::Seconded(candidate),
sender: authority, sender: authority,
}, },
})); }));
@@ -554,7 +554,7 @@ impl<Ctx: Context> Table<Ctx> {
// two signatures on same candidate // two signatures on same candidate
(ValidityVote::Issued(a), ValidityVote::Issued(b)) => (ValidityVote::Issued(a), ValidityVote::Issued(b)) =>
make_ds(DoubleSign::Candidate(votes.candidate.clone(), a, b)), make_ds(DoubleSign::Seconded(votes.candidate.clone(), a, b)),
// two signatures on same validity vote // two signatures on same validity vote
(ValidityVote::Valid(a), ValidityVote::Valid(b)) => (ValidityVote::Valid(a), ValidityVote::Valid(b)) =>
@@ -717,13 +717,13 @@ mod tests {
let mut table = create(); let mut table = create();
let statement_a = SignedStatement { let statement_a = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
let statement_b = SignedStatement { let statement_b = SignedStatement {
statement: Statement::Candidate(Candidate(2, 999)), statement: Statement::Seconded(Candidate(2, 999)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -753,7 +753,7 @@ mod tests {
let mut table = create(); let mut table = create();
let statement = SignedStatement { let statement = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -764,7 +764,7 @@ mod tests {
table.detected_misbehavior[&AuthorityId(1)][0], table.detected_misbehavior[&AuthorityId(1)][0],
Misbehavior::UnauthorizedStatement(UnauthorizedStatement { Misbehavior::UnauthorizedStatement(UnauthorizedStatement {
statement: SignedStatement { statement: SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}, },
@@ -786,7 +786,7 @@ mod tests {
let mut table = create(); let mut table = create();
let candidate_a = SignedStatement { let candidate_a = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -829,7 +829,7 @@ mod tests {
let mut table = create(); let mut table = create();
let statement = SignedStatement { let statement = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -878,7 +878,7 @@ mod tests {
let mut table = create(); let mut table = create();
let statement = SignedStatement { let statement = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -887,7 +887,7 @@ mod tests {
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1)));
let invalid_statement = SignedStatement { let invalid_statement = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(999), signature: Signature(999),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -910,7 +910,7 @@ mod tests {
let mut table = create(); let mut table = create();
let statement = SignedStatement { let statement = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -973,7 +973,7 @@ mod tests {
let mut table = create(); let mut table = create();
let statement = SignedStatement { let statement = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -1041,7 +1041,7 @@ mod tests {
// have 2/3 validity guarantors note validity. // have 2/3 validity guarantors note validity.
let mut table = create(); let mut table = create();
let statement = SignedStatement { let statement = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -1086,7 +1086,7 @@ mod tests {
let mut table = create(); let mut table = create();
let statement = SignedStatement { let statement = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
@@ -1112,7 +1112,7 @@ mod tests {
let mut table = create(); let mut table = create();
let statement = SignedStatement { let statement = SignedStatement {
statement: Statement::Candidate(Candidate(2, 100)), statement: Statement::Seconded(Candidate(2, 100)),
signature: Signature(1), signature: Signature(1),
sender: AuthorityId(1), sender: AuthorityId(1),
}; };
+1 -1
View File
@@ -53,7 +53,7 @@ pub mod v1 {
match *s { match *s {
generic::Statement::Valid(s) => PrimitiveStatement::Valid(s), generic::Statement::Valid(s) => PrimitiveStatement::Valid(s),
generic::Statement::Invalid(s) => PrimitiveStatement::Invalid(s), generic::Statement::Invalid(s) => PrimitiveStatement::Invalid(s),
generic::Statement::Candidate(ref s) => PrimitiveStatement::Candidate(s.hash()), generic::Statement::Seconded(ref s) => PrimitiveStatement::Seconded(s.hash()),
} }
} }
} }