diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs index 550c00cf0d..60f1135f70 100644 --- a/polkadot/node/core/approval-voting/src/lib.rs +++ b/polkadot/node/core/approval-voting/src/lib.rs @@ -697,7 +697,9 @@ fn approval_signing_payload( approval_vote: ApprovalVote, session_index: SessionIndex, ) -> Vec { - (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`. diff --git a/polkadot/node/core/backing/src/lib.rs b/polkadot/node/core/backing/src/lib.rs index 777279640e..a0ed6e26c9 100644 --- a/polkadot/node/core/backing/src/lib.rs +++ b/polkadot/node/core/backing/src/lib.rs @@ -195,7 +195,7 @@ struct InvalidErasureRoot; // the code. So this does the necessary conversion. fn primitive_statement_to_table(s: &SignedFullStatement) -> TableSignedStatement { 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::Invalid(h) => TableStatement::Invalid(h.clone()), }; @@ -1239,7 +1239,7 @@ mod tests { statement: TableStatement, ) -> 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::Invalid(candidate_hash) => Statement::Invalid(candidate_hash), } diff --git a/polkadot/node/network/statement-distribution/src/lib.rs b/polkadot/node/network/statement-distribution/src/lib.rs index 5527c6344c..bca8160a64 100644 --- a/polkadot/node/network/statement-distribution/src/lib.rs +++ b/polkadot/node/network/statement-distribution/src/lib.rs @@ -172,7 +172,7 @@ impl PeerRelayParentKnowledge { } let new_known = match fingerprint.0 { - CompactStatement::Candidate(ref h) => { + CompactStatement::Seconded(ref h) => { self.seconded_counts.entry(fingerprint.1) .or_default() .note_local(h.clone()); @@ -224,7 +224,7 @@ impl PeerRelayParentKnowledge { } let candidate_hash = match fingerprint.0 { - CompactStatement::Candidate(ref h) => { + CompactStatement::Seconded(ref h) => { let allowed_remote = self.seconded_counts.entry(fingerprint.1) .or_insert_with(Default::default) .note_remote(h.clone()); @@ -437,7 +437,7 @@ impl ActiveHeadData { }; match comparator.compact { - CompactStatement::Candidate(h) => { + CompactStatement::Seconded(h) => { let seconded_so_far = self.seconded_counts.entry(validator_index).or_insert(0); if *seconded_so_far >= VC_THRESHOLD { return NotedStatement::NotUseful; @@ -1241,8 +1241,8 @@ mod tests { assert!(knowledge.received_message_count.is_empty()); // Make the peer aware of the candidate. - assert_eq!(knowledge.send(&(CompactStatement::Candidate(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(0))), Some(true)); + assert_eq!(knowledge.send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(1))), Some(false)); assert!(knowledge.known_candidates.contains(&hash_a)); assert_eq!(knowledge.sent_statements.len(), 2); assert!(knowledge.received_statements.is_empty()); @@ -1263,8 +1263,8 @@ mod tests { let mut knowledge = PeerRelayParentKnowledge::default(); let hash_a = CandidateHash([1; 32].into()); - assert!(knowledge.receive(&(CompactStatement::Candidate(hash_a), ValidatorIndex(0)), 3).unwrap()); - assert!(knowledge.send(&(CompactStatement::Candidate(hash_a), ValidatorIndex(0))).is_none()); + assert!(knowledge.receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3).unwrap()); + assert!(knowledge.send(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0))).is_none()); } #[test] @@ -1279,7 +1279,7 @@ mod tests { ); assert_eq!( - knowledge.receive(&(CompactStatement::Candidate(hash_a), ValidatorIndex(0)), 3), + knowledge.receive(&(CompactStatement::Seconded(hash_a), ValidatorIndex(0)), 3), Ok(true), ); @@ -1312,12 +1312,12 @@ mod tests { let hash_c = CandidateHash([3; 32].into()); assert_eq!( - knowledge.receive(&(CompactStatement::Candidate(hash_b), ValidatorIndex(0)), 3), + knowledge.receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3), Ok(true), ); assert_eq!( - knowledge.receive(&(CompactStatement::Candidate(hash_c), ValidatorIndex(0)), 3), + knowledge.receive(&(CompactStatement::Seconded(hash_c), ValidatorIndex(0)), 3), Err(COST_UNEXPECTED_STATEMENT), ); @@ -1328,7 +1328,7 @@ mod tests { ); assert_eq!( - knowledge.receive(&(CompactStatement::Candidate(hash_b), ValidatorIndex(0)), 3), + knowledge.receive(&(CompactStatement::Seconded(hash_b), ValidatorIndex(0)), 3), Err(COST_DUPLICATE_STATEMENT), ); } @@ -1451,7 +1451,7 @@ mod tests { assert!(c_knowledge.known_candidates.contains(&candidate_hash)); assert!(c_knowledge.sent_statements.contains( - &(CompactStatement::Candidate(candidate_hash), ValidatorIndex(0)) + &(CompactStatement::Seconded(candidate_hash), ValidatorIndex(0)) )); assert!(c_knowledge.sent_statements.contains( &(CompactStatement::Valid(candidate_hash), ValidatorIndex(1)) diff --git a/polkadot/node/primitives/src/lib.rs b/polkadot/node/primitives/src/lib.rs index b00df8539d..313fe930d1 100644 --- a/polkadot/node/primitives/src/lib.rs +++ b/polkadot/node/primitives/src/lib.rs @@ -71,7 +71,7 @@ impl Statement { /// of the candidate. pub fn to_compact(&self) -> CompactStatement { 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::Invalid(hash) => CompactStatement::Invalid(hash), } diff --git a/polkadot/primitives/src/v0.rs b/polkadot/primitives/src/v0.rs index 5bc027b1b3..d6dfffb1f0 100644 --- a/polkadot/primitives/src/v0.rs +++ b/polkadot/primitives/src/v0.rs @@ -677,27 +677,74 @@ pub struct ErasureChunk { pub proof: Vec>, } +const BACKING_STATEMENT_MAGIC: [u8; 4] = *b"BKNG"; + /// Statements that can be made about parachain candidates. These are the /// actual values that are signed. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug, Hash))] pub enum CompactStatement { /// Proposal of a parachain candidate. - #[codec(index = 1)] - Candidate(CandidateHash), + Seconded(CandidateHash), /// State that a parachain candidate is valid. - #[codec(index = 2)] Valid(CandidateHash), /// 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)] Invalid(CandidateHash), } +impl From 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(&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(input: &mut I) -> Result { + 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 { /// Get the underlying candidate hash this references. pub fn candidate_hash(&self) -> &CandidateHash { match *self { - CompactStatement::Candidate(ref h) + CompactStatement::Seconded(ref h) | CompactStatement::Valid(ref h) | CompactStatement::Invalid(ref h) => h @@ -740,7 +787,7 @@ impl ValidityAttestation { ) -> Vec { match *self { ValidityAttestation::Implicit(_) => ( - CompactStatement::Candidate(candidate_hash), + CompactStatement::Seconded(candidate_hash), signing_context, ).encode(), ValidityAttestation::Explicit(_) => ( diff --git a/polkadot/statement-table/src/generic.rs b/polkadot/statement-table/src/generic.rs index b103b382ae..f9a6bce890 100644 --- a/polkadot/statement-table/src/generic.rs +++ b/polkadot/statement-table/src/generic.rs @@ -66,7 +66,7 @@ pub enum Statement { /// /// Broadcasting two different candidate messages per round is not allowed. #[codec(index = 1)] - Candidate(Candidate), + Seconded(Candidate), /// Broadcast by a authority to attest that the candidate with given digest is valid. #[codec(index = 2)] Valid(Digest), @@ -115,10 +115,10 @@ impl ValidityDoubleVote { - ((Statement::Candidate(c), s1), (Statement::Valid(d), s2)) + ((Statement::Seconded(c), s1), (Statement::Valid(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) => { ( @@ -134,7 +134,7 @@ impl ValidityDoubleVote { /// On candidate. - Candidate(Candidate, Signature, Signature), + Seconded(Candidate, Signature, Signature), /// On validity. Validity(Digest, Signature, Signature), /// On invalidity. @@ -146,7 +146,7 @@ impl DoubleSign { /// precisely where in the process the issue was detected. pub fn deconstruct(self) -> (Statement, Signature, Signature) { 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::Invalidity(digest, a, b) => (Statement::Invalid(digest), a, b), } @@ -365,7 +365,7 @@ impl Table { let SignedStatement { statement, signature, sender: signer } = statement; let res = match statement { - Statement::Candidate(candidate) => self.import_candidate( + Statement::Seconded(candidate) => self.import_candidate( context, signer.clone(), candidate, @@ -429,7 +429,7 @@ impl Table { return Err(Misbehavior::UnauthorizedStatement(UnauthorizedStatement { statement: SignedStatement { signature, - statement: Statement::Candidate(candidate), + statement: Statement::Seconded(candidate), sender: authority, }, })); @@ -554,7 +554,7 @@ impl Table { // two signatures on same candidate (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 (ValidityVote::Valid(a), ValidityVote::Valid(b)) => @@ -717,13 +717,13 @@ mod tests { let mut table = create(); let statement_a = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; let statement_b = SignedStatement { - statement: Statement::Candidate(Candidate(2, 999)), + statement: Statement::Seconded(Candidate(2, 999)), signature: Signature(1), sender: AuthorityId(1), }; @@ -753,7 +753,7 @@ mod tests { let mut table = create(); let statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; @@ -764,7 +764,7 @@ mod tests { table.detected_misbehavior[&AuthorityId(1)][0], Misbehavior::UnauthorizedStatement(UnauthorizedStatement { statement: SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }, @@ -786,7 +786,7 @@ mod tests { let mut table = create(); let candidate_a = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; @@ -829,7 +829,7 @@ mod tests { let mut table = create(); let statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; @@ -878,7 +878,7 @@ mod tests { let mut table = create(); let statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; @@ -887,7 +887,7 @@ mod tests { assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1))); let invalid_statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(999), sender: AuthorityId(1), }; @@ -910,7 +910,7 @@ mod tests { let mut table = create(); let statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; @@ -973,7 +973,7 @@ mod tests { let mut table = create(); let statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; @@ -1041,7 +1041,7 @@ mod tests { // have 2/3 validity guarantors note validity. let mut table = create(); let statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; @@ -1086,7 +1086,7 @@ mod tests { let mut table = create(); let statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; @@ -1112,7 +1112,7 @@ mod tests { let mut table = create(); let statement = SignedStatement { - statement: Statement::Candidate(Candidate(2, 100)), + statement: Statement::Seconded(Candidate(2, 100)), signature: Signature(1), sender: AuthorityId(1), }; diff --git a/polkadot/statement-table/src/lib.rs b/polkadot/statement-table/src/lib.rs index a00b582b7d..aa5a9362b1 100644 --- a/polkadot/statement-table/src/lib.rs +++ b/polkadot/statement-table/src/lib.rs @@ -53,7 +53,7 @@ pub mod v1 { match *s { generic::Statement::Valid(s) => PrimitiveStatement::Valid(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()), } } }