module Network.Haskoin.Crypto.NormalizedKeys
( MasterKey(..)
, AccPrvKey(..)
, AccPubKey(..)
, AddrPrvKey(..)
, AddrPubKey(..)
, KeyIndex
, makeMasterKey
, loadMasterKey
, loadPrvAcc
, loadPubAcc
, addr
, accPrvKey
, accPubKey
, extPrvKey
, extPubKey
, intPrvKey
, intPubKey
, accPrvKeys
, accPubKeys
, extPrvKeys
, extPubKeys
, intPrvKeys
, intPubKeys
, extAddr
, intAddr
, extAddrs
, intAddrs
, extAddrs'
, intAddrs'
, extMulSigKey
, intMulSigKey
, extMulSigKeys
, intMulSigKeys
, extMulSigAddr
, intMulSigAddr
, extMulSigAddrs
, intMulSigAddrs
) where
import Control.DeepSeq (NFData, rnf)
import Control.Monad (liftM2, guard)
import Control.Applicative ((<$>))
import Data.Word (Word32)
import Data.Maybe (mapMaybe, fromJust, isJust)
import qualified Data.ByteString as BS (ByteString)
import Network.Haskoin.Crypto.ExtendedKeys
import Network.Haskoin.Crypto.Base58
import Network.Haskoin.Script.Parser
type KeyIndex = Word32
newtype MasterKey = MasterKey { masterKey :: XPrvKey }
deriving (Eq, Show, Read)
instance NFData MasterKey where
rnf (MasterKey m) = rnf m
newtype AccPrvKey = AccPrvKey { getAccPrvKey :: XPrvKey }
deriving (Eq, Show, Read)
instance NFData AccPrvKey where
rnf (AccPrvKey k) = rnf k
newtype AccPubKey = AccPubKey { getAccPubKey :: XPubKey }
deriving (Eq, Show, Read)
instance NFData AccPubKey where
rnf (AccPubKey k) = rnf k
newtype AddrPrvKey = AddrPrvKey { getAddrPrvKey :: XPrvKey }
deriving (Eq, Show, Read)
instance NFData AddrPrvKey where
rnf (AddrPrvKey k) = rnf k
newtype AddrPubKey = AddrPubKey { getAddrPubKey :: XPubKey }
deriving (Eq, Show, Read)
instance NFData AddrPubKey where
rnf (AddrPubKey k) = rnf k
makeMasterKey :: BS.ByteString -> Maybe MasterKey
makeMasterKey bs = MasterKey <$> makeXPrvKey bs
loadMasterKey :: XPrvKey -> Maybe MasterKey
loadMasterKey k
| xPrvDepth k == 0 &&
xPrvParent k == 0 &&
xPrvIndex k == 0 = Just $ MasterKey k
| otherwise = Nothing
loadPrvAcc :: XPrvKey -> Maybe AccPrvKey
loadPrvAcc k
| xPrvDepth k == 1 &&
xPrvIsPrime k = Just $ AccPrvKey k
| otherwise = Nothing
loadPubAcc :: XPubKey -> Maybe AccPubKey
loadPubAcc k
| xPubDepth k == 1 &&
xPubIsPrime k = Just $ AccPubKey k
| otherwise = Nothing
accPrvKey :: MasterKey -> KeyIndex -> Maybe AccPrvKey
accPrvKey (MasterKey par) i = AccPrvKey <$> (f =<< primeSubKey par i)
where f k = guard (isJust $ prvSubKey k 0) >>
guard (isJust $ prvSubKey k 1) >>
return k
accPubKey :: MasterKey -> KeyIndex -> Maybe AccPubKey
accPubKey (MasterKey par) i = f <$> primeSubKey par i
where f = AccPubKey . deriveXPubKey
extPrvKey :: AccPrvKey -> KeyIndex -> Maybe AddrPrvKey
extPrvKey (AccPrvKey par) i = AddrPrvKey <$> prvSubKey extKey i
where extKey = fromJust $ prvSubKey par 0
extPubKey :: AccPubKey -> KeyIndex -> Maybe AddrPubKey
extPubKey (AccPubKey par) i = AddrPubKey <$> pubSubKey extKey i
where extKey = fromJust $ pubSubKey par 0
intPrvKey :: AccPrvKey -> KeyIndex -> Maybe AddrPrvKey
intPrvKey (AccPrvKey par) i = AddrPrvKey <$> prvSubKey intKey i
where intKey = fromJust $ prvSubKey par 1
intPubKey :: AccPubKey -> KeyIndex -> Maybe AddrPubKey
intPubKey (AccPubKey par) i = AddrPubKey <$> pubSubKey intKey i
where intKey = fromJust $ pubSubKey par 1
accPrvKeys :: MasterKey -> KeyIndex -> [(AccPrvKey,KeyIndex)]
accPrvKeys m i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (accPrvKey m j) (return j)
accPubKeys :: MasterKey -> KeyIndex -> [(AccPubKey,KeyIndex)]
accPubKeys m i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (accPubKey m j) (return j)
extPrvKeys :: AccPrvKey -> KeyIndex -> [(AddrPrvKey,KeyIndex)]
extPrvKeys a i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (extPrvKey a j) (return j)
extPubKeys :: AccPubKey -> KeyIndex -> [(AddrPubKey,KeyIndex)]
extPubKeys a i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (extPubKey a j) (return j)
intPrvKeys :: AccPrvKey -> KeyIndex -> [(AddrPrvKey,KeyIndex)]
intPrvKeys a i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (intPrvKey a j) (return j)
intPubKeys :: AccPubKey -> KeyIndex -> [(AddrPubKey,KeyIndex)]
intPubKeys a i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (intPubKey a j) (return j)
addr :: AddrPubKey -> Address
addr = xPubAddr . getAddrPubKey
extAddr :: AccPubKey -> KeyIndex -> Maybe Address
extAddr a i = addr <$> extPubKey a i
intAddr :: AccPubKey -> KeyIndex -> Maybe Address
intAddr a i = addr <$> intPubKey a i
extAddrs :: AccPubKey -> KeyIndex -> [(Address,KeyIndex)]
extAddrs a i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (extAddr a j) (return j)
intAddrs :: AccPubKey -> KeyIndex -> [(Address,KeyIndex)]
intAddrs a i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (intAddr a j) (return j)
extAddrs' :: AccPubKey -> KeyIndex -> [(Address,KeyIndex)]
extAddrs' a i = mapMaybe f $ cycleIndex' i
where f j = liftM2 (,) (extAddr a j) (return j)
intAddrs' :: AccPubKey -> KeyIndex -> [(Address,KeyIndex)]
intAddrs' a i = mapMaybe f $ cycleIndex' i
where f j = liftM2 (,) (intAddr a j) (return j)
extMulSigKey :: AccPubKey -> [XPubKey] -> KeyIndex -> Maybe [AddrPubKey]
extMulSigKey a ps i = (map AddrPubKey) <$> mulSigSubKey keys i
where keys = map (fromJust . (flip pubSubKey 0)) $ (getAccPubKey a) : ps
intMulSigKey :: AccPubKey -> [XPubKey] -> KeyIndex -> Maybe [AddrPubKey]
intMulSigKey a ps i = (map AddrPubKey) <$> mulSigSubKey keys i
where keys = map (fromJust . (flip pubSubKey 1)) $ (getAccPubKey a) : ps
extMulSigKeys :: AccPubKey -> [XPubKey] -> KeyIndex -> [([AddrPubKey],KeyIndex)]
extMulSigKeys a ps i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (extMulSigKey a ps j) (return j)
intMulSigKeys :: AccPubKey -> [XPubKey] -> KeyIndex -> [([AddrPubKey],KeyIndex)]
intMulSigKeys a ps i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (intMulSigKey a ps j) (return j)
extMulSigAddr :: AccPubKey -> [XPubKey] -> Int -> KeyIndex -> Maybe Address
extMulSigAddr a ps r i = do
xs <- (map (xPubKey . getAddrPubKey)) <$> extMulSigKey a ps i
return $ scriptAddr $ sortMulSig $ PayMulSig xs r
intMulSigAddr :: AccPubKey -> [XPubKey] -> Int -> KeyIndex -> Maybe Address
intMulSigAddr a ps r i = do
xs <- (map (xPubKey . getAddrPubKey)) <$> intMulSigKey a ps i
return $ scriptAddr $ sortMulSig $ PayMulSig xs r
extMulSigAddrs :: AccPubKey -> [XPubKey] -> Int -> KeyIndex
-> [(Address,KeyIndex)]
extMulSigAddrs a ps r i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (extMulSigAddr a ps r j) (return j)
intMulSigAddrs :: AccPubKey -> [XPubKey] -> Int -> KeyIndex
-> [(Address,KeyIndex)]
intMulSigAddrs a ps r i = mapMaybe f $ cycleIndex i
where f j = liftM2 (,) (intMulSigAddr a ps r j) (return j)