Skip to content

Commit

Permalink
Merge #1042
Browse files Browse the repository at this point in the history
1042: use a special 'ByronHybrid' index with range going from 0 to 2^32  r=KtorZ a=KtorZ

# Issue Number

<!-- Put here a reference to the issue this PR relates to and which requirements it tackles -->

#1041 

# Overview

<!-- Detail in a few bullet points the work accomplished in this PR -->

- [x] I have used a special 'ByronHybrid' index with range going from 0 to 2^32 for the address path.

# Comments

<!-- Additional comments or screenshots to attach if any -->

:question: Should we also worry about the account path :question: 

<!-- 
Don't forget to:

 ✓ Self-review your changes to make sure nothing unexpected slipped through
 ✓ Assign yourself to the PR
 ✓ Assign one or several reviewer(s)
 ✓ Once created, link this PR to its corresponding ticket
 ✓ Acknowledge any changes required to the Wiki
-->


Co-authored-by: KtorZ <[email protected]>
  • Loading branch information
iohk-bors[bot] and KtorZ authored Nov 15, 2019
2 parents b792178 + 212ed0c commit 4359edb
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 27 deletions.
31 changes: 21 additions & 10 deletions lib/core/src/Cardano/Byron/Codec/Cbor.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
-- need this for {-# HLINT ... #-}; see https://github.com/ndmitchell/hlint#ignoring-hints
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

Expand Down Expand Up @@ -176,7 +179,7 @@ decodeAddressDerivationPath
:: Passphrase "addr-derivation-payload"
-> CBOR.Decoder s (Maybe
( Index 'Hardened 'AccountK
, Index 'Hardened 'AddressK
, Index 'ByronHybrid 'AddressK
))
decodeAddressDerivationPath pwd = do
_ <- CBOR.decodeListLenCanonicalOf 3
Expand Down Expand Up @@ -210,7 +213,7 @@ decodeDerivationPathAttr
-> [(Word8, ByteString)]
-> CBOR.Decoder s (Maybe
( Index 'Hardened 'AccountK
, Index 'Hardened 'AddressK
, Index 'ByronHybrid 'AddressK
))
decodeDerivationPathAttr pwd attrs = do
case lookup derPathTag attrs of
Expand All @@ -224,7 +227,7 @@ decodeDerivationPathAttr pwd attrs = do
derPathTag = 1
decoder :: CBOR.Decoder s (Maybe
( Index 'Hardened 'AccountK
, Index 'Hardened 'AddressK
, Index 'ByronHybrid 'AddressK
))
decoder = do
bytes <- CBOR.decodeBytes
Expand All @@ -238,12 +241,14 @@ decodeDerivationPathAttr pwd attrs = do
decodeDerivationPath
:: CBOR.Decoder s
( Index 'Hardened 'AccountK
, Index 'Hardened 'AddressK
, Index 'ByronHybrid 'AddressK
)
decodeDerivationPath = do
ixs <- decodeListIndef CBOR.decodeWord32
case ixs of
[acctIx, addrIx] | isValidIx acctIx && isValidIx addrIx ->
[acctIx, addrIx]
| is @'Hardened @'AccountK acctIx
&& is @'ByronHybrid @'AddressK addrIx ->
pure (toEnum $ fromIntegral acctIx, toEnum $ fromIntegral addrIx)
[_, _] ->
fail $ mconcat
Expand All @@ -257,10 +262,16 @@ decodeDerivationPath = do
, show ixs
]
where
isValidIx i =
i >= getIndex (minBound @(Index 'Hardened _))
is
:: forall (typ :: DerivationType) (depth :: Depth).
( Bounded (Index typ depth)
)
=> Word32
-> Bool
is i =
i >= getIndex (minBound @(Index typ depth))
&&
i <= getIndex (maxBound @(Index 'Hardened _))
i <= getIndex (maxBound @(Index typ depth))

decodeBlockHeader :: CBOR.Decoder s BlockHeader
decodeBlockHeader = do
Expand Down Expand Up @@ -623,7 +634,7 @@ encodeProtocolMagicAttr pm = mempty
encodeDerivationPathAttr
:: Passphrase "addr-derivation-payload"
-> Index 'Hardened 'AccountK
-> Index 'Hardened 'AddressK
-> Index 'ByronHybrid 'AddressK
-> CBOR.Encoding
encodeDerivationPathAttr pwd acctIx addrIx = mempty
<> CBOR.encodeWord8 1 -- Tag for 'DerivationPath' attribute
Expand All @@ -633,7 +644,7 @@ encodeDerivationPathAttr pwd acctIx addrIx = mempty

encodeDerivationPath
:: Index 'Hardened 'AccountK
-> Index 'Hardened 'AddressK
-> Index 'ByronHybrid 'AddressK
-> CBOR.Encoding
encodeDerivationPath (Index acctIx) (Index addrIx) = mempty
<> CBOR.encodeListLenIndef
Expand Down
2 changes: 1 addition & 1 deletion lib/core/src/Cardano/Wallet/DB/Sqlite.hs
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ selectSeqStatePendingIxs wid =
-- | Type alias for the index -> address map so that lines do not exceed 80
-- characters in width.
type RndStateAddresses = Map
(W.Index 'W.Hardened 'W.AccountK, W.Index 'W.Hardened 'W.AddressK)
(W.Index 'W.Hardened 'W.AccountK, W.Index 'W.ByronHybrid 'W.AddressK)
W.Address

-- Persisting 'RndState' requires that the wallet root key has already been
Expand Down
20 changes: 19 additions & 1 deletion lib/core/src/Cardano/Wallet/Primitive/AddressDerivation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ instance Bounded (Index 'Soft level) where
minBound = Index minBound
maxBound = let (Index ix) = minBound @(Index 'Hardened _) in Index (ix - 1)

instance Bounded (Index 'ByronHybrid level) where
minBound = Index minBound
maxBound = Index maxBound

instance Enum (Index 'Hardened level) where
fromEnum (Index ix) = fromIntegral ix
toEnum ix
Expand All @@ -232,11 +236,25 @@ instance Enum (Index 'Soft level) where
| otherwise =
Index (fromIntegral ix)

instance Enum (Index 'ByronHybrid level) where
fromEnum (Index ix) = fromIntegral ix
toEnum ix
| Index (fromIntegral ix) > maxBound @(Index 'ByronHybrid _) =
error "[email protected]: bad argument"
| otherwise =
Index (fromIntegral ix)

instance Buildable (Index derivationType level) where
build (Index ix) = fromString (show ix)

-- | Type of derivation that should be used with the given indexes.
data DerivationType = Hardened | Soft
--
-- In theory, we should only consider two derivation types: soft and hard.
--
-- However, historically, addresses in Cardano used to be generated across the
-- both soft and hard domain. We therefore introduce a 'ByronHybrid' derivation
-- type that is the exact union of `Hardened` and `Soft`.
data DerivationType = Hardened | Soft | ByronHybrid

-- | An interface for doing hard derivations from the root private key
class HardDerivation (key :: Depth -> * -> *) where
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ type family DerivationPath (depth :: Depth) :: * where
Index 'Hardened 'AccountK
-- The address key is generated from the account key and address index.
DerivationPath 'AddressK =
(Index 'Hardened 'AccountK, Index 'Hardened 'AddressK)
(Index 'Hardened 'AccountK, Index 'ByronHybrid 'AddressK)

instance WalletKey ByronKey where
changePassphrase = changePassphraseRnd
Expand Down Expand Up @@ -332,7 +332,7 @@ deriveAccountPrivateKey (Passphrase pwd) masterKey idx@(Index accIx) = ByronKey
deriveAddressPrivateKey
:: Passphrase "encryption"
-> ByronKey 'AccountK XPrv
-> Index 'Hardened 'AddressK
-> Index 'ByronHybrid 'AddressK
-> ByronKey 'AddressK XPrv
deriveAddressPrivateKey (Passphrase pwd) accountKey idx@(Index addrIx) = ByronKey
{ getKey = deriveXPrv DerivationScheme1 pwd (getKey accountKey) addrIx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ instance Buildable (RndState network) where
<> indentF 4 ("Change addresses: " <> blockMapF' tupleF build pending)

-- | Shortcut type alias for HD random address derivation path.
type DerivationPath = (Index 'Hardened 'AccountK, Index 'Hardened 'AddressK)
type DerivationPath = (Index 'Hardened 'AccountK, Index 'ByronHybrid 'AddressK)

-- An address is considered to belong to the 'RndState' wallet if it can be decoded
-- as a Byron HD random address, and where the wallet key can be used to decrypt
Expand Down Expand Up @@ -188,7 +188,7 @@ findUnusedPath g accIx used
(addrIx, gen') = randomIndex g

randomIndex
:: forall ix g. (RandomGen g, ix ~ Index 'Hardened 'AddressK)
:: forall ix g. (RandomGen g, ix ~ Index 'ByronHybrid 'AddressK)
=> g
-> (ix, g)
randomIndex g = (Index ix, g')
Expand Down
4 changes: 2 additions & 2 deletions lib/core/test/unit/Cardano/Byron/Codec/CborSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ prop_derivationPathRoundTrip
:: Passphrase "addr-derivation-payload"
-> Passphrase "addr-derivation-payload"
-> Index 'Hardened 'AccountK
-> Index 'Hardened 'AddressK
-> Index 'ByronHybrid 'AddressK
-> Property
prop_derivationPathRoundTrip pwd pwd' acctIx addrIx =
let
Expand All @@ -199,7 +199,7 @@ instance {-# OVERLAPS #-} Arbitrary (Passphrase "addr-derivation-payload") where
bytes <- BS.pack <$> vectorOf 32 arbitrary
return $ Passphrase $ BA.convert bytes

instance Arbitrary (Index 'Hardened 'AddressK) where
instance Arbitrary (Index 'ByronHybrid 'AddressK) where
shrink _ = []
arbitrary = arbitraryBoundedEnum

Expand Down
2 changes: 1 addition & 1 deletion lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ instance Arbitrary (Index 'Hardened 'AccountK) where
shrink _ = []
arbitrary = arbitraryBoundedEnum

instance Arbitrary (Index 'Hardened 'AddressK) where
instance Arbitrary (Index 'ByronHybrid 'AddressK) where
shrink _ = []
arbitrary = arbitraryBoundedEnum

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ prop_keyDerivation
:: Passphrase "seed"
-> Passphrase "encryption"
-> Index 'Hardened 'AccountK
-> Index 'Hardened 'AddressK
-> Index 'ByronHybrid 'AddressK
-> Property
prop_keyDerivation seed encPwd accIx addrIx =
rndKey `seq` property () -- NOTE Making sure this doesn't throw
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ instance Arbitrary (Index 'Soft 'AddressK) where
shrink _ = []
arbitrary = arbitraryBoundedEnum

instance Arbitrary (Index 'Hardened 'AddressK) where
instance Arbitrary (Index 'ByronHybrid 'AddressK) where
shrink _ = []
arbitrary = arbitraryBoundedEnum

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ data Rnd = Rnd
prop_derivedKeysAreOurs
:: Rnd
-> Rnd
-> Index 'Hardened 'AddressK
-> Index 'ByronHybrid 'AddressK
-> Property
prop_derivedKeysAreOurs
(Rnd st@(RndState _ accIx _ _ _) rk pwd) (Rnd st' _ _) addrIx =
Expand All @@ -254,7 +254,7 @@ prop_derivedKeysAreOurs
prop_derivedKeysAreOwned
:: Rnd
-> Rnd
-> Index 'Hardened 'AddressK
-> Index 'ByronHybrid 'AddressK
-> Property
prop_derivedKeysAreOwned
(Rnd st@(RndState _ accIx _ _ _) rk pwd)
Expand All @@ -281,7 +281,7 @@ prop_changeAddressesBelongToUs

prop_forbiddenAddreses
:: Rnd
-> Index 'Hardened 'AddressK
-> Index 'ByronHybrid 'AddressK
-> Property
prop_forbiddenAddreses (Rnd st@(RndState _ accIx _ _ _) rk pwd) addrIx = conjoin
[ (Set.notMember addr (forbidden st))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Prelude

import Cardano.Wallet.Primitive.AddressDerivation
( Depth (AccountK, AddressK, RootK)
, DerivationType (Hardened)
, DerivationType (..)
, Index
, NetworkDiscriminant (..)
, Passphrase (..)
Expand Down Expand Up @@ -77,7 +77,7 @@ prop_derivedKeysAreOurs
=> Passphrase "seed"
-> Passphrase "encryption"
-> Index 'Hardened 'AccountK
-> Index 'Hardened 'AddressK
-> Index 'ByronHybrid 'AddressK
-> ByronKey 'RootK XPrv
-> Property
prop_derivedKeysAreOurs seed encPwd accIx addrIx rk' =
Expand All @@ -98,7 +98,7 @@ instance Arbitrary (Index 'Hardened 'AccountK) where
shrink _ = []
arbitrary = arbitraryBoundedEnum

instance Arbitrary (Index 'Hardened 'AddressK) where
instance Arbitrary (Index 'ByronHybrid 'AddressK) where
shrink _ = []
arbitrary = arbitraryBoundedEnum

Expand Down

0 comments on commit 4359edb

Please sign in to comment.