-
Notifications
You must be signed in to change notification settings - Fork 156
/
Copy pathApplyTx.hs
193 lines (172 loc) · 5.65 KB
/
ApplyTx.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- | Benchmarks for transaction application
module Bench.Cardano.Ledger.ApplyTx (applyTxBenchmarks) where
import Cardano.Binary
import Cardano.Ledger.Allegra (AllegraEra)
import Cardano.Ledger.Alonzo (AlonzoEra)
import qualified Cardano.Ledger.Core as Core
import Cardano.Ledger.Era (Era, ValidateScript)
import Cardano.Ledger.Mary (MaryEra)
import Cardano.Ledger.Shelley (ShelleyEra)
import Cardano.Ledger.Shelley.API
( AccountState (..),
ApplyTx,
Coin (..),
Globals,
LedgerEnv (..),
MempoolEnv,
MempoolState,
Tx,
applyTxsTransition,
)
import Cardano.Ledger.Shelley.LedgerState (DPState, UTxOState)
import Cardano.Ledger.Slot (SlotNo (SlotNo))
import Control.DeepSeq (NFData (..))
import Criterion
import qualified Data.ByteString.Lazy as BSL
import Data.Default.Class (Default, def)
import Data.Proxy (Proxy (..))
import qualified Data.Sequence as Seq
import Data.Sharing (fromNotSharedCBOR)
import Data.Typeable (typeRep)
import GHC.Generics (Generic)
import Test.Cardano.Ledger.Shelley.ConcreteCryptoTypes (C_Crypto)
import Test.Cardano.Ledger.Shelley.Utils (testGlobals)
type ShelleyBench = ShelleyEra C_Crypto
type AllegraBench = AllegraEra C_Crypto
type MaryBench = MaryEra C_Crypto
type AlonzoBench = AlonzoEra C_Crypto
--------------------------------------------------------------------------------
-- Applying a Shelley transaction in multiple eras.
--
-- This benchmark starts with a fixed Shelley transaction. We decode it in the
-- correct transaction format for subsequent eras, and benchmark applying it to
-- a given ledger state (also translated for each era.)
--------------------------------------------------------------------------------
-- | Static mempool environment. We apply Txs in some future slot. The account
-- state shouldn't matter much.
applyTxMempoolEnv :: Default (Core.PParams era) => MempoolEnv era
applyTxMempoolEnv =
LedgerEnv
{ ledgerSlotNo = SlotNo 71,
ledgerIx = 0,
ledgerPp = def,
ledgerAccount = AccountState (Coin 45000000000) (Coin 45000000000)
}
data ApplyTxRes era = ApplyTxRes
{ atrGlobals :: Globals,
atrMempoolEnv :: MempoolEnv era,
atrState :: MempoolState era,
atrTx :: Core.Tx era
}
deriving (Generic)
instance NFData (ApplyTxRes era) where
rnf (ApplyTxRes g me s t) = seq g (seq me (seq s (seq t ())))
resource_n_ledgerstate :: Int -> FilePath
resource_n_ledgerstate n = "bench/resources/" <> show n <> "_ledgerstate.cbor"
resource_n_tx :: Int -> FilePath
resource_n_tx n = "bench/resources/" <> show n <> "_tx.cbor"
-- | Apply the transaction as if it's a transaction from a given era.
applyTxEra ::
forall era.
( Era era,
ApplyTx era,
Default (Core.PParams era),
FromCBOR (MempoolState era)
) =>
Proxy era ->
FilePath ->
FilePath ->
Benchmark
applyTxEra p lsFile txFile = env loadRes go
where
loadRes :: IO (ApplyTxRes era)
loadRes = do
state <-
either (\err -> error $ "Failed to decode state: " <> show err) id
. decodeFullDecoder "state" fromCBOR
<$> BSL.readFile lsFile
tx <-
either (\err -> error $ "Failed to decode tx: " <> show err) id
. decodeAnnotator "tx" fromCBOR
<$> BSL.readFile txFile
pure $! ApplyTxRes testGlobals applyTxMempoolEnv state tx
go :: ApplyTxRes era -> Benchmark
go ~ApplyTxRes {atrGlobals, atrMempoolEnv, atrState, atrTx} =
bench (show $ typeRep p) $
whnf
( either (error . show) id
. applyTxsTransition @era @(Either _)
atrGlobals
atrMempoolEnv
(Seq.singleton atrTx)
)
atrState
applyTxGroup :: Benchmark
applyTxGroup =
bgroup
"Apply Shelley Tx"
[ withRes 0,
withRes 1
]
where
withRes n =
let ls = resource_n_ledgerstate n
tx = resource_n_tx n
in bgroup
(show n)
[ applyTxEra (Proxy @ShelleyBench) ls tx,
applyTxEra (Proxy @AllegraBench) ls tx,
applyTxEra (Proxy @MaryBench) ls tx
]
-- | Benchmark deserialising a shelley transaction as if it comes from the given
-- era.
deserialiseTxEra ::
forall era.
( Era era,
ValidateScript era,
FromCBOR (Annotator (Core.TxBody era)),
FromCBOR (Annotator (Core.AuxiliaryData era)),
FromCBOR (Annotator (Core.Witnesses era))
) =>
Proxy era ->
Benchmark
deserialiseTxEra p =
bench (show $ typeRep p) $
whnfIO $
either (\err -> error $ "Failed to decode tx: " <> show err) (id @(Tx era))
. decodeAnnotator "tx" fromCBOR
<$> BSL.readFile (resource_n_tx 0)
applyTxBenchmarks :: Benchmark
applyTxBenchmarks =
bgroup
"applyTxBenchmarks"
[ applyTxGroup,
bgroup
"Deserialise Shelley Tx"
[ deserialiseTxEra (Proxy @ShelleyBench),
deserialiseTxEra (Proxy @AllegraBench),
deserialiseTxEra (Proxy @MaryBench),
deserialiseTxEra (Proxy @AlonzoBench)
]
]
instance FromCBOR (UTxOState ShelleyBench) where
fromCBOR = fromNotSharedCBOR
instance FromCBOR (UTxOState AllegraBench) where
fromCBOR = fromNotSharedCBOR
instance FromCBOR (UTxOState MaryBench) where
fromCBOR = fromNotSharedCBOR
instance FromCBOR (UTxOState AlonzoBench) where
fromCBOR = fromNotSharedCBOR
instance FromCBOR (DPState C_Crypto) where
fromCBOR = fromNotSharedCBOR