module Bitcoin.BIP32.DetDerive
( module Bitcoin.BIP32.DetDerive
, module Bitcoin.BIP32.Types
)
where
import Bitcoin.Internal.Types
import Bitcoin.BIP32.Types
import Data.Serialize as Bin
import Data.Serialize.Get as BinGet
import qualified Network.Haskoin.Crypto as HC
import Network.Haskoin.Crypto (DerivPathI(..))
class DerivationSeed a where
toDerivSeed :: a -> ByteString
detDerive
:: forall a sourceKey t k derivPath.
( DerivationSeed a
, DerivPathElem derivPath
, IsChildKey sourceKey t k derivPath
)
=> sourceKey
-> a
-> t k
detDerive sourceKey seed =
mkChild sourceKey path
where
path :: derivPath
path = toPath (to128bitSeed seed)
toPath (w1,w2,w3,w4) = derivBegin w1 /:| w2 /:| w3 /:| w4
to128bitSeed
:: DerivationSeed a
=> a
-> (Word32, Word32, Word32, Word32)
to128bitSeed a = either (\e -> error $ "to128bitSeed bug: " ++ e) id $
BinGet.runGet getWords (Bin.encode . HC.hash256 . toDerivSeed $ a)
where
getWords = do
w1 <- BinGet.getWord32be
w2 <- BinGet.getWord32be
w3 <- BinGet.getWord32be
w4 <- BinGet.getWord32be
return (w1,w2,w3,w4)
class DerivPathElem derivPath where
derivBegin :: Word32 -> derivPath
(/:|) :: derivPath -> Word32 -> derivPath
instance DerivPathElem HC.SoftPath where
derivBegin i = Deriv :/ cap31Bit i
(/:|) p i = p :/ cap31Bit i
instance DerivPathElem HC.HardPath where
derivBegin i = Deriv :| cap31Bit i
(/:|) p i = p :| cap31Bit i
cap31Bit :: Word32 -> Word32
cap31Bit = (`mod` (0x80000000 :: Word32))