@@ -92,7 +92,7 @@ comparePraos ::
9292 -> Ordering
9393comparePraos tiebreakerFlavor =
9494 (compare `on` csvChainLength)
95- <> when' ( (==) `on` csvIssuer) (compare `on` csvIssueNo)
95+ <> when' issueNoArmed (compare `on` csvIssueNo)
9696 <> when' vrfArmed (compare `on` Down . csvTieBreakVRF)
9797 where
9898 -- When the predicate @p@ returns 'True', use the given comparison function,
@@ -104,6 +104,12 @@ comparePraos tiebreakerFlavor =
104104 when' p comp a1 a2 =
105105 if p a1 a2 then comp a1 a2 else EQ
106106
107+ -- Only compare the issue numbers when the issuers and slots are identical.
108+ -- Note that this case implies the VRFs also coincide.
109+ issueNoArmed v1 v2 =
110+ csvSlotNo v1 == csvSlotNo v2
111+ && csvIssuer v1 == csvIssuer v2
112+
107113 -- Whether to do a VRF comparison.
108114 vrfArmed v1 v2 = case tiebreakerFlavor of
109115 UnrestrictedVRFTiebreaker -> True
@@ -120,8 +126,9 @@ comparePraos tiebreakerFlavor =
120126--
121127-- 1. By chain length, with longer chains always preferred.
122128--
123- -- 2. If the tip of each chain was issued by the same agent, then we prefer
124- -- the chain whose tip has the highest ocert issue number.
129+ -- 2. If the tip of each chain was issued by the same agent and they have the
130+ -- same slot number, prefer the chain whose tip has the highest ocert issue
131+ -- number.
125132--
126133-- 3. By a VRF value from the chain tip, with lower values preferred. See
127134-- @pTieBreakVRFValue@ for which one is used.
@@ -142,8 +149,13 @@ instance Crypto c => Ord (PraosChainSelectView c) where
142149--
143150-- 1. Chain length, with longer chains always preferred.
144151--
145- -- 2. If the tip of each chain was issued by the same agent, then we prefer the
146- -- candidate if it has a higher ocert issue number.
152+ -- 2. If the tip of each chain was issued by the same agent and had the same
153+ -- slot number, then we prefer the candidate if it has a higher ocert issue
154+ -- number.
155+ --
156+ -- Note that this condition is equivalent to the VRFs being identical, as
157+ -- the VRF is a deterministic function of the issuer VRF key, the slot and
158+ -- the epoch nonce, and VRFs are collision-resistant.
147159--
148160-- 3. Depending on the 'VRFTiebreakerFlavor':
149161--
@@ -182,7 +194,8 @@ instance Crypto c => Ord (PraosChainSelectView c) where
182194-- block issuer can use their cold key to issue a new hot key with a higher
183195-- opcert issue number and set up a new pool. Due to this tiebreaker rule,
184196-- the blocks minted by that pool will take precedence (allowing the actual
185- -- block issuer to decide on eg the block contents and the predecessor), and
197+ -- block issuer to decide on eg the block contents and the predecessor) over
198+ -- blocks with the same block and slot number minted by the attacker, and
186199-- they will end up on the honest chain quickly, which means that the
187200-- adversary can't extend any chain containing such a block as it would
188201-- violate the monotonicity requirement on opcert issue numbers.
0 commit comments