-
Notifications
You must be signed in to change notification settings - Fork 730
/
Copy pathByron.hs
301 lines (240 loc) · 11.5 KB
/
Byron.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
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
-- | Byron key types and their 'Key' class instances
--
module Cardano.Api.Keys.Byron (
-- * Key types
ByronKey,
ByronKeyLegacy,
-- * Data family instances
AsType(..),
VerificationKey(..),
SigningKey(..),
Hash(..),
-- * Legacy format
IsByronKey(..),
ByronKeyFormat(..),
SomeByronSigningKey(..),
toByronSigningKey
) where
import qualified Cardano.Prelude as CBOR (toCborError)
import qualified Codec.CBOR.Decoding as CBOR
import qualified Codec.CBOR.Read as CBOR
import Control.Monad
import Data.Bifunctor
import qualified Data.ByteString.Lazy as LB
import Data.Coders (cborError)
import Data.Either.Combinators
import Data.String (IsString)
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Cardano.Crypto.DSIGN.Class as Crypto
import qualified Cardano.Crypto.Seed as Crypto
import qualified Cardano.Crypto.Signing as Crypto
import qualified Cardano.Crypto.Wallet as Crypto.HD
import Cardano.Binary (toStrictByteString)
import qualified Cardano.Chain.Common as Byron
import qualified Cardano.Crypto.Hashing as Byron
import qualified Cardano.Crypto.Signing as Byron
import qualified Cardano.Crypto.Wallet as Wallet
import Cardano.Api.Hash
import Cardano.Api.HasTypeProxy
import Cardano.Api.Keys.Class
import Cardano.Api.Keys.Shelley
import Cardano.Api.SerialiseCBOR
import Cardano.Api.SerialiseRaw
import Cardano.Api.SerialiseTextEnvelope
import Cardano.Api.SerialiseUsing
-- | Byron-era payment keys. Used for Byron addresses and witnessing
-- transactions that spend from these addresses.
--
-- These use Ed25519 but with a 32byte \"chaincode\" used in HD derivation.
-- The inclusion of the chaincode is a design mistake but one that cannot
-- be corrected for the Byron era. The Shelley era 'PaymentKey's do not include
-- a chaincode. It is safe to use a zero or random chaincode for new Byron keys.
--
-- This is a type level tag, used with other interfaces like 'Key'.
--
data ByronKey
data ByronKeyLegacy
class IsByronKey key where
byronKeyFormat :: ByronKeyFormat key
data ByronKeyFormat key where
ByronLegacyKeyFormat :: ByronKeyFormat ByronKeyLegacy
ByronModernKeyFormat :: ByronKeyFormat ByronKey
data SomeByronSigningKey
= AByronSigningKeyLegacy (SigningKey ByronKeyLegacy)
| AByronSigningKey (SigningKey ByronKey)
toByronSigningKey :: SomeByronSigningKey -> Byron.SigningKey
toByronSigningKey bWit =
case bWit of
AByronSigningKeyLegacy (ByronSigningKeyLegacy sKey) -> sKey
AByronSigningKey (ByronSigningKey sKey) -> sKey
--
-- Byron key
--
instance Key ByronKey where
newtype VerificationKey ByronKey =
ByronVerificationKey Byron.VerificationKey
deriving stock Eq
deriving (Show, IsString) via UsingRawBytesHex (VerificationKey ByronKey)
deriving newtype (ToCBOR, FromCBOR)
deriving anyclass SerialiseAsCBOR
newtype SigningKey ByronKey =
ByronSigningKey Byron.SigningKey
deriving (Show, IsString) via UsingRawBytesHex (SigningKey ByronKey)
deriving newtype (ToCBOR, FromCBOR)
deriving anyclass SerialiseAsCBOR
deterministicSigningKey :: AsType ByronKey -> Crypto.Seed -> SigningKey ByronKey
deterministicSigningKey AsByronKey seed =
ByronSigningKey (snd (Crypto.runMonadRandomWithSeed seed Byron.keyGen))
deterministicSigningKeySeedSize :: AsType ByronKey -> Word
deterministicSigningKeySeedSize AsByronKey = 32
getVerificationKey :: SigningKey ByronKey -> VerificationKey ByronKey
getVerificationKey (ByronSigningKey sk) =
ByronVerificationKey (Byron.toVerification sk)
verificationKeyHash :: VerificationKey ByronKey -> Hash ByronKey
verificationKeyHash (ByronVerificationKey vkey) =
ByronKeyHash (Byron.hashKey vkey)
instance HasTypeProxy ByronKey where
data AsType ByronKey = AsByronKey
proxyToAsType _ = AsByronKey
instance HasTextEnvelope (VerificationKey ByronKey) where
textEnvelopeType _ = "PaymentVerificationKeyByron_ed25519_bip32"
instance HasTextEnvelope (SigningKey ByronKey) where
textEnvelopeType _ = "PaymentSigningKeyByron_ed25519_bip32"
instance SerialiseAsRawBytes (VerificationKey ByronKey) where
serialiseToRawBytes (ByronVerificationKey (Byron.VerificationKey xvk)) =
Crypto.HD.unXPub xvk
eitherDeserialiseFromRawBytes (AsVerificationKey AsByronKey) bs =
first (\msg -> SerialiseAsRawBytesError ("Unable to deserialise VerificationKey ByronKey" ++ msg)) $
ByronVerificationKey . Byron.VerificationKey <$> Crypto.HD.xpub bs
instance SerialiseAsRawBytes (SigningKey ByronKey) where
serialiseToRawBytes (ByronSigningKey (Byron.SigningKey xsk)) =
toStrictByteString $ Crypto.toCBORXPrv xsk
eitherDeserialiseFromRawBytes (AsSigningKey AsByronKey) bs =
first (\e -> SerialiseAsRawBytesError ("Unable to deserialise SigningKey ByronKey" ++ show e)) $
ByronSigningKey . Byron.SigningKey . snd <$> CBOR.deserialiseFromBytes Byron.fromCBORXPrv (LB.fromStrict bs)
newtype instance Hash ByronKey = ByronKeyHash Byron.KeyHash
deriving (Eq, Ord)
deriving (Show, IsString) via UsingRawBytesHex (Hash ByronKey)
deriving (ToCBOR, FromCBOR) via UsingRawBytes (Hash ByronKey)
deriving anyclass SerialiseAsCBOR
instance SerialiseAsRawBytes (Hash ByronKey) where
serialiseToRawBytes (ByronKeyHash (Byron.KeyHash vkh)) =
Byron.abstractHashToBytes vkh
eitherDeserialiseFromRawBytes (AsHash AsByronKey) bs =
maybeToRight (SerialiseAsRawBytesError "Unable to deserialise Hash ByronKey") $
ByronKeyHash . Byron.KeyHash <$> Byron.abstractHashFromBytes bs
instance CastVerificationKeyRole ByronKey PaymentExtendedKey where
castVerificationKey (ByronVerificationKey vk) =
PaymentExtendedVerificationKey
(Byron.unVerificationKey vk)
instance CastVerificationKeyRole ByronKey PaymentKey where
castVerificationKey =
(castVerificationKey :: VerificationKey PaymentExtendedKey
-> VerificationKey PaymentKey)
. (castVerificationKey :: VerificationKey ByronKey
-> VerificationKey PaymentExtendedKey)
instance IsByronKey ByronKey where
byronKeyFormat = ByronModernKeyFormat
--
-- Legacy Byron key
--
instance Key ByronKeyLegacy where
newtype VerificationKey ByronKeyLegacy =
ByronVerificationKeyLegacy Byron.VerificationKey
deriving stock (Eq)
deriving (Show, IsString) via UsingRawBytesHex (VerificationKey ByronKeyLegacy)
deriving newtype (ToCBOR, FromCBOR)
deriving anyclass SerialiseAsCBOR
newtype SigningKey ByronKeyLegacy =
ByronSigningKeyLegacy Byron.SigningKey
deriving (Show, IsString) via UsingRawBytesHex (SigningKey ByronKeyLegacy)
deriving newtype (ToCBOR, FromCBOR)
deriving anyclass SerialiseAsCBOR
deterministicSigningKey :: AsType ByronKeyLegacy -> Crypto.Seed -> SigningKey ByronKeyLegacy
deterministicSigningKey _ _ = error "Please generate a non legacy Byron key instead"
deterministicSigningKeySeedSize :: AsType ByronKeyLegacy -> Word
deterministicSigningKeySeedSize AsByronKeyLegacy = 32
getVerificationKey :: SigningKey ByronKeyLegacy -> VerificationKey ByronKeyLegacy
getVerificationKey (ByronSigningKeyLegacy sk) =
ByronVerificationKeyLegacy (Byron.toVerification sk)
verificationKeyHash :: VerificationKey ByronKeyLegacy -> Hash ByronKeyLegacy
verificationKeyHash (ByronVerificationKeyLegacy vkey) =
ByronKeyHashLegacy (Byron.hashKey vkey)
instance HasTypeProxy ByronKeyLegacy where
data AsType ByronKeyLegacy = AsByronKeyLegacy
proxyToAsType _ = AsByronKeyLegacy
instance HasTextEnvelope (VerificationKey ByronKeyLegacy) where
textEnvelopeType _ = "PaymentVerificationKeyByronLegacy_ed25519_bip32"
instance HasTextEnvelope (SigningKey ByronKeyLegacy) where
textEnvelopeType _ = "PaymentSigningKeyByronLegacy_ed25519_bip32"
newtype instance Hash ByronKeyLegacy = ByronKeyHashLegacy Byron.KeyHash
deriving (Eq, Ord)
deriving (Show, IsString) via UsingRawBytesHex (Hash ByronKeyLegacy)
deriving (ToCBOR, FromCBOR) via UsingRawBytes (Hash ByronKeyLegacy)
deriving anyclass SerialiseAsCBOR
instance SerialiseAsRawBytes (Hash ByronKeyLegacy) where
serialiseToRawBytes (ByronKeyHashLegacy (Byron.KeyHash vkh)) =
Byron.abstractHashToBytes vkh
eitherDeserialiseFromRawBytes (AsHash AsByronKeyLegacy) bs =
maybeToRight (SerialiseAsRawBytesError "Unable to deserialise Hash ByronKeyLegacy") $
ByronKeyHashLegacy . Byron.KeyHash <$> Byron.abstractHashFromBytes bs
instance SerialiseAsRawBytes (VerificationKey ByronKeyLegacy) where
serialiseToRawBytes (ByronVerificationKeyLegacy (Byron.VerificationKey xvk)) =
Crypto.HD.unXPub xvk
eitherDeserialiseFromRawBytes (AsVerificationKey AsByronKeyLegacy) bs =
first (\msg -> SerialiseAsRawBytesError ("Unable to deserialise VerificationKey ByronKeyLegacy" ++ msg)) $
ByronVerificationKeyLegacy . Byron.VerificationKey <$> Crypto.HD.xpub bs
instance SerialiseAsRawBytes (SigningKey ByronKeyLegacy) where
serialiseToRawBytes (ByronSigningKeyLegacy (Byron.SigningKey xsk)) =
Crypto.HD.unXPrv xsk
eitherDeserialiseFromRawBytes (AsSigningKey AsByronKeyLegacy) bs =
first (\e -> SerialiseAsRawBytesError ("Unable to deserialise SigningKey ByronKeyLegacy" ++ show e)) $
ByronSigningKeyLegacy . snd <$> CBOR.deserialiseFromBytes decodeLegacyDelegateKey (LB.fromStrict bs)
where
-- Stolen from: cardano-sl/binary/src/Pos/Binary/Class/Core.hs
-- | Enforces that the input size is the same as the decoded one, failing in
-- case it's not.
enforceSize :: Text -> Int -> CBOR.Decoder s ()
enforceSize lbl requestedSize = CBOR.decodeListLenCanonical >>= matchSize requestedSize lbl
-- Stolen from: cardano-sl/binary/src/Pos/Binary/Class/Core.hs
-- | Compare two sizes, failing if they are not equal.
matchSize :: Int -> Text -> Int -> CBOR.Decoder s ()
matchSize requestedSize lbl actualSize =
when (actualSize /= requestedSize) $
cborError ( lbl <> " failed the size check. Expected " <> Text.pack (show requestedSize)
<> ", found " <> Text.pack (show actualSize)
)
decodeXPrv :: CBOR.Decoder s Wallet.XPrv
decodeXPrv = CBOR.decodeBytesCanonical >>= CBOR.toCborError . Wallet.xprv
-- | Decoder for a Byron/Classic signing key.
-- Lifted from cardano-sl legacy codebase.
decodeLegacyDelegateKey :: CBOR.Decoder s Byron.SigningKey
decodeLegacyDelegateKey = do
enforceSize "UserSecret" 4
_ <- do
enforceSize "vss" 1
CBOR.decodeBytes
pkey <- do
enforceSize "pkey" 1
Byron.SigningKey <$> decodeXPrv
_ <- do
CBOR.decodeListLenIndef
CBOR.decodeSequenceLenIndef (flip (:)) [] reverse CBOR.decodeNull
_ <- do
enforceSize "wallet" 0
pure pkey
instance CastVerificationKeyRole ByronKeyLegacy ByronKey where
castVerificationKey (ByronVerificationKeyLegacy vk) =
ByronVerificationKey vk
instance IsByronKey ByronKeyLegacy where
byronKeyFormat = ByronLegacyKeyFormat