Skip to content

Commit 0bf0a07

Browse files
committed
Introduce the PerasCertDiffusion protocol (instance of ObjectDiffusion), and the associated smoke test
1 parent 60ba6ce commit 0bf0a07

File tree

5 files changed

+248
-0
lines changed

5 files changed

+248
-0
lines changed

ouroboros-consensus/ouroboros-consensus.cabal

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ library
185185
Ouroboros.Consensus.MiniProtocol.LocalTxSubmission.Server
186186
Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.Inbound
187187
Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.Outbound
188+
Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.PerasCert
188189
Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.ObjectPool.API
190+
Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.ObjectPool.PerasCert
189191
Ouroboros.Consensus.Node.GsmState
190192
Ouroboros.Consensus.Node.InitStorage
191193
Ouroboros.Consensus.Node.NetworkProtocolVersion
@@ -602,6 +604,7 @@ test-suite consensus-test
602604
Test.Consensus.MiniProtocol.ChainSync.Client
603605
Test.Consensus.MiniProtocol.LocalStateQuery.Server
604606
Test.Consensus.MiniProtocol.ObjectDiffusion.Smoke
607+
Test.Consensus.MiniProtocol.ObjectDiffusion.PerasCert.Smoke
605608
Test.Consensus.Util.MonadSTM.NormalForm
606609
Test.Consensus.Util.Versioned
607610

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
module Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.ObjectPool.PerasCert
2+
( makePerasCertPoolReaderFromCertDB
3+
, makePerasCertPoolWriterFromCertDB
4+
, makePerasCertPoolReaderFromChainDB
5+
, makePerasCertPoolWriterFromChainDB
6+
) where
7+
8+
import Data.Functor ((<&>))
9+
import Ouroboros.Consensus.Block
10+
import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.ObjectPool.API
11+
import Ouroboros.Consensus.Storage.ChainDB.API (ChainDB)
12+
import qualified Ouroboros.Consensus.Storage.ChainDB.API as ChainDB
13+
import Ouroboros.Consensus.Storage.PerasCertDB.API
14+
( PerasCertDB
15+
, PerasCertSnapshot
16+
, PerasCertTicketNo
17+
)
18+
import qualified Ouroboros.Consensus.Storage.PerasCertDB.API as PerasCertDB
19+
import Ouroboros.Consensus.Util.IOLike
20+
21+
makePerasCertPoolReader ::
22+
(IOLike m, StandardHash blk) =>
23+
STM m (PerasCertSnapshot blk) ->
24+
ObjectPoolReader PerasRoundNo (PerasCert blk) PerasCertTicketNo m
25+
makePerasCertPoolReader getCertSnapshot =
26+
ObjectPoolReader
27+
{ rdrGetObjectId = perasCertRound
28+
, objectPoolGetSnapshot =
29+
getCertSnapshot <&> \snap ->
30+
ObjectPoolSnapshot
31+
{ objectPoolObjectsAfter = \ticketNo ->
32+
[ (cert, tno, sz)
33+
| (cert, tno) <- PerasCertDB.getCertsAfter snap ticketNo
34+
, let sz = 0 -- TODO
35+
]
36+
, objectPoolHasObject = PerasCertDB.containsCert snap
37+
}
38+
, objectPoolZeroTicketNo = PerasCertDB.zeroPerasCertTicketNo
39+
}
40+
41+
makePerasCertPoolReaderFromCertDB ::
42+
(IOLike m, StandardHash blk) =>
43+
PerasCertDB m blk -> ObjectPoolReader PerasRoundNo (PerasCert blk) PerasCertTicketNo m
44+
makePerasCertPoolReaderFromCertDB perasCertDB =
45+
makePerasCertPoolReader (PerasCertDB.getCertSnapshot perasCertDB)
46+
47+
makePerasCertPoolWriterFromCertDB ::
48+
(StandardHash blk, Monad m) =>
49+
PerasCertDB m blk -> ObjectPoolWriter PerasRoundNo (PerasCert blk) m
50+
makePerasCertPoolWriterFromCertDB perasCertDB =
51+
ObjectPoolWriter
52+
{ wrGetObjectId = perasCertRound
53+
, objectPoolAddObjects =
54+
mapM_ $ PerasCertDB.addCert perasCertDB
55+
}
56+
57+
makePerasCertPoolReaderFromChainDB ::
58+
(IOLike m, StandardHash blk) =>
59+
ChainDB m blk -> ObjectPoolReader PerasRoundNo (PerasCert blk) PerasCertTicketNo m
60+
makePerasCertPoolReaderFromChainDB chainDB =
61+
makePerasCertPoolReader (ChainDB.getPerasCertSnapshot chainDB)
62+
63+
makePerasCertPoolWriterFromChainDB ::
64+
(StandardHash blk, Monad m) =>
65+
ChainDB m blk -> ObjectPoolWriter PerasRoundNo (PerasCert blk) m
66+
makePerasCertPoolWriterFromChainDB chainDB =
67+
ObjectPoolWriter
68+
{ wrGetObjectId = perasCertRound
69+
, objectPoolAddObjects =
70+
mapM_ $ ChainDB.addPerasCert chainDB
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
module Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.PerasCert
2+
( TracePerasCertDiffusionInbound
3+
, TracePerasCertDiffusionOutbound
4+
, PerasCertPoolReader
5+
, PerasCertPoolWriter
6+
, PerasCertDiffusionInboundPipelined
7+
, PerasCertDiffusionOutbound
8+
) where
9+
10+
import Ouroboros.Consensus.Block
11+
import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.Inbound
12+
import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.ObjectPool.API
13+
import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.Outbound
14+
import Ouroboros.Consensus.Storage.PerasCertDB.API
15+
import Ouroboros.Network.Protocol.ObjectDiffusion.Inbound (ObjectDiffusionInboundPipelined)
16+
import Ouroboros.Network.Protocol.ObjectDiffusion.Outbound (ObjectDiffusionOutbound)
17+
18+
-- This module defines type aliases for the ObjectDiffusion protocol applied to PerasCert diffusion.
19+
20+
type TracePerasCertDiffusionInbound blk = TraceObjectDiffusionInbound PerasRoundNo (PerasCert blk)
21+
type TracePerasCertDiffusionOutbound blk = TraceObjectDiffusionOutbound PerasRoundNo (PerasCert blk)
22+
23+
type PerasCertPoolReader blk m =
24+
ObjectPoolReader PerasRoundNo (PerasCert blk) PerasCertTicketNo m
25+
type PerasCertPoolWriter blk m =
26+
ObjectPoolWriter PerasRoundNo (PerasCert blk) m
27+
28+
type PerasCertDiffusionInboundPipelined blk m a =
29+
ObjectDiffusionInboundPipelined
30+
PerasRoundNo
31+
(PerasCert blk)
32+
m
33+
a
34+
type PerasCertDiffusionOutbound blk m a =
35+
ObjectDiffusionOutbound
36+
PerasRoundNo
37+
(PerasCert blk)
38+
m
39+
a

ouroboros-consensus/test/consensus-test/Main.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import qualified Test.Consensus.MiniProtocol.BlockFetch.Client (tests)
1616
import qualified Test.Consensus.MiniProtocol.ChainSync.CSJ (tests)
1717
import qualified Test.Consensus.MiniProtocol.ChainSync.Client (tests)
1818
import qualified Test.Consensus.MiniProtocol.LocalStateQuery.Server (tests)
19+
import qualified Test.Consensus.MiniProtocol.ObjectDiffusion.PerasCert.Smoke (tests)
1920
import qualified Test.Consensus.MiniProtocol.ObjectDiffusion.Smoke (tests)
2021
import qualified Test.Consensus.Util.MonadSTM.NormalForm (tests)
2122
import qualified Test.Consensus.Util.Versioned (tests)
@@ -38,6 +39,7 @@ tests =
3839
, Test.Consensus.MiniProtocol.ChainSync.CSJ.tests
3940
, Test.Consensus.MiniProtocol.ChainSync.Client.tests
4041
, Test.Consensus.MiniProtocol.ObjectDiffusion.Smoke.tests
42+
, Test.Consensus.MiniProtocol.ObjectDiffusion.PerasCert.Smoke.tests
4143
, Test.Consensus.MiniProtocol.LocalStateQuery.Server.tests
4244
, testGroup
4345
"Mempool"
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
{-# LANGUAGE FlexibleContexts #-}
2+
{-# LANGUAGE FlexibleInstances #-}
3+
{-# LANGUAGE MultiParamTypeClasses #-}
4+
{-# LANGUAGE NamedFieldPuns #-}
5+
{-# LANGUAGE RankNTypes #-}
6+
{-# LANGUAGE TypeApplications #-}
7+
{-# LANGUAGE UndecidableInstances #-}
8+
{-# OPTIONS_GHC -Wno-orphans #-}
9+
{-# OPTIONS_GHC -Wno-unused-top-binds #-}
10+
11+
module Test.Consensus.MiniProtocol.ObjectDiffusion.PerasCert.Smoke (tests) where
12+
13+
import Control.Monad.IOSim (IOSim)
14+
import Control.Tracer (Tracer (..), contramap, nullTracer)
15+
import Data.Functor.Identity (Identity (..))
16+
import qualified Data.List.NonEmpty as NE
17+
import Debug.Trace (traceM)
18+
import Network.TypedProtocol.Driver.Simple (runPeer, runPipelinedPeer)
19+
import Ouroboros.Consensus.Block.SupportsPeras
20+
import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.ObjectPool.API
21+
import Ouroboros.Consensus.MiniProtocol.ObjectDiffusion.ObjectPool.PerasCert
22+
import Ouroboros.Consensus.Storage.PerasCertDB.API
23+
( AddPerasCertResult (..)
24+
, PerasCertDB
25+
, PerasCertTicketNo
26+
)
27+
import qualified Ouroboros.Consensus.Storage.PerasCertDB.API as PerasCertDB
28+
import qualified Ouroboros.Consensus.Storage.PerasCertDB.Impl as PerasCertDB
29+
import Ouroboros.Consensus.Util.IOLike
30+
import Ouroboros.Network.Block (Point (..), SlotNo (SlotNo), StandardHash)
31+
import Ouroboros.Network.Point (Block (Block), WithOrigin (..))
32+
import Ouroboros.Network.Protocol.ObjectDiffusion.Codec
33+
import Ouroboros.Network.Protocol.ObjectDiffusion.Inbound
34+
( objectDiffusionInboundServerPeerPipelined
35+
)
36+
import Ouroboros.Network.Protocol.ObjectDiffusion.Outbound (objectDiffusionOutboundClientPeer)
37+
import Test.Consensus.MiniProtocol.ObjectDiffusion.Smoke
38+
( ListWithUniqueIds (..)
39+
, WithId
40+
, getId
41+
, prop_smoke_object_diffusion
42+
)
43+
import Test.QuickCheck
44+
import Test.Tasty
45+
import Test.Tasty.QuickCheck (testProperty)
46+
import Test.Util.TestBlock
47+
48+
-- When wanting to debug a part of the test:
49+
debugTracer :: Monad m => Tracer m String
50+
debugTracer = Tracer traceM
51+
52+
tests :: TestTree
53+
tests =
54+
testGroup
55+
"ObjectDiffusion.PerasCert.Smoke"
56+
[ testProperty "PerasCertDiffusion smoke test" prop_smoke
57+
]
58+
59+
instance Arbitrary (Point TestBlock) where
60+
arbitrary =
61+
-- Sometimes pick the genesis point
62+
frequency
63+
[ (1, pure $ Point Origin)
64+
,
65+
( 4
66+
, do
67+
slotNo <- SlotNo <$> arbitrary
68+
hash <- TestHash . NE.fromList . getNonEmpty <$> arbitrary
69+
pure $ Point (At (Block slotNo hash))
70+
)
71+
]
72+
73+
instance Arbitrary (Point blk) => Arbitrary (PerasCert blk) where
74+
arbitrary = do
75+
pcCertRound <- PerasRoundNo <$> arbitrary
76+
pcCertBoostedBlock <- arbitrary
77+
pure $ PerasCert{pcCertRound, pcCertBoostedBlock}
78+
79+
instance WithId (PerasCert blk) PerasRoundNo where
80+
getId = pcCertRound
81+
82+
newCertDB :: (IOLike m, StandardHash blk) => [PerasCert blk] -> m (PerasCertDB m blk)
83+
newCertDB certs = do
84+
db <- PerasCertDB.openDB (PerasCertDB.PerasCertDbArgs @Identity nullTracer)
85+
mapM_
86+
( \cert -> do
87+
result <- PerasCertDB.addCert db cert
88+
case result of
89+
AddedPerasCertToDB -> pure ()
90+
PerasCertAlreadyInDB -> throwIO (userError "Expected AddedPerasCertToDB, but cert was already in DB")
91+
)
92+
certs
93+
pure db
94+
95+
prop_smoke :: ListWithUniqueIds (PerasCert TestBlock) PerasRoundNo -> Property
96+
prop_smoke (ListWithUniqueIds certs) =
97+
prop_smoke_object_diffusion certs mkOutboundAsync mkInboundAsync mkPoolInterfaces
98+
where
99+
mkOutboundAsync outbound outboundChannel tracer =
100+
async $
101+
( ()
102+
<$ runPeer
103+
((\x -> "Outbound (Client): " ++ show x) `contramap` tracer)
104+
codecObjectDiffusionId
105+
outboundChannel
106+
(objectDiffusionOutboundClientPeer outbound)
107+
)
108+
mkInboundAsync inbound inboundChannel tracer =
109+
async $
110+
( ()
111+
<$ runPipelinedPeer
112+
((\x -> "Inbound (Server): " ++ show x) `contramap` tracer)
113+
codecObjectDiffusionId
114+
inboundChannel
115+
(objectDiffusionInboundServerPeerPipelined inbound)
116+
)
117+
mkPoolInterfaces ::
118+
forall s.
119+
IOSim
120+
s
121+
( ObjectPoolReader PerasRoundNo (PerasCert TestBlock) PerasCertTicketNo (IOSim s)
122+
, ObjectPoolReader PerasRoundNo (PerasCert TestBlock) PerasCertTicketNo (IOSim s)
123+
, ObjectPoolWriter PerasRoundNo (PerasCert TestBlock) (IOSim s)
124+
)
125+
mkPoolInterfaces = do
126+
outboundPool <- newCertDB certs
127+
inboundPool <- newCertDB []
128+
129+
let outboundPoolReader = makePerasCertPoolReaderFromCertDB outboundPool
130+
inboundPoolReader = makePerasCertPoolReaderFromCertDB inboundPool
131+
inboundPoolWriter = makePerasCertPoolWriterFromCertDB inboundPool
132+
133+
return (outboundPoolReader, inboundPoolReader, inboundPoolWriter)

0 commit comments

Comments
 (0)