@@ -120,42 +120,9 @@ where
120120 EPT : ExecutionProtocol ,
121121{
122122 fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
123- match ( & self , other) {
124- ( Self :: Qc ( qc_1) , Self :: Qc ( qc_2) ) => {
125- if qc_1. get_round ( ) == qc_2. get_round ( ) {
126- None
127- } else {
128- Some ( qc_1. get_round ( ) . cmp ( & qc_2. get_round ( ) ) )
129- }
130- }
131- ( Self :: Tip ( tip_1) , Self :: Tip ( tip_2) ) => {
132- if tip_1. block_header . block_round == tip_2. block_header . block_round {
133- None
134- } else {
135- Some (
136- tip_1
137- . block_header
138- . block_round
139- . cmp ( & tip_2. block_header . block_round ) ,
140- )
141- }
142- }
143- ( Self :: Qc ( qc_1) , Self :: Tip ( tip_2) ) => {
144- if qc_1. get_round ( ) == tip_2. block_header . block_round {
145- // QC takes precedence
146- Some ( std:: cmp:: Ordering :: Greater )
147- } else {
148- Some ( qc_1. get_round ( ) . cmp ( & tip_2. block_header . block_round ) )
149- }
150- }
151- ( Self :: Tip ( tip_1) , Self :: Qc ( qc_2) ) => {
152- if tip_1. block_header . block_round == qc_2. get_round ( ) {
153- // QC takes precedence
154- Some ( std:: cmp:: Ordering :: Less )
155- } else {
156- Some ( tip_1. block_header . block_round . cmp ( & qc_2. get_round ( ) ) )
157- }
158- }
123+ match self . rank ( ) . cmp ( & other. rank ( ) ) {
124+ std:: cmp:: Ordering :: Equal if self != other => None ,
125+ ord => Some ( ord) ,
159126 }
160127 }
161128}
@@ -166,6 +133,18 @@ where
166133 SCT : SignatureCollection < NodeIdPubKey = CertificateSignaturePubKey < ST > > ,
167134 EPT : ExecutionProtocol ,
168135{
136+ pub fn rank ( & self ) -> HighExtendRank {
137+ match & self {
138+ Self :: Tip ( tip) => HighExtendRank :: Tip {
139+ tip_round : tip. block_header . block_round ,
140+ qc_round : tip. block_header . qc . get_round ( ) ,
141+ } ,
142+ Self :: Qc ( qc) => HighExtendRank :: Qc {
143+ qc_round : qc. get_round ( ) ,
144+ } ,
145+ }
146+ }
147+
169148 pub fn qc ( & self ) -> & QuorumCertificate < SCT > {
170149 match & self {
171150 Self :: Tip ( tip) => & tip. block_header . qc ,
@@ -238,6 +217,17 @@ where
238217 SCT : SignatureCollection < NodeIdPubKey = CertificateSignaturePubKey < ST > > ,
239218 EPT : ExecutionProtocol ,
240219{
220+ pub fn rank ( & self ) -> HighExtendRank {
221+ match & self {
222+ Self :: Tip ( tip, _) => HighExtendRank :: Tip {
223+ tip_round : tip. block_header . block_round ,
224+ qc_round : tip. block_header . qc . get_round ( ) ,
225+ } ,
226+ Self :: Qc ( qc) => HighExtendRank :: Qc {
227+ qc_round : qc. get_round ( ) ,
228+ } ,
229+ }
230+ }
241231 pub fn qc ( & self ) -> & QuorumCertificate < SCT > {
242232 match & self {
243233 Self :: Tip ( tip, _) => & tip. block_header . qc ,
@@ -315,6 +305,81 @@ where
315305 }
316306}
317307
308+ #[ derive( PartialEq , Eq ) ]
309+ pub enum HighExtendRank {
310+ Tip { tip_round : Round , qc_round : Round } ,
311+ Qc { qc_round : Round } ,
312+ }
313+
314+ impl PartialOrd for HighExtendRank {
315+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
316+ Some ( self . cmp ( other) )
317+ }
318+ }
319+
320+ impl Ord for HighExtendRank {
321+ fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
322+ match ( & self , other) {
323+ (
324+ Self :: Qc {
325+ qc_round : qc_round_1,
326+ } ,
327+ Self :: Qc {
328+ qc_round : qc_round_2,
329+ } ,
330+ ) => qc_round_1. cmp ( qc_round_2) ,
331+ (
332+ Self :: Tip {
333+ qc_round : qc_round_1,
334+ tip_round : tip_round_1,
335+ } ,
336+ Self :: Tip {
337+ qc_round : qc_round_2,
338+ tip_round : tip_round_2,
339+ } ,
340+ ) => {
341+ if tip_round_1 != tip_round_2 {
342+ tip_round_1. cmp ( tip_round_2)
343+ } else {
344+ qc_round_1. cmp ( qc_round_2)
345+ }
346+ }
347+ (
348+ Self :: Qc {
349+ qc_round : qc_round_1,
350+ } ,
351+ Self :: Tip {
352+ qc_round : _,
353+ tip_round : tip_round_2,
354+ } ,
355+ ) => {
356+ if qc_round_1 == tip_round_2 {
357+ // QC takes precedence
358+ std:: cmp:: Ordering :: Greater
359+ } else {
360+ qc_round_1. cmp ( tip_round_2)
361+ }
362+ }
363+ (
364+ Self :: Tip {
365+ qc_round : _,
366+ tip_round : tip_round_1,
367+ } ,
368+ Self :: Qc {
369+ qc_round : qc_round_2,
370+ } ,
371+ ) => {
372+ if tip_round_1 == qc_round_2 {
373+ // QC takes precedence
374+ std:: cmp:: Ordering :: Less
375+ } else {
376+ tip_round_1. cmp ( qc_round_2)
377+ }
378+ }
379+ }
380+ }
381+ }
382+
318383/// Data to include in a timeout
319384#[ derive( Clone , Debug , PartialEq , Eq , Hash , RlpEncodable , RlpDecodable , Serialize ) ]
320385pub struct TimeoutInfo {
@@ -329,6 +394,21 @@ pub struct TimeoutInfo {
329394 pub high_tip_round : Round ,
330395}
331396
397+ impl TimeoutInfo {
398+ pub fn rank ( & self ) -> HighExtendRank {
399+ if self . high_tip_round == GENESIS_ROUND {
400+ HighExtendRank :: Qc {
401+ qc_round : self . high_qc_round ,
402+ }
403+ } else {
404+ HighExtendRank :: Tip {
405+ qc_round : self . high_qc_round ,
406+ tip_round : self . high_tip_round ,
407+ }
408+ }
409+ }
410+ }
411+
332412#[ derive( Clone , Debug , PartialEq , Eq , RlpEncodable , RlpDecodable , Serialize , Deserialize ) ]
333413#[ serde( bound(
334414 serialize = "SCT: SignatureCollection" ,
@@ -342,6 +422,21 @@ pub struct HighTipRoundSigColTuple<SCT> {
342422 pub sigs : SCT ,
343423}
344424
425+ impl < SCT > HighTipRoundSigColTuple < SCT > {
426+ pub fn rank ( & self ) -> HighExtendRank {
427+ if self . high_tip_round == GENESIS_ROUND {
428+ HighExtendRank :: Qc {
429+ qc_round : self . high_qc_round ,
430+ }
431+ } else {
432+ HighExtendRank :: Tip {
433+ qc_round : self . high_qc_round ,
434+ tip_round : self . high_tip_round ,
435+ }
436+ }
437+ }
438+ }
439+
345440/// TimeoutCertificate is used to advance rounds when a QC is unable to
346441/// form for a round
347442/// A collection of Timeout messages is the basis for building a TC
@@ -427,3 +522,67 @@ where
427522
428523 pub high_qc : QuorumCertificate < SCT > ,
429524}
525+
526+ #[ cfg( test) ]
527+ mod test {
528+ use std:: cmp:: Ordering ;
529+
530+ use monad_types:: Round ;
531+ use test_case:: test_case;
532+
533+ use crate :: timeout:: HighExtendRank ;
534+
535+ #[ test_case(
536+ HighExtendRank :: Qc { qc_round: Round ( 1 ) } ,
537+ HighExtendRank :: Qc { qc_round: Round ( 1 ) } ,
538+ Ordering :: Equal ;
539+ "qc equal"
540+ ) ]
541+ #[ test_case(
542+ HighExtendRank :: Qc { qc_round: Round ( 1 ) } ,
543+ HighExtendRank :: Qc { qc_round: Round ( 2 ) } ,
544+ Ordering :: Less ;
545+ "qc not equal"
546+ ) ]
547+ #[ test_case(
548+ HighExtendRank :: Tip { tip_round: Round ( 1 ) , qc_round: Round ( 0 ) } ,
549+ HighExtendRank :: Tip { tip_round: Round ( 1 ) , qc_round: Round ( 0 ) } ,
550+ Ordering :: Equal ;
551+ "tip equal"
552+ ) ]
553+ #[ test_case(
554+ HighExtendRank :: Tip { tip_round: Round ( 1 ) , qc_round: Round ( 0 ) } ,
555+ HighExtendRank :: Tip { tip_round: Round ( 2 ) , qc_round: Round ( 0 ) } ,
556+ Ordering :: Less ;
557+ "tip not equal 1"
558+ ) ]
559+ #[ test_case(
560+ HighExtendRank :: Tip { tip_round: Round ( 1 ) , qc_round: Round ( 0 ) } ,
561+ HighExtendRank :: Tip { tip_round: Round ( 2 ) , qc_round: Round ( 1 ) } ,
562+ Ordering :: Less ;
563+ "tip not equal 2"
564+ ) ]
565+ #[ test_case(
566+ HighExtendRank :: Tip { tip_round: Round ( 1 ) , qc_round: Round ( 0 ) } ,
567+ HighExtendRank :: Tip { tip_round: Round ( 1 ) , qc_round: Round ( 1 ) } ,
568+ Ordering :: Less ;
569+ "tip rounds equal, qc rounds not equal"
570+ ) ]
571+ #[ test_case(
572+ HighExtendRank :: Tip { tip_round: Round ( 1 ) , qc_round: Round ( 0 ) } ,
573+ HighExtendRank :: Qc { qc_round: Round ( 1 ) } ,
574+ Ordering :: Less ;
575+ "tip round equals qc round"
576+ ) ]
577+ #[ test_case(
578+ HighExtendRank :: Tip { tip_round: Round ( 2 ) , qc_round: Round ( 0 ) } ,
579+ HighExtendRank :: Qc { qc_round: Round ( 1 ) } ,
580+ Ordering :: Greater ;
581+ "tip round greater than qc round"
582+ ) ]
583+ fn high_extend_rank ( rank_1 : HighExtendRank , rank_2 : HighExtendRank , ord : Ordering ) {
584+ assert_eq ! ( rank_1. cmp( & rank_2) , ord) ;
585+ // test reverse
586+ assert_eq ! ( rank_2. cmp( & rank_1) , ord. reverse( ) ) ;
587+ }
588+ }
0 commit comments