{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TypeApplications #-}
#if __GLASGOW_HASKELL__ >= 908
{-# OPTIONS_GHC -Wno-x-partial #-}
#endif
module Test.Ouroboros.Consensus.ChainGenerator.Tests.Adversarial
( SomeTestAdversarial (..)
, TestAdversarial (..)
, tests
) where
import Control.Applicative ((<|>))
import qualified Control.Monad.Except as Exn
import Data.Functor ((<&>))
import Data.Functor.Identity (runIdentity)
import Data.IORef (modifyIORef', newIORef, readIORef, writeIORef)
import Data.Proxy (Proxy (Proxy))
import qualified System.Random as R
import qualified System.Timeout as IO (timeout)
import Test.Ouroboros.Consensus.ChainGenerator.Adversarial
( genPrefixBlockCount
)
import qualified Test.Ouroboros.Consensus.ChainGenerator.Adversarial as A
import qualified Test.Ouroboros.Consensus.ChainGenerator.BitVector as BV
import qualified Test.Ouroboros.Consensus.ChainGenerator.Counting as C
import qualified Test.Ouroboros.Consensus.ChainGenerator.Honest as H
import Test.Ouroboros.Consensus.ChainGenerator.Params
( Asc
, Delta (Delta)
, Kcp (Kcp)
, Len (Len)
, Scg (Scg)
, genAsc
)
import qualified Test.Ouroboros.Consensus.ChainGenerator.RaceIterator as RI
import Test.Ouroboros.Consensus.ChainGenerator.Slot (E (SlotE))
import qualified Test.Ouroboros.Consensus.ChainGenerator.Slot as S
import qualified Test.Ouroboros.Consensus.ChainGenerator.Some as Some
import qualified Test.Ouroboros.Consensus.ChainGenerator.Tests.Honest as H
import qualified Test.QuickCheck as QC
import Test.QuickCheck.Extras (unsafeMapSuchThatJust)
import Test.QuickCheck.Random (QCGen)
import qualified Test.Tasty as TT
import qualified Test.Tasty.QuickCheck as TT
import qualified Test.Util.QuickCheck as QC
tests :: [TT.TestTree]
tests :: [TestTree]
tests =
[ TestName -> (SomeTestAdversarial -> QCGen -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
TT.testProperty TestName
"k+1 blocks after the intersection" SomeTestAdversarial -> QCGen -> Property
prop_kPlus1BlocksAfterIntersection
, TestName -> (SomeTestAdversarial -> QCGen -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
TT.testProperty TestName
"Adversarial chains lose density and race comparisons" SomeTestAdversarial -> QCGen -> Property
prop_adversarialChain
, QuickCheckMaxSize -> TestTree -> TestTree
forall v. IsOption v => v -> TestTree -> TestTree
TT.localOption (Int -> QuickCheckMaxSize
TT.QuickCheckMaxSize Int
6) (TestTree -> TestTree) -> TestTree -> TestTree
forall a b. (a -> b) -> a -> b
$
TestName
-> (SomeTestAdversarialMutation -> QCGen -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
TT.testProperty
TestName
"Adversarial chains win if checked with relaxed parameters"
SomeTestAdversarialMutation -> QCGen -> Property
prop_adversarialChainMutation
]
data SomeTestAdversarial
= forall base hon.
SomeTestAdversarial
!(Proxy base)
!(Proxy hon)
!(TestAdversarial base hon)
instance Show SomeTestAdversarial where
showsPrec :: Int -> SomeTestAdversarial -> ShowS
showsPrec Int
p (SomeTestAdversarial Proxy base
base Proxy hon
hon TestAdversarial base hon
test) =
Int -> ShowBuilder SomeTestAdversarial -> ShowS
forall a.
NoFun "runShowsPrec" a (AbsError "runShowsPrec" a) =>
Int -> ShowBuilder a -> ShowS
Some.runShowsPrec Int
p (ShowBuilder SomeTestAdversarial -> ShowS)
-> ShowBuilder SomeTestAdversarial -> ShowS
forall a b. (a -> b) -> a -> b
$
(Proxy base
-> Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial)
-> TestName
-> ShowBuilder
(Proxy base
-> Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial)
forall a. a -> TestName -> ShowBuilder a
Some.showCtor Proxy base
-> Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial
forall base hon.
Proxy base
-> Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial
SomeTestAdversarial TestName
"SomeTestAdversarial"
ShowBuilder
(Proxy base
-> Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial)
-> Proxy base
-> ShowBuilder
(Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial)
forall a b. Show a => ShowBuilder (a -> b) -> a -> ShowBuilder b
`Some.showArg` Proxy base
base
ShowBuilder
(Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial)
-> Proxy hon
-> ShowBuilder (TestAdversarial base hon -> SomeTestAdversarial)
forall a b. Show a => ShowBuilder (a -> b) -> a -> ShowBuilder b
`Some.showArg` Proxy hon
hon
ShowBuilder (TestAdversarial base hon -> SomeTestAdversarial)
-> TestAdversarial base hon -> ShowBuilder SomeTestAdversarial
forall a b. Show a => ShowBuilder (a -> b) -> a -> ShowBuilder b
`Some.showArg` TestAdversarial base hon
test
instance Read SomeTestAdversarial where
readPrec :: ReadPrec SomeTestAdversarial
readPrec =
ReadBuilder SomeTestAdversarial -> ReadPrec SomeTestAdversarial
forall a.
NoFun "runReadPrec" a (AbsError "runReadPrec" a) =>
ReadBuilder a -> ReadPrec a
Some.runReadPrec (ReadBuilder SomeTestAdversarial -> ReadPrec SomeTestAdversarial)
-> ReadBuilder SomeTestAdversarial -> ReadPrec SomeTestAdversarial
forall a b. (a -> b) -> a -> b
$
(Proxy Any
-> Proxy Any -> TestAdversarial Any Any -> SomeTestAdversarial)
-> TestName
-> ReadBuilder
(Proxy Any
-> Proxy Any -> TestAdversarial Any Any -> SomeTestAdversarial)
forall a. a -> TestName -> ReadBuilder a
Some.readCtor Proxy Any
-> Proxy Any -> TestAdversarial Any Any -> SomeTestAdversarial
forall base hon.
Proxy base
-> Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial
SomeTestAdversarial TestName
"SomeTestAdversarial"
ReadBuilder
(Proxy Any
-> Proxy Any -> TestAdversarial Any Any -> SomeTestAdversarial)
-> ReadBuilder (Proxy Any)
-> ReadBuilder
(Proxy Any -> TestAdversarial Any Any -> SomeTestAdversarial)
forall a b. ReadBuilder (a -> b) -> ReadBuilder a -> ReadBuilder b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBuilder (Proxy Any)
forall a. Read a => ReadBuilder a
Some.readArg
ReadBuilder
(Proxy Any -> TestAdversarial Any Any -> SomeTestAdversarial)
-> ReadBuilder (Proxy Any)
-> ReadBuilder (TestAdversarial Any Any -> SomeTestAdversarial)
forall a b. ReadBuilder (a -> b) -> ReadBuilder a -> ReadBuilder b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBuilder (Proxy Any)
forall a. Read a => ReadBuilder a
Some.readArg
ReadBuilder (TestAdversarial Any Any -> SomeTestAdversarial)
-> ReadBuilder (TestAdversarial Any Any)
-> ReadBuilder SomeTestAdversarial
forall a b. ReadBuilder (a -> b) -> ReadBuilder a -> ReadBuilder b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBuilder (TestAdversarial Any Any)
forall a. Read a => ReadBuilder a
Some.readArg
data TestAdversarial base hon = TestAdversarial
{ forall base hon. TestAdversarial base hon -> Asc
testAscA :: !Asc
, forall base hon. TestAdversarial base hon -> Asc
testAscH :: !Asc
, forall base hon.
TestAdversarial base hon -> AdversarialRecipe base hon
testRecipeA :: !(A.AdversarialRecipe base hon)
, forall base hon.
TestAdversarial base hon -> SomeCheckedAdversarialRecipe base hon
testRecipeA' :: !(A.SomeCheckedAdversarialRecipe base hon)
, forall base hon. TestAdversarial base hon -> HonestRecipe
testRecipeH :: !H.HonestRecipe
, forall base hon.
TestAdversarial base hon -> CheckedHonestRecipe base hon
testRecipeH' :: !(H.CheckedHonestRecipe base hon)
, forall base hon. TestAdversarial base hon -> QCGen
testSeedH :: !QCGen
}
deriving (ReadPrec [TestAdversarial base hon]
ReadPrec (TestAdversarial base hon)
Int -> ReadS (TestAdversarial base hon)
ReadS [TestAdversarial base hon]
(Int -> ReadS (TestAdversarial base hon))
-> ReadS [TestAdversarial base hon]
-> ReadPrec (TestAdversarial base hon)
-> ReadPrec [TestAdversarial base hon]
-> Read (TestAdversarial base hon)
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
forall base hon. ReadPrec [TestAdversarial base hon]
forall base hon. ReadPrec (TestAdversarial base hon)
forall base hon. Int -> ReadS (TestAdversarial base hon)
forall base hon. ReadS [TestAdversarial base hon]
$creadsPrec :: forall base hon. Int -> ReadS (TestAdversarial base hon)
readsPrec :: Int -> ReadS (TestAdversarial base hon)
$creadList :: forall base hon. ReadS [TestAdversarial base hon]
readList :: ReadS [TestAdversarial base hon]
$creadPrec :: forall base hon. ReadPrec (TestAdversarial base hon)
readPrec :: ReadPrec (TestAdversarial base hon)
$creadListPrec :: forall base hon. ReadPrec [TestAdversarial base hon]
readListPrec :: ReadPrec [TestAdversarial base hon]
Read, Int -> TestAdversarial base hon -> ShowS
[TestAdversarial base hon] -> ShowS
TestAdversarial base hon -> TestName
(Int -> TestAdversarial base hon -> ShowS)
-> (TestAdversarial base hon -> TestName)
-> ([TestAdversarial base hon] -> ShowS)
-> Show (TestAdversarial base hon)
forall a.
(Int -> a -> ShowS) -> (a -> TestName) -> ([a] -> ShowS) -> Show a
forall base hon. Int -> TestAdversarial base hon -> ShowS
forall base hon. [TestAdversarial base hon] -> ShowS
forall base hon. TestAdversarial base hon -> TestName
$cshowsPrec :: forall base hon. Int -> TestAdversarial base hon -> ShowS
showsPrec :: Int -> TestAdversarial base hon -> ShowS
$cshow :: forall base hon. TestAdversarial base hon -> TestName
show :: TestAdversarial base hon -> TestName
$cshowList :: forall base hon. [TestAdversarial base hon] -> ShowS
showList :: [TestAdversarial base hon] -> ShowS
Show)
instance QC.Arbitrary SomeTestAdversarial where
arbitrary :: Gen SomeTestAdversarial
arbitrary = Gen (Maybe SomeTestAdversarial) -> Gen SomeTestAdversarial
forall a. Gen (Maybe a) -> Gen a
unsafeMapSuchThatJust (Gen (Maybe SomeTestAdversarial) -> Gen SomeTestAdversarial)
-> Gen (Maybe SomeTestAdversarial) -> Gen SomeTestAdversarial
forall a b. (a -> b) -> a -> b
$ do
H.TestHonest
{ H.testAsc = testAscH
, H.testRecipe = testRecipeH
, H.testRecipe' = someTestRecipeH'
} <-
Gen TestHonest
forall a. Arbitrary a => Gen a
QC.arbitrary
H.SomeCheckedHonestRecipe Proxy Proxy testRecipeH' <- pure someTestRecipeH'
testSeedH <- QC.arbitrary
let arHonest = Maybe Asc
-> CheckedHonestRecipe base hon -> QCGen -> ChainSchema base hon
forall base hon g.
RandomGen g =>
Maybe Asc
-> CheckedHonestRecipe base hon -> g -> ChainSchema base hon
H.uniformTheHonestChain (Asc -> Maybe Asc
forall a. a -> Maybe a
Just Asc
testAscH) CheckedHonestRecipe base hon
testRecipeH' QCGen
testSeedH
testSeedPrefix <- QC.arbitrary @QCGen
let arPrefix = HonestRecipe
-> QCGen -> ChainSchema base hon -> Var hon 'ActiveSlotE
forall g base hon.
RandomGen g =>
HonestRecipe -> g -> ChainSchema base hon -> Var hon 'ActiveSlotE
genPrefixBlockCount HonestRecipe
testRecipeH QCGen
testSeedPrefix ChainSchema base hon
arHonest
H.HonestRecipe kcp scg delta _len = testRecipeH
testRecipeA =
A.AdversarialRecipe
{ Var hon 'ActiveSlotE
arPrefix :: Var hon 'ActiveSlotE
arPrefix :: Var hon 'ActiveSlotE
A.arPrefix
, arParams :: (Kcp, Scg, Delta)
A.arParams = (Kcp
kcp, Scg
scg, Delta
delta)
, ChainSchema base hon
arHonest :: ChainSchema base hon
arHonest :: ChainSchema base hon
A.arHonest
}
testAscA <- genAsc
case Exn.runExcept $ A.checkAdversarialRecipe testRecipeA of
Left NoSuchAdversarialChainSchema
e -> case NoSuchAdversarialChainSchema
e of
NoSuchAdversarialChainSchema
A.NoSuchAdversarialBlock -> Maybe SomeTestAdversarial -> Gen (Maybe SomeTestAdversarial)
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe SomeTestAdversarial
forall a. Maybe a
Nothing
NoSuchAdversarialChainSchema
A.NoSuchCompetitor -> TestName -> Gen (Maybe SomeTestAdversarial)
forall a. HasCallStack => TestName -> a
error (TestName -> Gen (Maybe SomeTestAdversarial))
-> TestName -> Gen (Maybe SomeTestAdversarial)
forall a b. (a -> b) -> a -> b
$ TestName
"impossible! " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> NoSuchAdversarialChainSchema -> TestName
forall a. Show a => a -> TestName
show NoSuchAdversarialChainSchema
e
NoSuchAdversarialChainSchema
A.NoSuchIntersection -> TestName -> Gen (Maybe SomeTestAdversarial)
forall a. HasCallStack => TestName -> a
error (TestName -> Gen (Maybe SomeTestAdversarial))
-> TestName -> Gen (Maybe SomeTestAdversarial)
forall a b. (a -> b) -> a -> b
$ TestName
"impossible! " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> NoSuchAdversarialChainSchema -> TestName
forall a. Show a => a -> TestName
show NoSuchAdversarialChainSchema
e
Right SomeCheckedAdversarialRecipe base hon
testRecipeA' -> do
Maybe SomeTestAdversarial -> Gen (Maybe SomeTestAdversarial)
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe SomeTestAdversarial -> Gen (Maybe SomeTestAdversarial))
-> Maybe SomeTestAdversarial -> Gen (Maybe SomeTestAdversarial)
forall a b. (a -> b) -> a -> b
$
SomeTestAdversarial -> Maybe SomeTestAdversarial
forall a. a -> Maybe a
Just (SomeTestAdversarial -> Maybe SomeTestAdversarial)
-> SomeTestAdversarial -> Maybe SomeTestAdversarial
forall a b. (a -> b) -> a -> b
$
Proxy base
-> Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial
forall base hon.
Proxy base
-> Proxy hon -> TestAdversarial base hon -> SomeTestAdversarial
SomeTestAdversarial Proxy base
forall {k} (t :: k). Proxy t
Proxy Proxy hon
forall {k} (t :: k). Proxy t
Proxy (TestAdversarial base hon -> SomeTestAdversarial)
-> TestAdversarial base hon -> SomeTestAdversarial
forall a b. (a -> b) -> a -> b
$
TestAdversarial
{ Asc
testAscA :: Asc
testAscA :: Asc
testAscA
, Asc
testAscH :: Asc
testAscH :: Asc
testAscH
, AdversarialRecipe base hon
testRecipeA :: AdversarialRecipe base hon
testRecipeA :: AdversarialRecipe base hon
testRecipeA
, SomeCheckedAdversarialRecipe base hon
testRecipeA' :: SomeCheckedAdversarialRecipe base hon
testRecipeA' :: SomeCheckedAdversarialRecipe base hon
testRecipeA'
, HonestRecipe
testRecipeH :: HonestRecipe
testRecipeH :: HonestRecipe
testRecipeH
, CheckedHonestRecipe base hon
testRecipeH' :: CheckedHonestRecipe base hon
testRecipeH' :: CheckedHonestRecipe base hon
testRecipeH'
, QCGen
testSeedH :: QCGen
testSeedH :: QCGen
testSeedH
}
prop_kPlus1BlocksAfterIntersection :: SomeTestAdversarial -> QCGen -> QC.Property
prop_kPlus1BlocksAfterIntersection :: SomeTestAdversarial -> QCGen -> Property
prop_kPlus1BlocksAfterIntersection SomeTestAdversarial
someTestAdversarial QCGen
testSeedA = Identity Property -> Property
forall a. Identity a -> a
runIdentity (Identity Property -> Property) -> Identity Property -> Property
forall a b. (a -> b) -> a -> b
$ do
SomeTestAdversarial
Proxy
Proxy
TestAdversarial
{ testAscA
, testRecipeA
, testRecipeA'
} <-
SomeTestAdversarial -> Identity SomeTestAdversarial
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SomeTestAdversarial
someTestAdversarial
A.SomeCheckedAdversarialRecipe Proxy recipeA' <- pure testRecipeA'
let A.AdversarialRecipe{A.arHonest = schedH} = testRecipeA
schedA = Maybe Asc
-> CheckedAdversarialRecipe base hon adv
-> QCGen
-> ChainSchema base adv
forall g base hon adv.
RandomGen g =>
Maybe Asc
-> CheckedAdversarialRecipe base hon adv
-> g
-> ChainSchema base adv
A.uniformAdversarialChain (Asc -> Maybe Asc
forall a. a -> Maybe a
Just Asc
testAscA) CheckedAdversarialRecipe base hon adv
recipeA' QCGen
testSeedA
H.ChainSchema winA vA = schedA
H.ChainSchema _winH vH = schedH
A.AdversarialRecipe{A.arParams = (Kcp k, scg, _delta)} = testRecipeA
C.SomeWindow Proxy stabWin <- do
pure $ calculateStability scg schedA
pure
$ QC.counterexample
( unlines $
H.prettyChainSchema schedH "H"
++ H.prettyChainSchema schedA "A"
)
$ QC.counterexample ("arPrefix = " <> show (A.arPrefix testRecipeA))
$ QC.counterexample ("stabWin = " <> show stabWin)
$ QC.counterexample ("stabWin' = " <> show (C.joinWin winA stabWin))
$ QC.counterexample
("The honest chain should have k+1 blocks after the intersection")
( BV.countActivesInV S.notInverted vH
`QC.ge` C.toSize (C.Count (k + 1) + A.arPrefix testRecipeA)
)
QC..&&. QC.counterexample
("The alternative chain should have k+1 blocks after the intersection")
(BV.countActivesInV S.notInverted vA `QC.ge` C.Count (k + 1))
prop_adversarialChain :: SomeTestAdversarial -> QCGen -> QC.Property
prop_adversarialChain :: SomeTestAdversarial -> QCGen -> Property
prop_adversarialChain SomeTestAdversarial
someTestAdversarial QCGen
testSeedA = Identity Property -> Property
forall a. Identity a -> a
runIdentity (Identity Property -> Property) -> Identity Property -> Property
forall a b. (a -> b) -> a -> b
$ do
SomeTestAdversarial
Proxy
Proxy
TestAdversarial
{ testAscA
, testRecipeA
, testRecipeA'
} <-
SomeTestAdversarial -> Identity SomeTestAdversarial
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SomeTestAdversarial
someTestAdversarial
A.SomeCheckedAdversarialRecipe Proxy recipeA' <- pure testRecipeA'
let A.AdversarialRecipe{A.arHonest = schedH} = testRecipeA
schedA = Maybe Asc
-> CheckedAdversarialRecipe base hon adv
-> QCGen
-> ChainSchema base adv
forall g base hon adv.
RandomGen g =>
Maybe Asc
-> CheckedAdversarialRecipe base hon adv
-> g
-> ChainSchema base adv
A.uniformAdversarialChain (Asc -> Maybe Asc
forall a. a -> Maybe a
Just Asc
testAscA) CheckedAdversarialRecipe base hon adv
recipeA' QCGen
testSeedA
let H.ChainSchema winA _vA = schedA
C.SomeWindow Proxy stabWin <- do
let A.AdversarialRecipe{A.arParams = (_kcp, scg, _delta)} = testRecipeA
pure $ calculateStability scg schedA
pure $ case Exn.runExcept $ A.checkAdversarialChain testRecipeA schedA of
Right () -> () -> Property
forall prop. Testable prop => prop -> Property
QC.property ()
Left AdversarialViolation hon adv
e -> case AdversarialViolation hon adv
e of
A.BadAnchor{} -> TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (AdversarialViolation hon adv -> TestName
forall a. Show a => a -> TestName
show AdversarialViolation hon adv
e) Bool
False
A.BadCount{} -> TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (AdversarialViolation hon adv -> TestName
forall a. Show a => a -> TestName
show AdversarialViolation hon adv
e) Bool
False
A.BadDensity{} -> TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (AdversarialViolation hon adv -> TestName
forall a. Show a => a -> TestName
show AdversarialViolation hon adv
e) Bool
False
A.BadRace RaceViolation hon adv
rv -> case RaceViolation hon adv
rv of
A.AdversaryWonRace
{ rvAdv :: forall hon adv. RaceViolation hon adv -> Race adv
A.rvAdv = RI.Race (C.SomeWindow Proxy skolem
Proxy Contains 'SlotE adv (Win RaceLbl skolem)
rAdv)
, rvHon :: forall hon adv. RaceViolation hon adv -> Race hon
A.rvHon = RI.Race (C.SomeWindow Proxy skolem
Proxy Contains 'SlotE hon (Win RaceLbl skolem)
rHon)
} ->
Property -> Property
forall a. a -> a
id (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (ChainSchema base hon
-> ChainSchema base adv
-> Contains 'SlotE base adv
-> Contains 'SlotE adv (Win AdvStabLbl skolem)
-> RaceViolation hon adv
-> TestName
forall base hon adv stab.
ChainSchema base hon
-> ChainSchema base adv
-> Contains 'SlotE base adv
-> Contains 'SlotE adv stab
-> RaceViolation hon adv
-> TestName
advCounterexample ChainSchema base hon
schedH ChainSchema base adv
schedA Contains 'SlotE base adv
winA Contains 'SlotE adv (Win AdvStabLbl skolem)
stabWin RaceViolation hon adv
rv) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (TestName
"arPrefix = " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> Var hon 'ActiveSlotE -> TestName
forall a. Show a => a -> TestName
show (AdversarialRecipe base hon -> Var hon 'ActiveSlotE
forall base hon. AdversarialRecipe base hon -> Var hon 'ActiveSlotE
A.arPrefix AdversarialRecipe base hon
testRecipeA)) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (TestName
"rvAdv = " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> Contains 'SlotE adv (Win RaceLbl skolem) -> TestName
forall a. Show a => a -> TestName
show Contains 'SlotE adv (Win RaceLbl skolem)
rAdv) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (TestName
"rvAdv' = " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> Contains 'SlotE base (Win RaceLbl skolem) -> TestName
forall a. Show a => a -> TestName
show (Contains 'SlotE base adv
-> Contains 'SlotE adv (Win RaceLbl skolem)
-> Contains 'SlotE base (Win RaceLbl skolem)
forall {kelem} (elem :: kelem) outer mid inner.
Contains elem outer mid
-> Contains elem mid inner -> Contains elem outer inner
C.joinWin Contains 'SlotE base adv
winA Contains 'SlotE adv (Win RaceLbl skolem)
rAdv)) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (TestName
"rvHon = " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> Contains 'SlotE hon (Win RaceLbl skolem) -> TestName
forall a. Show a => a -> TestName
show Contains 'SlotE hon (Win RaceLbl skolem)
rHon) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (TestName
"stabWin = " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> Contains 'SlotE adv (Win AdvStabLbl skolem) -> TestName
forall a. Show a => a -> TestName
show Contains 'SlotE adv (Win AdvStabLbl skolem)
stabWin) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (TestName
"stabWin' = " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> Contains 'SlotE base (Win AdvStabLbl skolem) -> TestName
forall a. Show a => a -> TestName
show (Contains 'SlotE base adv
-> Contains 'SlotE adv (Win AdvStabLbl skolem)
-> Contains 'SlotE base (Win AdvStabLbl skolem)
forall {kelem} (elem :: kelem) outer mid inner.
Contains elem outer mid
-> Contains elem mid inner -> Contains elem outer inner
C.joinWin Contains 'SlotE base adv
winA Contains 'SlotE adv (Win AdvStabLbl skolem)
stabWin)) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (AdversarialViolation hon adv -> TestName
forall a. Show a => a -> TestName
show AdversarialViolation hon adv
e) (Bool -> Property) -> Bool -> Property
forall a b. (a -> b) -> a -> b
$
Bool
False
data AdvStabLbl
calculateStability :: Scg -> H.ChainSchema base adv -> C.SomeWindow AdvStabLbl adv SlotE
calculateStability :: forall base adv.
Scg -> ChainSchema base adv -> SomeWindow AdvStabLbl adv 'SlotE
calculateStability (Scg Int
s) ChainSchema base adv
schedA =
Size adv 'SlotE
-> Lbl AdvStabLbl
-> Index adv 'SlotE
-> Size Any 'SlotE
-> SomeWindow AdvStabLbl adv 'SlotE
forall {kelem} {klbl} outer (elem :: kelem) (lbl :: klbl) x.
Size outer elem
-> Lbl lbl
-> Index outer elem
-> Size x elem
-> SomeWindow lbl outer elem
C.withWindow
(Contains 'SlotE base adv -> Size adv 'SlotE
forall {kelem} (elem :: kelem) outer inner.
Contains elem outer inner -> Size inner elem
C.windowSize Contains 'SlotE base adv
winA)
(forall lbl. Lbl lbl
forall {k} (lbl :: k). Lbl lbl
C.Lbl @AdvStabLbl)
(Int -> Index adv 'SlotE
forall kelem kwhich base (elem :: kelem) (which :: kwhich).
Int -> Count base elem which
C.Count Int
0)
(Int -> Size Any 'SlotE
forall kelem kwhich base (elem :: kelem) (which :: kwhich).
Int -> Count base elem which
C.Count (Int -> Size Any 'SlotE) -> Int -> Size Any 'SlotE
forall a b. (a -> b) -> a -> b
$ Int
firstActive Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
theBlockItself Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
s)
where
H.ChainSchema Contains 'SlotE base adv
winA Vector adv 'SlotE S
vA = ChainSchema base adv
schedA
C.Count Int
firstActive = case Proxy 'Inverted
-> Vector adv 'SlotE S
-> Index adv (PreImage 'Inverted 'EmptySlotE)
-> MaybeFound adv
forall (pol :: Pol) (proxy :: Pol -> *) base.
POL pol =>
proxy pol
-> Vector base 'SlotE S
-> Index base (PreImage pol 'EmptySlotE)
-> MaybeFound base
BV.findIthEmptyInV Proxy 'Inverted
S.inverted Vector adv 'SlotE S
vA (Int -> Count adv 'ActiveSlotE Preds
forall kelem kwhich base (elem :: kelem) (which :: kwhich).
Int -> Count base elem which
C.Count Int
0) of
BV.JustFound Index adv 'SlotE
x -> Index adv 'SlotE
x
MaybeFound adv
BV.NothingFound -> TestName -> Index adv 'SlotE
forall a. HasCallStack => TestName -> a
error (TestName -> Index adv 'SlotE) -> TestName -> Index adv 'SlotE
forall a b. (a -> b) -> a -> b
$ TestName
"impossible! " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> [TestName] -> TestName
H.unlines' (ChainSchema base adv -> TestName -> [TestName]
forall base inner. ChainSchema base inner -> TestName -> [TestName]
H.prettyChainSchema ChainSchema base adv
schedA TestName
"A")
theBlockItself :: Int
theBlockItself = Int
1
advCounterexample ::
A.ChainSchema base hon ->
A.ChainSchema base adv ->
C.Contains 'SlotE base adv ->
C.Contains 'SlotE adv stab ->
A.RaceViolation hon adv ->
String
advCounterexample :: forall base hon adv stab.
ChainSchema base hon
-> ChainSchema base adv
-> Contains 'SlotE base adv
-> Contains 'SlotE adv stab
-> RaceViolation hon adv
-> TestName
advCounterexample ChainSchema base hon
schedH ChainSchema base adv
schedA Contains 'SlotE base adv
winA Contains 'SlotE adv stab
stabWin RaceViolation hon adv
rv =
case RaceViolation hon adv
rv of
A.AdversaryWonRace
{ rvAdv :: forall hon adv. RaceViolation hon adv -> Race adv
A.rvAdv = RI.Race (C.SomeWindow Proxy skolem
Proxy Contains 'SlotE adv (Win RaceLbl skolem)
rAdv)
, rvHon :: forall hon adv. RaceViolation hon adv -> Race hon
A.rvHon = RI.Race (C.SomeWindow Proxy skolem
Proxy Contains 'SlotE hon (Win RaceLbl skolem)
rHon)
} ->
[TestName] -> TestName
H.unlines' ([TestName] -> TestName) -> [TestName] -> TestName
forall a b. (a -> b) -> a -> b
$
[]
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [Contains 'SlotE hon (Win RaceLbl skolem) -> ShowS
forall base inner. Contains 'SlotE base inner -> ShowS
H.prettyWindow Contains 'SlotE hon (Win RaceLbl skolem)
rHon TestName
"rHon"]
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [TestName] -> [TestName]
forall a. [a] -> [a]
reverse (ChainSchema base hon -> TestName -> [TestName]
forall base inner. ChainSchema base inner -> TestName -> [TestName]
H.prettyChainSchema ChainSchema base hon
schedH TestName
"H")
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> ChainSchema base adv -> TestName -> [TestName]
forall base inner. ChainSchema base inner -> TestName -> [TestName]
H.prettyChainSchema ChainSchema base adv
schedA TestName
"A"
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [Contains 'SlotE base (Win RaceLbl skolem) -> ShowS
forall base inner. Contains 'SlotE base inner -> ShowS
H.prettyWindow (Contains 'SlotE base adv
-> Contains 'SlotE adv (Win RaceLbl skolem)
-> Contains 'SlotE base (Win RaceLbl skolem)
forall {kelem} (elem :: kelem) outer mid inner.
Contains elem outer mid
-> Contains elem mid inner -> Contains elem outer inner
C.joinWin Contains 'SlotE base adv
winA Contains 'SlotE adv (Win RaceLbl skolem)
rAdv) TestName
"rAdv'"]
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [Contains 'SlotE base stab -> ShowS
forall base inner. Contains 'SlotE base inner -> ShowS
H.prettyWindow (Contains 'SlotE base adv
-> Contains 'SlotE adv stab -> Contains 'SlotE base stab
forall {kelem} (elem :: kelem) outer mid inner.
Contains elem outer mid
-> Contains elem mid inner -> Contains elem outer inner
C.joinWin Contains 'SlotE base adv
winA Contains 'SlotE adv stab
stabWin) TestName
"stabWin'"]
data AdversarialMutation
=
AdversarialMutateDelta Int
|
AdversarialMutateKcp
deriving (AdversarialMutation -> AdversarialMutation -> Bool
(AdversarialMutation -> AdversarialMutation -> Bool)
-> (AdversarialMutation -> AdversarialMutation -> Bool)
-> Eq AdversarialMutation
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AdversarialMutation -> AdversarialMutation -> Bool
== :: AdversarialMutation -> AdversarialMutation -> Bool
$c/= :: AdversarialMutation -> AdversarialMutation -> Bool
/= :: AdversarialMutation -> AdversarialMutation -> Bool
Eq, ReadPrec [AdversarialMutation]
ReadPrec AdversarialMutation
Int -> ReadS AdversarialMutation
ReadS [AdversarialMutation]
(Int -> ReadS AdversarialMutation)
-> ReadS [AdversarialMutation]
-> ReadPrec AdversarialMutation
-> ReadPrec [AdversarialMutation]
-> Read AdversarialMutation
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS AdversarialMutation
readsPrec :: Int -> ReadS AdversarialMutation
$creadList :: ReadS [AdversarialMutation]
readList :: ReadS [AdversarialMutation]
$creadPrec :: ReadPrec AdversarialMutation
readPrec :: ReadPrec AdversarialMutation
$creadListPrec :: ReadPrec [AdversarialMutation]
readListPrec :: ReadPrec [AdversarialMutation]
Read, Int -> AdversarialMutation -> ShowS
[AdversarialMutation] -> ShowS
AdversarialMutation -> TestName
(Int -> AdversarialMutation -> ShowS)
-> (AdversarialMutation -> TestName)
-> ([AdversarialMutation] -> ShowS)
-> Show AdversarialMutation
forall a.
(Int -> a -> ShowS) -> (a -> TestName) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AdversarialMutation -> ShowS
showsPrec :: Int -> AdversarialMutation -> ShowS
$cshow :: AdversarialMutation -> TestName
show :: AdversarialMutation -> TestName
$cshowList :: [AdversarialMutation] -> ShowS
showList :: [AdversarialMutation] -> ShowS
Show)
data TestAdversarialMutation base hon
= TestAdversarialMutation
!H.HonestRecipe
!(H.CheckedHonestRecipe base hon)
!(A.AdversarialRecipe base hon)
!(A.SomeCheckedAdversarialRecipe base hon)
!AdversarialMutation
deriving (ReadPrec [TestAdversarialMutation base hon]
ReadPrec (TestAdversarialMutation base hon)
Int -> ReadS (TestAdversarialMutation base hon)
ReadS [TestAdversarialMutation base hon]
(Int -> ReadS (TestAdversarialMutation base hon))
-> ReadS [TestAdversarialMutation base hon]
-> ReadPrec (TestAdversarialMutation base hon)
-> ReadPrec [TestAdversarialMutation base hon]
-> Read (TestAdversarialMutation base hon)
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
forall base hon. ReadPrec [TestAdversarialMutation base hon]
forall base hon. ReadPrec (TestAdversarialMutation base hon)
forall base hon. Int -> ReadS (TestAdversarialMutation base hon)
forall base hon. ReadS [TestAdversarialMutation base hon]
$creadsPrec :: forall base hon. Int -> ReadS (TestAdversarialMutation base hon)
readsPrec :: Int -> ReadS (TestAdversarialMutation base hon)
$creadList :: forall base hon. ReadS [TestAdversarialMutation base hon]
readList :: ReadS [TestAdversarialMutation base hon]
$creadPrec :: forall base hon. ReadPrec (TestAdversarialMutation base hon)
readPrec :: ReadPrec (TestAdversarialMutation base hon)
$creadListPrec :: forall base hon. ReadPrec [TestAdversarialMutation base hon]
readListPrec :: ReadPrec [TestAdversarialMutation base hon]
Read, Int -> TestAdversarialMutation base hon -> ShowS
[TestAdversarialMutation base hon] -> ShowS
TestAdversarialMutation base hon -> TestName
(Int -> TestAdversarialMutation base hon -> ShowS)
-> (TestAdversarialMutation base hon -> TestName)
-> ([TestAdversarialMutation base hon] -> ShowS)
-> Show (TestAdversarialMutation base hon)
forall a.
(Int -> a -> ShowS) -> (a -> TestName) -> ([a] -> ShowS) -> Show a
forall base hon. Int -> TestAdversarialMutation base hon -> ShowS
forall base hon. [TestAdversarialMutation base hon] -> ShowS
forall base hon. TestAdversarialMutation base hon -> TestName
$cshowsPrec :: forall base hon. Int -> TestAdversarialMutation base hon -> ShowS
showsPrec :: Int -> TestAdversarialMutation base hon -> ShowS
$cshow :: forall base hon. TestAdversarialMutation base hon -> TestName
show :: TestAdversarialMutation base hon -> TestName
$cshowList :: forall base hon. [TestAdversarialMutation base hon] -> ShowS
showList :: [TestAdversarialMutation base hon] -> ShowS
Show)
data SomeTestAdversarialMutation
= forall base hon.
SomeTestAdversarialMutation
!(Proxy base)
!(Proxy hon)
!(TestAdversarialMutation base hon)
instance Show SomeTestAdversarialMutation where
showsPrec :: Int -> SomeTestAdversarialMutation -> ShowS
showsPrec Int
p (SomeTestAdversarialMutation Proxy base
base Proxy hon
hon TestAdversarialMutation base hon
testMut) =
Int -> ShowBuilder SomeTestAdversarialMutation -> ShowS
forall a.
NoFun "runShowsPrec" a (AbsError "runShowsPrec" a) =>
Int -> ShowBuilder a -> ShowS
Some.runShowsPrec Int
p (ShowBuilder SomeTestAdversarialMutation -> ShowS)
-> ShowBuilder SomeTestAdversarialMutation -> ShowS
forall a b. (a -> b) -> a -> b
$
(Proxy base
-> Proxy hon
-> TestAdversarialMutation base hon
-> SomeTestAdversarialMutation)
-> TestName
-> ShowBuilder
(Proxy base
-> Proxy hon
-> TestAdversarialMutation base hon
-> SomeTestAdversarialMutation)
forall a. a -> TestName -> ShowBuilder a
Some.showCtor Proxy base
-> Proxy hon
-> TestAdversarialMutation base hon
-> SomeTestAdversarialMutation
forall base hon.
Proxy base
-> Proxy hon
-> TestAdversarialMutation base hon
-> SomeTestAdversarialMutation
SomeTestAdversarialMutation TestName
"SomeTestAdversarialMutation"
ShowBuilder
(Proxy base
-> Proxy hon
-> TestAdversarialMutation base hon
-> SomeTestAdversarialMutation)
-> Proxy base
-> ShowBuilder
(Proxy hon
-> TestAdversarialMutation base hon -> SomeTestAdversarialMutation)
forall a b. Show a => ShowBuilder (a -> b) -> a -> ShowBuilder b
`Some.showArg` Proxy base
base
ShowBuilder
(Proxy hon
-> TestAdversarialMutation base hon -> SomeTestAdversarialMutation)
-> Proxy hon
-> ShowBuilder
(TestAdversarialMutation base hon -> SomeTestAdversarialMutation)
forall a b. Show a => ShowBuilder (a -> b) -> a -> ShowBuilder b
`Some.showArg` Proxy hon
hon
ShowBuilder
(TestAdversarialMutation base hon -> SomeTestAdversarialMutation)
-> TestAdversarialMutation base hon
-> ShowBuilder SomeTestAdversarialMutation
forall a b. Show a => ShowBuilder (a -> b) -> a -> ShowBuilder b
`Some.showArg` TestAdversarialMutation base hon
testMut
instance Read SomeTestAdversarialMutation where
readPrec :: ReadPrec SomeTestAdversarialMutation
readPrec =
ReadBuilder SomeTestAdversarialMutation
-> ReadPrec SomeTestAdversarialMutation
forall a.
NoFun "runReadPrec" a (AbsError "runReadPrec" a) =>
ReadBuilder a -> ReadPrec a
Some.runReadPrec (ReadBuilder SomeTestAdversarialMutation
-> ReadPrec SomeTestAdversarialMutation)
-> ReadBuilder SomeTestAdversarialMutation
-> ReadPrec SomeTestAdversarialMutation
forall a b. (a -> b) -> a -> b
$
(Proxy Any
-> Proxy Any
-> TestAdversarialMutation Any Any
-> SomeTestAdversarialMutation)
-> TestName
-> ReadBuilder
(Proxy Any
-> Proxy Any
-> TestAdversarialMutation Any Any
-> SomeTestAdversarialMutation)
forall a. a -> TestName -> ReadBuilder a
Some.readCtor Proxy Any
-> Proxy Any
-> TestAdversarialMutation Any Any
-> SomeTestAdversarialMutation
forall base hon.
Proxy base
-> Proxy hon
-> TestAdversarialMutation base hon
-> SomeTestAdversarialMutation
SomeTestAdversarialMutation TestName
"SomeTestAdversarialMutation"
ReadBuilder
(Proxy Any
-> Proxy Any
-> TestAdversarialMutation Any Any
-> SomeTestAdversarialMutation)
-> ReadBuilder (Proxy Any)
-> ReadBuilder
(Proxy Any
-> TestAdversarialMutation Any Any -> SomeTestAdversarialMutation)
forall a b. ReadBuilder (a -> b) -> ReadBuilder a -> ReadBuilder b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBuilder (Proxy Any)
forall a. Read a => ReadBuilder a
Some.readArg
ReadBuilder
(Proxy Any
-> TestAdversarialMutation Any Any -> SomeTestAdversarialMutation)
-> ReadBuilder (Proxy Any)
-> ReadBuilder
(TestAdversarialMutation Any Any -> SomeTestAdversarialMutation)
forall a b. ReadBuilder (a -> b) -> ReadBuilder a -> ReadBuilder b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBuilder (Proxy Any)
forall a. Read a => ReadBuilder a
Some.readArg
ReadBuilder
(TestAdversarialMutation Any Any -> SomeTestAdversarialMutation)
-> ReadBuilder (TestAdversarialMutation Any Any)
-> ReadBuilder SomeTestAdversarialMutation
forall a b. ReadBuilder (a -> b) -> ReadBuilder a -> ReadBuilder b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBuilder (TestAdversarialMutation Any Any)
forall a. Read a => ReadBuilder a
Some.readArg
mutateAdversarial ::
A.AdversarialRecipe base hon -> AdversarialMutation -> A.AdversarialRecipe base hon
mutateAdversarial :: forall base hon.
AdversarialRecipe base hon
-> AdversarialMutation -> AdversarialRecipe base hon
mutateAdversarial AdversarialRecipe base hon
recipe AdversarialMutation
mut =
A.AdversarialRecipe{ChainSchema base hon
arHonest :: ChainSchema base hon
arHonest :: ChainSchema base hon
A.arHonest, arParams :: (Kcp, Scg, Delta)
A.arParams = (Int -> Kcp
Kcp Int
k', Int -> Scg
Scg Int
s', Int -> Delta
Delta Int
d'), Var hon 'ActiveSlotE
arPrefix :: Var hon 'ActiveSlotE
arPrefix :: Var hon 'ActiveSlotE
A.arPrefix}
where
A.AdversarialRecipe{ChainSchema base hon
arHonest :: forall base hon. AdversarialRecipe base hon -> ChainSchema base hon
arHonest :: ChainSchema base hon
A.arHonest, arParams :: forall base hon. AdversarialRecipe base hon -> (Kcp, Scg, Delta)
A.arParams = (Kcp Int
k, Scg Int
s, Delta Int
d), Var hon 'ActiveSlotE
arPrefix :: forall base hon. AdversarialRecipe base hon -> Var hon 'ActiveSlotE
arPrefix :: Var hon 'ActiveSlotE
A.arPrefix} = AdversarialRecipe base hon
recipe
(Int
k', Int
s', Int
d') = case AdversarialMutation
mut of
AdversarialMutateDelta Int
dInc -> (Int
k, Int
s, Int
d Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dInc)
AdversarialMutation
AdversarialMutateKcp -> (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1, Int
s, Int
d)
instance QC.Arbitrary SomeTestAdversarialMutation where
arbitrary :: Gen SomeTestAdversarialMutation
arbitrary = do
Gen (Maybe SomeTestAdversarialMutation)
-> Gen SomeTestAdversarialMutation
forall a. Gen (Maybe a) -> Gen a
unsafeMapSuchThatJust (Gen (Maybe SomeTestAdversarialMutation)
-> Gen SomeTestAdversarialMutation)
-> Gen (Maybe SomeTestAdversarialMutation)
-> Gen SomeTestAdversarialMutation
forall a b. (a -> b) -> a -> b
$ do
recipeH@(H.HonestRecipe kcp scg delta len) <- Gen HonestRecipe
H.genHonestRecipe
someTestRecipeH' <- case Exn.runExcept $ H.checkHonestRecipe recipeH of
Left NoSuchHonestChainSchema
e -> TestName -> Gen SomeCheckedHonestRecipe
forall a. HasCallStack => TestName -> a
error (TestName -> Gen SomeCheckedHonestRecipe)
-> TestName -> Gen SomeCheckedHonestRecipe
forall a b. (a -> b) -> a -> b
$ TestName
"impossible! " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> (HonestRecipe, NoSuchHonestChainSchema) -> TestName
forall a. Show a => a -> TestName
show (HonestRecipe
recipeH, NoSuchHonestChainSchema
e)
Right SomeCheckedHonestRecipe
x -> SomeCheckedHonestRecipe -> Gen SomeCheckedHonestRecipe
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SomeCheckedHonestRecipe
x
H.SomeCheckedHonestRecipe Proxy Proxy recipeH' <- pure someTestRecipeH'
seedH <- QC.arbitrary @QCGen
let arHonest = Maybe Asc
-> CheckedHonestRecipe base hon -> QCGen -> ChainSchema base hon
forall base hon g.
RandomGen g =>
Maybe Asc
-> CheckedHonestRecipe base hon -> g -> ChainSchema base hon
H.uniformTheHonestChain Maybe Asc
forall a. Maybe a
Nothing CheckedHonestRecipe base hon
recipeH' QCGen
seedH
testSeedPrefix <- QC.arbitrary @QCGen
let arPrefix = HonestRecipe
-> QCGen -> ChainSchema base hon -> Var hon 'ActiveSlotE
forall g base hon.
RandomGen g =>
HonestRecipe -> g -> ChainSchema base hon -> Var hon 'ActiveSlotE
genPrefixBlockCount HonestRecipe
recipeH QCGen
testSeedPrefix ChainSchema base hon
arHonest
let recipeA =
A.AdversarialRecipe
{ Var hon 'ActiveSlotE
arPrefix :: Var hon 'ActiveSlotE
arPrefix :: Var hon 'ActiveSlotE
A.arPrefix
, arParams :: (Kcp, Scg, Delta)
A.arParams = (Kcp
kcp, Scg
scg, Delta
delta)
, ChainSchema base hon
arHonest :: ChainSchema base hon
arHonest :: ChainSchema base hon
A.arHonest
}
case Exn.runExcept $ A.checkAdversarialRecipe recipeA of
Left NoSuchAdversarialChainSchema
e -> Maybe SomeTestAdversarialMutation
-> Gen (Maybe SomeTestAdversarialMutation)
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe SomeTestAdversarialMutation
-> Gen (Maybe SomeTestAdversarialMutation))
-> Maybe SomeTestAdversarialMutation
-> Gen (Maybe SomeTestAdversarialMutation)
forall a b. (a -> b) -> a -> b
$ case NoSuchAdversarialChainSchema
e of
NoSuchAdversarialChainSchema
A.NoSuchAdversarialBlock -> Maybe SomeTestAdversarialMutation
forall a. Maybe a
Nothing
NoSuchAdversarialChainSchema
A.NoSuchCompetitor -> TestName -> Maybe SomeTestAdversarialMutation
forall a. HasCallStack => TestName -> a
error (TestName -> Maybe SomeTestAdversarialMutation)
-> TestName -> Maybe SomeTestAdversarialMutation
forall a b. (a -> b) -> a -> b
$ TestName
"impossible! " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> NoSuchAdversarialChainSchema -> TestName
forall a. Show a => a -> TestName
show NoSuchAdversarialChainSchema
e
NoSuchAdversarialChainSchema
A.NoSuchIntersection -> TestName -> Maybe SomeTestAdversarialMutation
forall a. HasCallStack => TestName -> a
error (TestName -> Maybe SomeTestAdversarialMutation)
-> TestName -> Maybe SomeTestAdversarialMutation
forall a b. (a -> b) -> a -> b
$ TestName
"impossible! " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> NoSuchAdversarialChainSchema -> TestName
forall a. Show a => a -> TestName
show NoSuchAdversarialChainSchema
e
Right SomeCheckedAdversarialRecipe base hon
recipeA' -> do
let dInc :: Int
dInc = SomeCheckedAdversarialRecipe base hon -> Int
forall {base} {hon}. SomeCheckedAdversarialRecipe base hon -> Int
deltaIncrementFromRecipe SomeCheckedAdversarialRecipe base hon
recipeA'
mut <- [AdversarialMutation] -> Gen AdversarialMutation
forall a. HasCallStack => [a] -> Gen a
QC.elements [AdversarialMutation
AdversarialMutateKcp, Int -> AdversarialMutation
AdversarialMutateDelta Int
dInc]
pure $ case Exn.runExcept $ A.checkAdversarialRecipe $ mutateAdversarial recipeA mut of
Left{} -> Maybe SomeTestAdversarialMutation
forall a. Maybe a
Nothing
Right (A.SomeCheckedAdversarialRecipe Proxy adv
Proxy CheckedAdversarialRecipe base hon adv
mutRecipeA)
| let A.UnsafeCheckedAdversarialRecipe
{ carParams :: forall base hon adv.
CheckedAdversarialRecipe base hon adv -> (Kcp, Scg, Delta)
A.carParams = (Kcp Int
k', Scg
_scg', Delta
_delta')
, Contains 'SlotE hon adv
carWin :: Contains 'SlotE hon adv
carWin :: forall base hon adv.
CheckedAdversarialRecipe base hon adv -> Contains 'SlotE hon adv
A.carWin
} = CheckedAdversarialRecipe base hon adv
mutRecipeA
, Count adv 'SlotE Total -> Int
forall {kelem} {kwhich} base (elem :: kelem) (which :: kwhich).
Count base elem which -> Int
C.getCount (Contains 'SlotE hon adv -> Count adv 'SlotE Total
forall {kelem} (elem :: kelem) outer inner.
Contains elem outer inner -> Size inner elem
C.windowSize Contains 'SlotE hon adv
carWin) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
k' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 ->
Maybe SomeTestAdversarialMutation
forall a. Maybe a
Nothing
| let H.ChainSchema Contains 'SlotE base hon
_winH Vector hon 'SlotE S
vH = ChainSchema base hon
arHonest
, let Len Int
l = Len
len
, let (Kcp Int
k', Scg
_scg', Delta Int
d') = CheckedAdversarialRecipe base hon adv -> (Kcp, Scg, Delta)
forall base hon adv.
CheckedAdversarialRecipe base hon adv -> (Kcp, Scg, Delta)
A.carParams CheckedAdversarialRecipe base hon adv
mutRecipeA
,
Int
endOfFirstRace <- case Proxy 'Inverted
-> Vector hon 'SlotE S
-> Index hon (PreImage 'Inverted 'EmptySlotE)
-> MaybeFound hon
forall (pol :: Pol) (proxy :: Pol -> *) base.
POL pol =>
proxy pol
-> Vector base 'SlotE S
-> Index base (PreImage pol 'EmptySlotE)
-> MaybeFound base
BV.findIthEmptyInV Proxy 'Inverted
S.inverted Vector hon 'SlotE S
vH (Var hon 'ActiveSlotE -> Index hon 'ActiveSlotE
forall {kelem} base (elem :: kelem).
Var base elem -> Index base elem
C.toIndex Var hon 'ActiveSlotE
arPrefix Index hon 'ActiveSlotE -> Int -> Index hon 'ActiveSlotE
forall {kelem} {kwhich} base (elem :: kelem) (which :: kwhich).
Count base elem which -> Int -> Count base elem which
C.+ Int
k') of
BV.NothingFound{} -> Int
l
BV.JustFound Index hon 'SlotE
x -> Index hon 'SlotE -> Int
forall {kelem} {kwhich} base (elem :: kelem) (which :: kwhich).
Count base elem which -> Int
C.getCount Index hon 'SlotE
x Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
d'
, Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
endOfFirstRace ->
Maybe SomeTestAdversarialMutation
forall a. Maybe a
Nothing
| Bool
otherwise ->
SomeTestAdversarialMutation -> Maybe SomeTestAdversarialMutation
forall a. a -> Maybe a
Just (SomeTestAdversarialMutation -> Maybe SomeTestAdversarialMutation)
-> SomeTestAdversarialMutation -> Maybe SomeTestAdversarialMutation
forall a b. (a -> b) -> a -> b
$
Proxy base
-> Proxy hon
-> TestAdversarialMutation base hon
-> SomeTestAdversarialMutation
forall base hon.
Proxy base
-> Proxy hon
-> TestAdversarialMutation base hon
-> SomeTestAdversarialMutation
SomeTestAdversarialMutation Proxy base
forall {k} (t :: k). Proxy t
Proxy Proxy hon
forall {k} (t :: k). Proxy t
Proxy (TestAdversarialMutation base hon -> SomeTestAdversarialMutation)
-> TestAdversarialMutation base hon -> SomeTestAdversarialMutation
forall a b. (a -> b) -> a -> b
$
HonestRecipe
-> CheckedHonestRecipe base hon
-> AdversarialRecipe base hon
-> SomeCheckedAdversarialRecipe base hon
-> AdversarialMutation
-> TestAdversarialMutation base hon
forall base hon.
HonestRecipe
-> CheckedHonestRecipe base hon
-> AdversarialRecipe base hon
-> SomeCheckedAdversarialRecipe base hon
-> AdversarialMutation
-> TestAdversarialMutation base hon
TestAdversarialMutation
HonestRecipe
recipeH
CheckedHonestRecipe base hon
recipeH'
AdversarialRecipe base hon
recipeA
SomeCheckedAdversarialRecipe base hon
recipeA'
AdversarialMutation
mut
where
deltaIncrementFromRecipe :: SomeCheckedAdversarialRecipe base hon -> Int
deltaIncrementFromRecipe (A.SomeCheckedAdversarialRecipe Proxy adv
_ CheckedAdversarialRecipe base hon adv
r) =
let H.ChainSchema Contains 'SlotE base hon
_ Vector hon 'SlotE S
v = CheckedAdversarialRecipe base hon adv -> ChainSchema base hon
forall base hon adv.
CheckedAdversarialRecipe base hon adv -> ChainSchema base hon
A.carHonest CheckedAdversarialRecipe base hon adv
r
sv :: Vector adv 'SlotE S
sv = Contains 'SlotE hon adv
-> Vector hon 'SlotE S -> Vector adv 'SlotE S
forall {k} a (elem :: k) outer inner.
Unbox a =>
Contains elem outer inner
-> Vector outer elem a -> Vector inner elem a
C.sliceV (CheckedAdversarialRecipe base hon adv -> Contains 'SlotE hon adv
forall base hon adv.
CheckedAdversarialRecipe base hon adv -> Contains 'SlotE hon adv
A.carWin CheckedAdversarialRecipe base hon adv
r) Vector hon 'SlotE S
v
(Kcp Int
k, Scg Int
s, Delta
_) = CheckedAdversarialRecipe base hon adv -> (Kcp, Scg, Delta)
forall base hon adv.
CheckedAdversarialRecipe base hon adv -> (Kcp, Scg, Delta)
A.carParams CheckedAdversarialRecipe base hon adv
r
kPlus1st :: Int
kPlus1st = case Proxy 'Inverted
-> Vector adv 'SlotE S
-> Index adv (PreImage 'Inverted 'EmptySlotE)
-> MaybeFound adv
forall (pol :: Pol) (proxy :: Pol -> *) base.
POL pol =>
proxy pol
-> Vector base 'SlotE S
-> Index base (PreImage pol 'EmptySlotE)
-> MaybeFound base
BV.findIthEmptyInV Proxy 'Inverted
S.inverted Vector adv 'SlotE S
sv (Int -> Count adv 'ActiveSlotE Preds
forall kelem kwhich base (elem :: kelem) (which :: kwhich).
Int -> Count base elem which
C.Count Int
k) of
MaybeFound adv
BV.NothingFound -> Int
1
BV.JustFound Index adv 'SlotE
i -> Index adv 'SlotE -> Int
forall {kelem} {kwhich} base (elem :: kelem) (which :: kwhich).
Count base elem which -> Int
C.getCount Index adv 'SlotE
i
in case Proxy 'Inverted
-> Vector adv 'SlotE S
-> Index adv (PreImage 'Inverted 'EmptySlotE)
-> MaybeFound adv
forall (pol :: Pol) (proxy :: Pol -> *) base.
POL pol =>
proxy pol
-> Vector base 'SlotE S
-> Index base (PreImage pol 'EmptySlotE)
-> MaybeFound base
BV.findIthEmptyInV Proxy 'Inverted
S.inverted Vector adv 'SlotE S
sv (Int -> Count adv 'ActiveSlotE Preds
forall kelem kwhich base (elem :: kelem) (which :: kwhich).
Int -> Count base elem which
C.Count (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)) of
BV.JustFound Index adv 'SlotE
i | Index adv 'SlotE -> Int
forall {kelem} {kwhich} base (elem :: kelem) (which :: kwhich).
Count base elem which -> Int
C.getCount Index adv 'SlotE
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
s -> Int
1
MaybeFound adv
_ -> Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
kPlus1st
prop_adversarialChainMutation :: SomeTestAdversarialMutation -> QCGen -> QC.Property
prop_adversarialChainMutation :: SomeTestAdversarialMutation -> QCGen -> Property
prop_adversarialChainMutation (SomeTestAdversarialMutation Proxy base
Proxy Proxy hon
Proxy TestAdversarialMutation base hon
testAdversarialMut) QCGen
testSeedAsSeed0 =
TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
TT.counterexample TestName
flakyTestCopy (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
IO Property -> Property
forall prop. Testable prop => IO prop -> Property
QC.ioProperty (IO Property -> Property) -> IO Property -> Property
forall a b. (a -> b) -> a -> b
$ do
A.SomeCheckedAdversarialRecipe Proxy recipeA' <- SomeCheckedAdversarialRecipe base hon
-> IO (SomeCheckedAdversarialRecipe base hon)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure SomeCheckedAdversarialRecipe base hon
someRecipeA'
counter <- newIORef @Int 0
catch <- newIORef @(QCGen, [String]) (undefined, [])
IO.timeout
(20 * 10 ^ (6 :: Int))
(go catch counter recipeA' testSeedAsSeed0)
>>= \case
Just Property
prop -> Property -> IO Property
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Property
prop
Maybe Property
Nothing ->
((,) ((QCGen, [TestName]) -> Int -> ((QCGen, [TestName]), Int))
-> IO (QCGen, [TestName]) -> IO (Int -> ((QCGen, [TestName]), Int))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef (QCGen, [TestName]) -> IO (QCGen, [TestName])
forall a. IORef a -> IO a
readIORef IORef (QCGen, [TestName])
catch IO (Int -> ((QCGen, [TestName]), Int))
-> IO Int -> IO ((QCGen, [TestName]), Int)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef IORef Int
counter) IO ((QCGen, [TestName]), Int)
-> (((QCGen, [TestName]), Int) -> Property) -> IO Property
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \((QCGen
seedA, [TestName]
schedA'), Int
n) ->
Property -> Property
forall a. a -> a
id
(Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample (TestName
"n = " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> TestName
forall a. Show a => a -> TestName
show Int
n)
(Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
QC.counterexample
(TestAdversarialMutation base hon
-> AdversarialRecipe base hon -> [TestName] -> QCGen -> TestName
forall base hon.
TestAdversarialMutation base hon
-> AdversarialRecipe base hon -> [TestName] -> QCGen -> TestName
advMutCounterexample TestAdversarialMutation base hon
testAdversarialMut AdversarialRecipe base hon
mutatedRecipe [TestName]
schedA' QCGen
seedA)
(Bool -> Property) -> Bool -> Property
forall a b. (a -> b) -> a -> b
$ Bool
False
where
TestAdversarialMutation HonestRecipe
recipeH CheckedHonestRecipe base hon
_recipeH' AdversarialRecipe base hon
recipeA SomeCheckedAdversarialRecipe base hon
someRecipeA' AdversarialMutation
mut = TestAdversarialMutation base hon
testAdversarialMut
H.HonestRecipe Kcp
_kcp Scg
scg Delta
_delta Len
_len = HonestRecipe
recipeH
mutatedRecipe :: AdversarialRecipe base hon
mutatedRecipe = AdversarialRecipe base hon
-> AdversarialMutation -> AdversarialRecipe base hon
forall base hon.
AdversarialRecipe base hon
-> AdversarialMutation -> AdversarialRecipe base hon
mutateAdversarial AdversarialRecipe base hon
recipeA AdversarialMutation
mut
go :: IORef (QCGen, [TestName])
-> IORef a
-> CheckedAdversarialRecipe base hon inner
-> QCGen
-> IO Property
go IORef (QCGen, [TestName])
catch IORef a
counter CheckedAdversarialRecipe base hon inner
recipeA' QCGen
testSeedAsSeed = do
IORef a -> (a -> a) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef a
counter (a -> a -> a
forall a. Num a => a -> a -> a
+ a
1)
let
(QCGen
testSeedA, QCGen
testSeedAsSeed') = QCGen -> (QCGen, QCGen)
forall g. RandomGen g => g -> (g, g)
R.split QCGen
testSeedAsSeed
schedA :: ChainSchema base inner
schedA = Maybe Asc
-> CheckedAdversarialRecipe base hon inner
-> QCGen
-> ChainSchema base inner
forall g base hon adv.
RandomGen g =>
Maybe Asc
-> CheckedAdversarialRecipe base hon adv
-> g
-> ChainSchema base adv
A.uniformAdversarialChain Maybe Asc
forall a. Maybe a
Nothing CheckedAdversarialRecipe base hon inner
recipeA' (QCGen
testSeedA :: QCGen)
m :: Except (AdversarialViolation hon inner) ()
m = AdversarialRecipe base hon
-> ChainSchema base inner
-> Except (AdversarialViolation hon inner) ()
forall base hon adv.
AdversarialRecipe base hon
-> ChainSchema base adv -> Except (AdversarialViolation hon adv) ()
A.checkAdversarialChain AdversarialRecipe base hon
mutatedRecipe ChainSchema base inner
schedA
case Except (AdversarialViolation hon inner) ()
-> Either (AdversarialViolation hon inner) ()
forall e a. Except e a -> Either e a
Exn.runExcept Except (AdversarialViolation hon inner) ()
m of
Right () -> do
let A.UnsafeCheckedAdversarialRecipe{Contains 'SlotE hon inner
carWin :: forall base hon adv.
CheckedAdversarialRecipe base hon adv -> Contains 'SlotE hon adv
carWin :: Contains 'SlotE hon inner
A.carWin} = CheckedAdversarialRecipe base hon inner
recipeA'
pretty :: [TestName]
pretty = case Scg -> ChainSchema base inner -> SomeWindow AdvStabLbl inner 'SlotE
forall base adv.
Scg -> ChainSchema base adv -> SomeWindow AdvStabLbl adv 'SlotE
calculateStability Scg
scg ChainSchema base inner
schedA of
C.SomeWindow Proxy skolem
Proxy Contains 'SlotE inner (Win AdvStabLbl skolem)
win ->
[Contains 'SlotE hon (Win AdvStabLbl skolem) -> ShowS
forall base inner. Contains 'SlotE base inner -> ShowS
H.prettyWindow (Contains 'SlotE hon inner
-> Contains 'SlotE inner (Win AdvStabLbl skolem)
-> Contains 'SlotE hon (Win AdvStabLbl skolem)
forall {kelem} (elem :: kelem) outer mid inner.
Contains elem outer mid
-> Contains elem mid inner -> Contains elem outer inner
C.joinWin Contains 'SlotE hon inner
carWin Contains 'SlotE inner (Win AdvStabLbl skolem)
win) TestName
"no accel"]
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [Size inner 'ActiveSlotE -> TestName
forall a. Show a => a -> TestName
show (ChainSchema base inner -> Size inner 'ActiveSlotE
forall base inner.
ChainSchema base inner -> Size inner 'ActiveSlotE
H.countChainSchema ChainSchema base inner
schedA)]
IORef (QCGen, [TestName]) -> (QCGen, [TestName]) -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (QCGen, [TestName])
catch (QCGen
testSeedA, ChainSchema base inner -> TestName -> [TestName]
forall base inner. ChainSchema base inner -> TestName -> [TestName]
H.prettyChainSchema ChainSchema base inner
schedA TestName
"A" [TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [TestName]
pretty)
IORef (QCGen, [TestName])
-> IORef a
-> CheckedAdversarialRecipe base hon inner
-> QCGen
-> IO Property
go IORef (QCGen, [TestName])
catch IORef a
counter CheckedAdversarialRecipe base hon inner
recipeA' QCGen
testSeedAsSeed'
Left AdversarialViolation hon inner
e -> case AdversarialViolation hon inner
e of
A.BadAnchor{} -> TestName -> IO Property
forall a. HasCallStack => TestName -> a
error (TestName -> IO Property) -> TestName -> IO Property
forall a b. (a -> b) -> a -> b
$ TestName
"impossible! " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> AdversarialViolation hon inner -> TestName
forall a. Show a => a -> TestName
show AdversarialViolation hon inner
e
A.BadCount{} -> TestName -> IO Property
forall a. HasCallStack => TestName -> a
error (TestName -> IO Property) -> TestName -> IO Property
forall a b. (a -> b) -> a -> b
$ TestName
"impossible! " TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> AdversarialViolation hon inner -> TestName
forall a. Show a => a -> TestName
show AdversarialViolation hon inner
e
A.BadDensity{} -> Property -> IO Property
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Property -> IO Property) -> Property -> IO Property
forall a b. (a -> b) -> a -> b
$ () -> Property
forall prop. Testable prop => prop -> Property
QC.property ()
A.BadRace{} -> Property -> IO Property
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Property -> IO Property) -> Property -> IO Property
forall a b. (a -> b) -> a -> b
$ () -> Property
forall prop. Testable prop => prop -> Property
QC.property ()
flakyTestCopy :: TestName
flakyTestCopy =
TestName
"This test may be flaky, and its failure may not be indicative of an actual problem: see https://github.com/IntersectMBO/ouroboros-consensus/issues/1442"
advMutCounterexample ::
TestAdversarialMutation base hon ->
A.AdversarialRecipe base hon ->
[String] ->
QCGen ->
String
advMutCounterexample :: forall base hon.
TestAdversarialMutation base hon
-> AdversarialRecipe base hon -> [TestName] -> QCGen -> TestName
advMutCounterexample TestAdversarialMutation base hon
testAdversarialMut AdversarialRecipe base hon
mutatedRecipe [TestName]
schedA' QCGen
seedA =
[TestName] -> TestName
H.unlines' ([TestName] -> TestName) -> [TestName] -> TestName
forall a b. (a -> b) -> a -> b
$
[]
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [QCGen -> TestName
forall a. Show a => a -> TestName
show QCGen
seedA]
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [ Size hon 'ActiveSlotE -> TestName
forall a. Show a => a -> TestName
show Size hon 'ActiveSlotE
ch
TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> TestName
" - "
TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> Var hon 'ActiveSlotE -> TestName
forall a. Show a => a -> TestName
show Var hon 'ActiveSlotE
arPrefix
TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> TestName
" = "
TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> Var hon 'ActiveSlotE -> TestName
forall a. Show a => a -> TestName
show (Size hon 'ActiveSlotE -> Var hon 'ActiveSlotE
forall {kelem} {kwhich} base (elem :: kelem) (which :: kwhich).
Count base elem which -> Var base elem
C.toVar Size hon 'ActiveSlotE
ch Var hon 'ActiveSlotE
-> Var hon 'ActiveSlotE -> Var hon 'ActiveSlotE
forall a. Num a => a -> a -> a
- Var hon 'ActiveSlotE
arPrefix)
TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> TestName
" vs "
TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> (Kcp, AdversarialMutation) -> TestName
forall a. Show a => a -> TestName
show (Kcp
kcp, AdversarialMutation
mut)
]
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [TestName]
schedH'
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> [TestName]
schedA'
[TestName] -> [TestName] -> [TestName]
forall a. Semigroup a => a -> a -> a
<> Maybe (Bool, Race hon) -> [TestName]
go' (((,) Bool
False (Race hon -> (Bool, Race hon))
-> Maybe (Race hon) -> Maybe (Bool, Race hon)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Kcp -> Vector hon 'SlotE S -> Maybe (Race hon)
forall base. Kcp -> Vector base 'SlotE S -> Maybe (Race base)
RI.init Kcp
kcp' Vector hon 'SlotE S
vH) Maybe (Bool, Race hon)
-> Maybe (Bool, Race hon) -> Maybe (Bool, Race hon)
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Bool, Race hon) -> Maybe (Bool, Race hon)
forall a. a -> Maybe a
Just (Bool
True, Vector hon 'SlotE S -> Race hon
forall base. Vector base 'SlotE S -> Race base
RI.initConservative Vector hon 'SlotE S
vH))
where
TestAdversarialMutation HonestRecipe
recipeH CheckedHonestRecipe base hon
_recipeH' AdversarialRecipe base hon
recipeA SomeCheckedAdversarialRecipe base hon
someRecipeA' AdversarialMutation
mut = TestAdversarialMutation base hon
testAdversarialMut
H.HonestRecipe Kcp
kcp Scg
_scg Delta
_delta Len
_len = HonestRecipe
recipeH
A.AdversarialRecipe{ChainSchema base hon
arHonest :: forall base hon. AdversarialRecipe base hon -> ChainSchema base hon
arHonest :: ChainSchema base hon
A.arHonest, Var hon 'ActiveSlotE
arPrefix :: forall base hon. AdversarialRecipe base hon -> Var hon 'ActiveSlotE
arPrefix :: Var hon 'ActiveSlotE
A.arPrefix} = AdversarialRecipe base hon
recipeA
H.ChainSchema Contains 'SlotE base hon
_winH Vector hon 'SlotE S
vH = ChainSchema base hon
arHonest
A.AdversarialRecipe{arParams :: forall base hon. AdversarialRecipe base hon -> (Kcp, Scg, Delta)
A.arParams = (Kcp
kcp', Scg
_scg', Delta
_delta')} = AdversarialRecipe base hon
mutatedRecipe
schedH' :: [TestName]
schedH' = ChainSchema base hon -> TestName -> [TestName]
forall base inner. ChainSchema base inner -> TestName -> [TestName]
H.prettyChainSchema ChainSchema base hon
arHonest TestName
"H"
ch :: Size hon 'ActiveSlotE
ch = ChainSchema base hon -> Size hon 'ActiveSlotE
forall base inner.
ChainSchema base inner -> Size inner 'ActiveSlotE
H.countChainSchema ChainSchema base hon
arHonest
next :: Race hon -> Maybe (Bool, Race hon)
next Race hon
iter =
((,) Bool
False (Race hon -> (Bool, Race hon))
-> Maybe (Race hon) -> Maybe (Bool, Race hon)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector hon 'SlotE S -> Race hon -> Maybe (Race hon)
forall base. Vector base 'SlotE S -> Race base -> Maybe (Race base)
RI.next Vector hon 'SlotE S
vH Race hon
iter)
Maybe (Bool, Race hon)
-> Maybe (Bool, Race hon) -> Maybe (Bool, Race hon)
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ((,) Bool
True (Race hon -> (Bool, Race hon))
-> Maybe (Race hon) -> Maybe (Bool, Race hon)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector hon 'SlotE S -> Race hon -> Maybe (Race hon)
forall base. Vector base 'SlotE S -> Race base -> Maybe (Race base)
RI.nextConservative Vector hon 'SlotE S
vH Race hon
iter)
go' :: Maybe (Bool, Race hon) -> [TestName]
go' = \case
Maybe (Bool, Race hon)
Nothing -> []
Just (Bool
cons, iter :: Race hon
iter@(RI.Race (C.SomeWindow Proxy skolem
Proxy Contains 'SlotE hon (Win RaceLbl skolem)
win)))
| A.SomeCheckedAdversarialRecipe Proxy adv
Proxy CheckedAdversarialRecipe base hon adv
recipeA' <- SomeCheckedAdversarialRecipe base hon
someRecipeA'
, A.UnsafeCheckedAdversarialRecipe{Contains 'SlotE hon adv
carWin :: forall base hon adv.
CheckedAdversarialRecipe base hon adv -> Contains 'SlotE hon adv
carWin :: Contains 'SlotE hon adv
A.carWin} <- CheckedAdversarialRecipe base hon adv
recipeA'
, Contains 'SlotE hon (Win RaceLbl skolem) -> Index hon 'SlotE
forall {kelem} (elem :: kelem) outer inner.
Contains elem outer inner -> Index outer elem
C.windowStart Contains 'SlotE hon (Win RaceLbl skolem)
win Index hon 'SlotE -> Index hon 'SlotE -> Bool
forall a. Ord a => a -> a -> Bool
< Contains 'SlotE hon adv -> Index hon 'SlotE
forall {kelem} (elem :: kelem) outer inner.
Contains elem outer inner -> Index outer elem
C.windowStart Contains 'SlotE hon adv
carWin ->
Maybe (Bool, Race hon) -> [TestName]
go' (Race hon -> Maybe (Bool, Race hon)
next Race hon
iter)
| Bool
otherwise ->
TestName
""
TestName -> [TestName] -> [TestName]
forall a. a -> [a] -> [a]
: [TestName] -> TestName
forall a. HasCallStack => [a] -> a
head ([TestName] -> [TestName]
forall a. HasCallStack => [a] -> [a]
tail [TestName]
schedH')
TestName -> [TestName] -> [TestName]
forall a. a -> [a] -> [a]
: Contains 'SlotE hon (Win RaceLbl skolem) -> ShowS
forall base inner. Contains 'SlotE base inner -> ShowS
H.prettyWindow Contains 'SlotE hon (Win RaceLbl skolem)
win (TestName
"raceH" TestName -> ShowS
forall a. Semigroup a => a -> a -> a
<> if Bool
cons then TestName
" (conservative)" else TestName
"")
TestName -> [TestName] -> [TestName]
forall a. a -> [a] -> [a]
: Int -> [TestName] -> [TestName]
forall a. Int -> [a] -> [a]
take Int
2 ([TestName] -> [TestName]
forall a. HasCallStack => [a] -> [a]
tail [TestName]
schedA')