/
Bootstrap.hs
278 lines (250 loc) · 7.51 KB
/
Bootstrap.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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Test.Cardano.Ledger.Shelley.Address.Bootstrap
( genBootstrapAddress,
testBootstrapSpending,
testBootstrapNotSpending,
bootstrapHashTest,
genSignature,
)
where
import Cardano.Binary (serialize')
import qualified Cardano.Chain.Common as Byron
import qualified Cardano.Crypto.DSIGN as DSIGN
import qualified Cardano.Crypto.Hash as Hash
import qualified Cardano.Crypto.Signing as Byron
import qualified Cardano.Crypto.Wallet as Byron
import Cardano.Ledger.Address
( Addr (..),
BootstrapAddress (..),
bootstrapKeyHash,
)
import Cardano.Ledger.BaseTypes
( Network (..),
StrictMaybe (..),
)
import Cardano.Ledger.Coin (Coin (..))
import Cardano.Ledger.Credential
( Credential (..),
StakeReference (..),
)
import Cardano.Ledger.Crypto (Crypto (..))
import Cardano.Ledger.Keys
( GenDelegs (..),
KeyRole (..),
VKey (..),
coerceKeyRole,
hashKey,
)
import Cardano.Ledger.SafeHash (extractHash, hashAnnotated)
import Cardano.Ledger.Shelley (ShelleyEra)
import Cardano.Ledger.Shelley.Address.Bootstrap
import Cardano.Ledger.Shelley.LedgerState
( PPUPState (..),
UTxOState (..),
)
import Cardano.Ledger.Shelley.PParams
( PParams' (..),
ProposedPPUpdates (..),
emptyPParams,
)
import Cardano.Ledger.Shelley.Rules.Utxo
( UtxoEnv (..),
)
import Cardano.Ledger.Shelley.Rules.Utxow
( UTXOW,
UtxowPredicateFailure (..),
)
import Cardano.Ledger.Shelley.Tx
( Tx (..),
WitnessSetHKD (..),
)
import Cardano.Ledger.Shelley.TxBody
( TxBody (..),
TxId (..),
TxIn (..),
TxOut (..),
Wdrl (..),
)
import Cardano.Ledger.Shelley.UTxO
( UTxO (..),
)
import Cardano.Ledger.Slot
( SlotNo (..),
)
import Cardano.Ledger.Val ((<->))
import Cardano.Prelude
( ByteString,
)
import qualified Data.Map as Map
import Data.Maybe (fromJust)
import qualified Data.Sequence.Strict as StrictSeq
import qualified Data.Set as Set
import qualified Test.Cardano.Chain.Common.Gen as Byron
import qualified Test.Cardano.Crypto.Gen as Byron
import qualified Test.Cardano.Ledger.Shelley.ConcreteCryptoTypes as Original
( C_Crypto,
)
import Test.Cardano.Ledger.Shelley.Generator.EraGen (genesisId)
import Test.Cardano.Ledger.Shelley.Generator.ShelleyEraGen ()
import Test.Cardano.Ledger.Shelley.Orphans ()
import Test.Cardano.Ledger.Shelley.Utils (testSTS)
import Test.Cardano.Prelude (genBytes)
import Test.QuickCheck (Gen)
import Test.QuickCheck.Hedgehog (hedgehog)
import Test.Tasty (TestTree)
import Test.Tasty.HUnit
( Assertion,
)
import Test.Tasty.QuickCheck (testProperty, (===))
bootstrapHashTest :: TestTree
bootstrapHashTest = testProperty "rebuild the 'addr root' using a bootstrap witness" $
do
(byronVKey, byronAddr) <- genByronVKeyAddr
sig <- genSignature
let addr = BootstrapAddress byronAddr
(shelleyVKey, chainCode) = unpackByronVKey @C_crypto byronVKey
witness :: BootstrapWitness C_crypto
witness =
BootstrapWitness
{ bwKey = shelleyVKey,
bwChainCode = chainCode,
bwSig = sig,
bwAttributes = serialize' $ Byron.addrAttributes byronAddr
}
pure $
(coerceKeyRole $ bootstrapKeyHash @C_crypto addr)
=== bootstrapWitKeyHash witness
genSignature :: forall a b. DSIGN.DSIGNAlgorithm a => Gen (DSIGN.SignedDSIGN a b)
genSignature =
DSIGN.SignedDSIGN
. fromJust
. DSIGN.rawDeserialiseSigDSIGN
<$> hedgehog (genBytes . fromIntegral $ DSIGN.sizeSigDSIGN ([] @a))
genBootstrapAddress :: Gen (BootstrapAddress crypto)
genBootstrapAddress = BootstrapAddress . snd <$> genByronVKeyAddr
genByronVKeyAddr :: Gen (Byron.VerificationKey, Byron.Address)
genByronVKeyAddr = do
vkey <- hedgehog Byron.genVerificationKey
addr <- genByronAddrFromVKey vkey
pure (vkey, addr)
genByronAddrFromVKey :: Byron.VerificationKey -> Gen Byron.Address
genByronAddrFromVKey vkey =
Byron.makeAddress (Byron.VerKeyASD vkey) <$> hedgehog Byron.genAddrAttributes
utxo0 :: UTxO C
utxo0 =
UTxO $
Map.singleton
(TxIn genesisId 0)
(TxOut aliceAddr aliceInitCoin)
utxoState0 :: UTxOState C
utxoState0 =
UTxOState
{ _utxo = utxo0,
_deposited = Coin 0,
_fees = Coin 0,
_ppups = PPUPState (ProposedPPUpdates mempty) (ProposedPPUpdates mempty)
}
tx :: Tx C
tx = Tx txBody mempty {bootWits = Set.fromList [aliceWitness]} SNothing
txBad :: Tx C
txBad = Tx txBody mempty {bootWits = Set.fromList [aliceBadWitness]} SNothing
utxoState1 :: UTxOState C
utxoState1 =
UTxOState
{ _utxo = UTxO $ Map.fromList [bobResult, aliceResult],
_deposited = Coin 0,
_fees = Coin 10,
_ppups = PPUPState (ProposedPPUpdates mempty) (ProposedPPUpdates mempty)
}
where
txid = TxId $ hashAnnotated txBody
bobResult = (TxIn txid 0, TxOut bobAddr coinsToBob)
aliceResult = (TxIn txid 1, TxOut aliceAddr (Coin 998990))
utxoEnv :: UtxoEnv C
utxoEnv =
UtxoEnv
0
emptyPParams {_maxTxSize = 1000}
mempty
(GenDelegs mempty)
aliceInitCoin :: Coin
aliceInitCoin = Coin 1000000
aliceSigningKey :: Byron.SigningKey
aliceSigningKey = Byron.SigningKey $ Byron.generate seed (mempty :: ByteString)
where
seed :: ByteString -- 32 bytes
seed = "12345678901234567890123456789012"
aliceVKey :: VKey 'Witness C_crypto
aliceVKey = fst . unpackByronVKey . Byron.toVerification $ aliceSigningKey
aliceByronAddr :: Byron.Address
aliceByronAddr = Byron.makeAddress asd attrs
where
asd = Byron.VerKeyASD $ byronVerificationKey
attrs =
Byron.AddrAttributes
(Just (Byron.HDAddressPayload "a compressed lenna.png"))
(Byron.NetworkTestnet 0)
byronVerificationKey = Byron.toVerification aliceSigningKey
aliceAddr :: Addr C_crypto
aliceAddr = AddrBootstrap (BootstrapAddress aliceByronAddr)
aliceWitness :: BootstrapWitness C_crypto
aliceWitness =
makeBootstrapWitness
(extractHash (hashAnnotated txBody))
aliceSigningKey
(Byron.addrAttributes aliceByronAddr)
aliceBadWitness :: BootstrapWitness C_crypto
aliceBadWitness =
makeBootstrapWitness
(extractHash (hashAnnotated txBody {_ttl = SlotNo 100000000}))
aliceSigningKey
(Byron.addrAttributes aliceByronAddr)
bobAddr :: Addr C_crypto
bobAddr = Addr Testnet (KeyHashObj k) StakeRefNull
where
k = coerceKeyRole $ hashKey aliceVKey
coinsToBob :: Coin
coinsToBob = Coin 1000
txBody :: TxBody C
txBody =
TxBody
{ _inputs = Set.fromList [TxIn genesisId 0],
_outputs = StrictSeq.fromList [TxOut bobAddr coinsToBob, TxOut aliceAddr change],
_certs = StrictSeq.fromList mempty,
_wdrls = Wdrl Map.empty,
_txfee = fee,
_ttl = SlotNo 10,
_txUpdate = SNothing,
_mdHash = SNothing
}
where
change = (aliceInitCoin <-> coinsToBob) <-> fee
fee = Coin 10
testBootstrapSpending :: Assertion
testBootstrapSpending =
testSTS @(UTXOW C)
utxoEnv
utxoState0
tx
(Right utxoState1)
testBootstrapNotSpending :: Assertion
testBootstrapNotSpending =
testSTS @(UTXOW C)
utxoEnv
utxoState0
txBad
(Left [InvalidWitnessesUTXOW [aliceVKey]])
type C = ShelleyEra C_crypto
data C_crypto
instance Cardano.Ledger.Crypto.Crypto C_crypto where
type KES C_crypto = KES Original.C_Crypto
type VRF C_crypto = VRF Original.C_Crypto
type DSIGN C_crypto = DSIGN.Ed25519DSIGN
type HASH C_crypto = HASH Original.C_Crypto
type ADDRHASH C_crypto = Hash.Blake2b_224