-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow to customize
preferCandidate
(#1063)
Closes #939 The core idea is to keep a total order (via `Ord`) for `SelectView`, but allowing to customize the logic of `preferCandidate` (previously, it was always defined in terms of `Ord`, i.e. `preferCandidate ours cand = cand > ours`), such that it becomes possible to eg implement the restricted VRF tiebreaker (#524) this way, which is fundamentally intransitive. This is in contrast to #1046 (an alternative to this PR), where `preferCandidate` is not customizable, and we instead live with the fact the ordering might not be transitive, which techically would require replacing our calls to `sortBy` with eg a topological sorting algorithm, or just assume/test that `sortBy` still works "well enough" with non-transitive orders. Also see #1047 as a follow-up PR that leverages the new flexibility offered by this PR. This PR undoes some of the changes of IntersectMBO/ouroboros-network#2743 and IntersectMBO/ouroboros-network#2732 which were back then merged to increase simplicity/ease of exposition in the report, but it now turns out that the flexibility they removed is actually useful for us today.
- Loading branch information
Showing
26 changed files
with
528 additions
and
132 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
...tocol/changelog.d/20240417_122550_alexander.esgen_customize_prefer_candidate.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
### Non-Breaking | ||
|
||
- Adapted to introduction of new `ChainOrder` type class. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module Main (main) where | ||
|
||
import qualified Test.Consensus.Protocol.Praos.SelectView | ||
import Test.Tasty | ||
import Test.Util.TestEnv | ||
|
||
main :: IO () | ||
main = defaultMainWithTestEnv defaultTestEnvConfig tests | ||
|
||
tests :: TestTree | ||
tests = | ||
testGroup "protocol" | ||
[ Test.Consensus.Protocol.Praos.SelectView.tests | ||
] |
91 changes: 91 additions & 0 deletions
91
ouroboros-consensus-protocol/test/protocol-test/Test/Consensus/Protocol/Praos/SelectView.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
{-# LANGUAGE DataKinds #-} | ||
{-# LANGUAGE FlexibleInstances #-} | ||
{-# LANGUAGE LambdaCase #-} | ||
{-# LANGUAGE NamedFieldPuns #-} | ||
{-# LANGUAGE ScopedTypeVariables #-} | ||
{-# LANGUAGE TypeApplications #-} | ||
|
||
{-# OPTIONS_GHC -Wno-orphans #-} | ||
|
||
module Test.Consensus.Protocol.Praos.SelectView (tests) where | ||
|
||
import qualified Cardano.Crypto.Hash as Crypto | ||
import qualified Cardano.Crypto.Util as Crypto | ||
import Cardano.Crypto.VRF (OutputVRF, mkTestOutputVRF) | ||
import Cardano.Ledger.Crypto (Crypto (..), StandardCrypto) | ||
import qualified Cardano.Ledger.Keys as SL | ||
import Codec.Serialise (encode) | ||
import Control.Monad | ||
import Data.Containers.ListUtils (nubOrdOn) | ||
import Ouroboros.Consensus.Block | ||
import Ouroboros.Consensus.Protocol.Praos.Common | ||
import Test.Cardano.Ledger.Binary.Arbitrary () | ||
import Test.Ouroboros.Consensus.Protocol | ||
import Test.QuickCheck.Gen (Gen (..)) | ||
import Test.QuickCheck.Random (mkQCGen) | ||
import Test.Tasty | ||
import Test.Tasty.QuickCheck hiding (elements) | ||
import Test.Util.QuickCheck | ||
import Test.Util.TestEnv | ||
|
||
tests :: TestTree | ||
tests = testGroup "PraosChainSelectView" | ||
[ adjustQuickCheckTests (* 50) | ||
-- Use a small max size by default in order to have a decent chance to | ||
-- trigger the actual tiebreaker cases. | ||
$ adjustQuickCheckMaxSize (`div` 10) | ||
$ tests_chainOrder (Proxy @(PraosChainSelectView StandardCrypto)) | ||
] | ||
|
||
instance Crypto c => Arbitrary (PraosChainSelectView c) where | ||
arbitrary = do | ||
size <- fromIntegral <$> getSize | ||
csvChainLength <- BlockNo <$> choose (1, size) | ||
csvSlotNo <- SlotNo <$> choose (1, size) | ||
csvIssuer <- elements knownIssuers | ||
csvIssueNo <- genIssueNo | ||
pure PraosChainSelectView { | ||
csvChainLength | ||
, csvSlotNo | ||
, csvIssuer | ||
, csvIssueNo | ||
, csvTieBreakVRF = mkVRFFor csvIssuer csvSlotNo | ||
} | ||
where | ||
-- We want to draw from the same small set of issuer identities in order to | ||
-- have a chance to explore cases where the issuers of two 'SelectView's | ||
-- are identical. | ||
knownIssuers :: [SL.VKey SL.BlockIssuer c] | ||
knownIssuers = | ||
nubOrdOn SL.hashKey | ||
$ unGen (replicateM numIssuers (SL.VKey <$> arbitrary)) randomSeed 100 | ||
where | ||
randomSeed = mkQCGen 4 -- chosen by fair dice roll | ||
numIssuers = 10 | ||
|
||
-- TODO Actually randomize this once the issue number tiebreaker has been | ||
-- fixed to be transitive. See the document in | ||
-- https://github.com/IntersectMBO/ouroboros-consensus/pull/891 for | ||
-- details. | ||
-- | ||
-- TL;DR: In an edge case, the issue number tiebreaker prevents the | ||
-- chain order from being transitive. This could be fixed relatively | ||
-- easily, namely by swapping the issue number tiebreaker and the VRF | ||
-- tiebreaker. However, this is technically not backwards-compatible, | ||
-- impacting the current pre-Conway diffusion pipelining scheme. | ||
-- | ||
-- See https://github.com/IntersectMBO/ouroboros-consensus/issues/1075. | ||
genIssueNo = pure 1 | ||
|
||
-- The header VRF is a deterministic function of the issuer VRF key, the | ||
-- slot and the epoch nonce. Additionally, for any particular chain, the | ||
-- slot determines the epoch nonce. | ||
mkVRFFor :: SL.VKey SL.BlockIssuer c -> SlotNo -> OutputVRF (VRF c) | ||
mkVRFFor issuer slot = | ||
mkTestOutputVRF | ||
$ Crypto.bytesToNatural | ||
$ Crypto.hashToBytes | ||
$ Crypto.xor (Crypto.castHash issuerHash) | ||
$ Crypto.hashWithSerialiser encode slot | ||
where | ||
SL.KeyHash issuerHash = SL.hashKey issuer |
5 changes: 5 additions & 0 deletions
5
...ensus/changelog.d/20240417_122327_alexander.esgen_customize_prefer_candidate.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
### Breaking | ||
|
||
- Introduced new `ChainOrder` (with `preferCandidate`) class for `SelectView`s, | ||
and add necessary instances. Adapted `preferAnchoredCandidate` to use | ||
`preferCandidate` instead of relying on `preferAnchoredFragment`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.