{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} module Haskoin.Keys.ExtendedSpec (spec) where import Control.Monad (forM_) import Data.Aeson as A import Data.Bits ((.&.)) import qualified Data.ByteString.Lazy.Char8 as B8 import Data.Bytes.Get import Data.Bytes.Put import Data.Bytes.Serial import Data.Either (isLeft) import Data.Maybe (fromJust, isJust, isNothing) import Data.String (fromString) import Data.String.Conversions (cs) import Data.Text (Text) import Data.Word (Word32) import Haskoin.Address import Haskoin.Constants import Haskoin.Keys import Haskoin.Util import Haskoin.Util.Arbitrary import Haskoin.UtilSpec (customCerealID) import Test.HUnit (Assertion, assertBool, assertEqual) import Test.Hspec import Test.Hspec.QuickCheck import Test.QuickCheck hiding ((.&.)) serialVals :: [SerialBox] serialVals = [ SerialBox arbitraryDerivPath , SerialBox arbitraryHardPath , SerialBox arbitrarySoftPath ] readVals :: [ReadBox] readVals = [ ReadBox arbitraryDerivPath , ReadBox arbitraryHardPath , ReadBox arbitrarySoftPath , ReadBox arbitraryXPrvKey , ReadBox (snd <$> arbitraryXPubKey) , ReadBox arbitraryParsedPath , ReadBox arbitraryBip32PathIndex ] jsonVals :: [JsonBox] jsonVals = [ JsonBox arbitraryDerivPath , JsonBox arbitraryHardPath , JsonBox arbitrarySoftPath , JsonBox arbitraryParsedPath ] netVals :: [NetBox] netVals = [ NetBox ( xPrvToJSON , xPrvToEncoding , xPrvFromJSON , genNetData arbitraryXPrvKey) , NetBox ( xPubToJSON , xPubToEncoding , xPubFromJSON , genNetData (snd <$> arbitraryXPubKey)) ] spec :: Spec spec = do testIdentity serialVals readVals jsonVals netVals describe "Custom identity tests" $ do prop "encodes and decodes extended private key" $ forAll arbitraryNetwork $ \net -> forAll arbitraryXPrvKey $ customCerealID (getXPrvKey net) (putXPrvKey net) prop "encodes and decodes extended public key" $ forAll arbitraryNetwork $ \net -> forAll arbitraryXPubKey $ customCerealID (getXPubKey net) (putXPubKey net) . snd describe "bip32 subkey derivation vector 1" $ vectorSpec m1 vector1 describe "bip32 subkey derivation vector 2" $ vectorSpec m2 vector2 describe "bip32 subkey derivation vector 3" $ vectorSpec m3 vector3 describe "bip32 subkey derivation using string path" $ do it "either derivations" testApplyPath it "either derivations" testBadApplyPath it "dublic derivations" testDerivePubPath it "private derivations" testDerivePrvPath it "path parsing" testParsePath it "from json" testFromJsonPath it "to json" testToJsonPath describe "Derivation Paths" $ do prop "from string derivation path" $ forAll arbitraryDerivPath $ \p -> fromString (cs $ pathToStr p) == p prop "from string hard derivation path" $ forAll arbitraryHardPath $ \p -> fromString (cs $ pathToStr p) == p prop "from string soft derivation path" $ forAll arbitrarySoftPath $ \p -> fromString (cs $ pathToStr p) == p prop "from and to lists of derivation paths" $ forAll arbitraryDerivPath $ \p -> listToPath (pathToList p) == p prop "from and to lists of hard derivation paths" $ forAll arbitraryHardPath $ \p -> toHard (listToPath $ pathToList p) == Just p prop "from and to lists of soft derivation paths" $ forAll arbitrarySoftPath $ \p -> toSoft (listToPath $ pathToList p) == Just p describe "Extended Keys" $ do let net = btc prop "computes pubkey of a subkey is subkey of the pubkey" $ forAll arbitraryXPrvKey pubKeyOfSubKeyIsSubKeyOfPubKey prop "exports and imports extended private key" $ forAll arbitraryXPrvKey $ \k -> xPrvImport net (xPrvExport net k) == Just k prop "exports and imports extended public key" $ forAll arbitraryXPubKey $ \(_, k) -> xPubImport net (xPubExport net k) == Just k pubKeyOfSubKeyIsSubKeyOfPubKey :: XPrvKey -> Word32 -> Bool pubKeyOfSubKeyIsSubKeyOfPubKey k i = deriveXPubKey (prvSubKey k i') == pubSubKey (deriveXPubKey k) i' where i' = fromIntegral $ i .&. 0x7fffffff -- make it a public derivation testFromJsonPath :: Assertion testFromJsonPath = sequence_ $ do path <- jsonPathVectors return $ assertEqual path (Just [fromString path :: DerivPath]) (A.decode $ B8.pack $ "[\"" ++ path ++ "\"]") testToJsonPath :: Assertion testToJsonPath = sequence_ $ do path <- jsonPathVectors return $ assertEqual path (B8.pack $ "[\"" ++ path ++ "\"]") (A.encode [fromString path :: ParsedPath]) jsonPathVectors :: [String] jsonPathVectors = [ "m" , "m/0" , "m/0'" , "M/0'" , "m/2147483647" , "M/2147483647" , "m/1/2/3/4/5/6/7/8" , "M/1/2/3/4/5/6/7/8" , "m/1'/2'/3/4" , "M/1'/2'/3/4" ] testParsePath :: Assertion testParsePath = sequence_ $ do (path, t) <- parsePathVectors return $ assertBool path (t $ parsePath path) parsePathVectors :: [(String, Maybe ParsedPath -> Bool)] parsePathVectors = [ ("m", isJust) , ("m/0'", isJust) , ("M/0'", isJust) , ("m/2147483648", isNothing) , ("m/2147483647", isJust) , ("M/2147483648", isNothing) , ("M/2147483647", isJust) , ("M/-1", isNothing) , ("M/-2147483648", isNothing) , ("m/1/2/3/4/5/6/7/8", isJust) , ("M/1/2/3/4/5/6/7/8", isJust) , ("m/1'/2'/3/4", isJust) , ("M/1'/2'/3/4", isJust) , ("m/1/2'/3/4'", isJust) , ("M/1/2'/3/4'", isJust) , ("meh", isNothing) , ("infinity", isNothing) , ("NaN", isNothing) ] testApplyPath :: Assertion testApplyPath = sequence_ $ do (key, path, final) <- applyPathVectors return $ assertEqual path final $ applyPath (fromJust $ parsePath path) key testBadApplyPath :: Assertion testBadApplyPath = sequence_ $ do (key, path) <- badApplyPathVectors return $ assertBool path $ isLeft $ applyPath (fromJust $ parsePath path) key testDerivePubPath :: Assertion testDerivePubPath = sequence_ $ do (key, path, final) <- derivePubPathVectors return $ assertEqual path final $ derivePubPath (fromString path :: SoftPath) key testDerivePrvPath :: Assertion testDerivePrvPath = sequence_ $ do (key, path, final) <- derivePrvPathVectors return $ assertEqual path final $ derivePath (fromString path :: DerivPath) key derivePubPathVectors :: [(XPubKey, String, XPubKey)] derivePubPathVectors = [ ( xpub, "M", xpub ) , ( xpub, "M/8", pubSubKey xpub 8 ) , ( xpub, "M/8/30/1", foldl pubSubKey xpub [8,30,1] ) ] where xprv = fromJust $ xPrvImport btc "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\ \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB" xpub = deriveXPubKey xprv derivePrvPathVectors :: [(XPrvKey, String, XPrvKey)] derivePrvPathVectors = [ ( xprv, "m", xprv ) , ( xprv, "M", xprv ) , ( xprv, "m/8'", hardSubKey xprv 8 ) , ( xprv, "M/8'", hardSubKey xprv 8 ) , ( xprv, "m/8'/30/1" , foldl prvSubKey (hardSubKey xprv 8) [30,1] ) , ( xprv, "M/8'/30/1" , foldl prvSubKey (hardSubKey xprv 8) [30,1] ) , ( xprv, "m/3/20" , foldl prvSubKey xprv [3,20] ) , ( xprv, "M/3/20" , foldl prvSubKey xprv [3,20] ) ] where xprv = fromJust $ xPrvImport btc "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\ \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB" applyPathVectors :: [(XKey, String, Either String XKey)] applyPathVectors = [ (XPrv xprv btc, "m", Right (XPrv xprv btc)) , (XPrv xprv btc, "M", Right (XPub xpub btc)) , (XPrv xprv btc, "m/8'", Right (XPrv (hardSubKey xprv 8) btc)) , ( XPrv xprv btc , "M/8'" , Right (XPub (deriveXPubKey (hardSubKey xprv 8)) btc)) , ( XPrv xprv btc , "m/8'/30/1" , Right (XPrv (foldl prvSubKey (hardSubKey xprv 8) [30, 1]) btc)) , ( XPrv xprv btc , "M/8'/30/1" , Right (XPub (deriveXPubKey (foldl prvSubKey (hardSubKey xprv 8) [30, 1])) btc)) , (XPrv xprv btc, "m/3/20", Right (XPrv (foldl prvSubKey xprv [3, 20]) btc)) , ( XPrv xprv btc , "M/3/20" , Right (XPub (deriveXPubKey (foldl prvSubKey xprv [3, 20])) btc)) , ( XPub xpub btc , "M/3/20" , Right (XPub (deriveXPubKey (foldl prvSubKey xprv [3, 20])) btc)) ] where xprv = fromJust $ xPrvImport btc "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\ \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB" xpub = deriveXPubKey xprv badApplyPathVectors :: [(XKey, String)] badApplyPathVectors = [ (XPub xpub btc, "m/8'") , (XPub xpub btc, "M/8'") , (XPub xpub btc, "M/1/2/3'/4/5") ] where xprv = fromJust $ xPrvImport btc "xprv9s21ZrQH143K46iDVRSyFfGfMgQjzC4BV3ZUfNbG7PHQrJjE53ofAn5gYkp6KQ\ \WzGmb8oageSRxBY8s4rjr9VXPVp2HQDbwPt4H31Gg4LpB" xpub = deriveXPubKey xprv -- BIP 0032 Test Vectors -- https://en.bitcoin.it/wiki/BIP_0032_TestVectors bip44Addr :: DerivPath bip44Addr = Deriv :| 44 :| 0 :| 0 :/ 0 :/ 0 vectorSpec :: TestKey -> [TestVector] -> Spec vectorSpec mTxt vecTxt = forM_ (parseVector mTxt vecTxt) $ \(d,m,v) -> it ("chain " <> cs d) $ runVector m v runVector :: XPrvKey -> TestVector -> Assertion runVector m v = do assertBool "xPrvID" $ encodeHex (runPutS . serialize $ xPrvID m) == v !! 0 assertBool "xPrvFP" $ encodeHex (runPutS . serialize $ xPrvFP m) == v !! 1 assertBool "xPrvAddr" $ addrToText btc (xPubAddr $ deriveXPubKey m) == Just (v !! 2) assertBool "bip44Addr" $ addrToText btc (xPubAddr $ deriveXPubKey $ derivePath bip44Addr m) == Just (v !! 3) assertBool "prvKey" $ encodeHex (getSecKey $ xPrvKey m) == v !! 4 assertBool "xPrvWIF" $ xPrvWif btc m == v !! 5 assertBool "pubKey" $ encodeHex (exportPubKey True $ xPubKey $ deriveXPubKey m) == v !! 6 assertBool "chain code" $ encodeHex (runPutS . serialize $ xPrvChain m) == v !! 7 assertBool "Hex PubKey" $ encodeHex (runPutS $ putXPubKey btc $ deriveXPubKey m) == v !! 8 assertBool "Hex PrvKey" $ encodeHex (runPutS (putXPrvKey btc m)) == v !! 9 assertBool "Base58 PubKey" $ xPubExport btc (deriveXPubKey m) == v !! 10 assertBool "Base58 PrvKey" $ xPrvExport btc m == v !! 11 -- This function was used to generate addition data for the test vectors genVector :: XPrvKey -> [(Text, Text)] genVector m = [ ("xPrvID", encodeHex (runPutS . serialize $ xPrvID m)) , ("xPrvFP", encodeHex (runPutS . serialize $ xPrvFP m)) , ("xPrvAddr", fromJust $ addrToText btc (xPubAddr $ deriveXPubKey m)) , ( "bip44Addr" , fromJust $ addrToText btc (xPubAddr $ deriveXPubKey $ derivePath bip44Addr m)) , ("prvKey", encodeHex (getSecKey $ xPrvKey m)) , ("xPrvWIF", xPrvWif btc m) , ("pubKey", encodeHex (exportPubKey True $ xPubKey $ deriveXPubKey m)) , ("chain code", encodeHex (runPutS . serialize $ xPrvChain m)) , ("Hex PubKey", encodeHex (runPutS $ putXPubKey btc $ deriveXPubKey m)) , ("Hex PrvKey", encodeHex (runPutS (putXPrvKey btc m))) ] parseVector :: TestKey -> [TestVector] -> [(Text, XPrvKey, TestVector)] parseVector mTxt vs = go <$> vs where mast = makeXPrvKey $ fromJust $ decodeHex mTxt go (d:vec) = let deriv = getParsedPath $ fromJust $ parsePath $ cs d in (d, derivePath deriv mast, vec) go _ = undefined type TestVector = [Text] type TestKey = Text m1 :: TestKey m1 = "000102030405060708090a0b0c0d0e0f" vector1 :: [TestVector] vector1 = [ [ "m" , "3442193e1bb70916e914552172cd4e2dbc9df811" , "3442193e" , "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma" , "1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r" , "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35" , "L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW" , "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2" , "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508" , "0488b21e000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d5080339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2" , "0488ade4000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d50800e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35" , "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8" , "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" ] , [ "m/0'" , "5c1bd648ed23aa5fd50ba52b2457c11e9e80a6a7" , "5c1bd648" , "19Q2WoS5hSS6T8GjhK8KZLMgmWaq4neXrh" , "1DDVw6BRKUv9U8Hzg5rGsia13nDrgJQpBd" , "edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea" , "L5BmPijJjrKbiUfG4zbiFKNqkvuJ8usooJmzuD7Z8dkRoTThYnAT" , "035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56" , "47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141" , "0488b21e013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56" , "0488ade4013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae623614100edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea" , "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw" , "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7" ] , [ "m/0'/1" , "bef5a2f9a56a94aab12459f72ad9cf8cf19c7bbe" , "bef5a2f9" , "1JQheacLPdM5ySCkrZkV66G2ApAXe1mqLj" , "1KMg6dRggXSkpz9fFyU76ru83TUSwPePEZ" , "3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368" , "KyFAjQ5rgrKvhXvNMtFB5PCSKUYD1yyPEe3xr3T34TZSUHycXtMM" , "03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c" , "2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19" , "0488b21e025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c1903501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c" , "0488ade4025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19003c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368" , "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ" , "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs" ] , [ "m/0'/1/2'" , "ee7ab90cde56a8c0e2bb086ac49748b8db9dce72" , "ee7ab90c" , "1NjxqbA9aZWnh17q1UW3rB4EPu79wDXj7x" , "1WykKhR25y7VDT21nZEwUUKSKDz9pENJh" , "cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca" , "L43t3od1Gh7Lj55Bzjj1xDAgJDcL7YFo2nEcNaMGiyRZS1CidBVU" , "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2" , "04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f" , "0488b21e03bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2" , "0488ade403bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f00cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca" , "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5" , "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM" ] , [ "m/0'/1/2'/2" , "d880d7d893848509a62d8fb74e32148dac68412f" , "d880d7d8" , "1LjmJcdPnDHhNTUgrWyhLGnRDKxQjoxAgt" , "1asQ3smHhv2nv5R6hPpiUfkEorJpsdwwx" , "0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4" , "KwjQsVuMjbCP2Zmr3VaFaStav7NvevwjvvkqrWd5Qmh1XVnCteBR" , "02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29" , "cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd" , "0488b21e04ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29" , "0488ade404ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd000f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4" , "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV" , "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334" ] , [ "m/0'/1/2'/2/1000000000" , "d69aa102255fed74378278c7812701ea641fdf32" , "d69aa102" , "1LZiqrop2HGR4qrH1ULZPyBpU6AUP49Uam" , "1HXJog342VFdc68AB9Cb6LwVmCjvcLMiwm" , "471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8" , "Kybw8izYevo5xMh1TK7aUr7jHFCxXS1zv8p3oqFz3o2zFbhRXHYs" , "022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011" , "c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e" , "0488b21e05d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011" , "0488ade405d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e00471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8" , "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy" , "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76" ] ] m2 :: TestKey m2 = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542" vector2 :: [TestVector] vector2 = [ [ "m" , "bd16bee53961a47d6ad888e29545434a89bdfe95" , "bd16bee5" , "1JEoxevbLLG8cVqeoGKQiAwoWbNYSUyYjg" , "148CGtv7bwcC933EHtcDfzDQVneur1R8Y1" , "4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e" , "KyjXhyHF9wTphBkfpxjL8hkDXDUSbE3tKANT94kXSyh6vn6nKaoy" , "03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7" , "60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689" , "0488b21e00000000000000000060499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd968903cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7" , "0488ade400000000000000000060499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689004b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e" , "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB" , "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U" ] , [ "m/0" , "5a61ff8eb7aaca3010db97ebda76121610b78096" , "5a61ff8e" , "19EuDJdgfRkwCmRzbzVBHZWQG9QNWhftbZ" , "1KVyTSpsBGYs7NdyZmArEpVTfWJQSgiDCx" , "abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e" , "L2ysLrR6KMSAtx7uPqmYpoTeiRzydXBattRXjXz5GDFPrdfPzKbj" , "02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea" , "f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c" , "0488b21e01bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea" , "0488ade401bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c00abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e" , "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH" , "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt" ] , [ "m/0/2147483647'" , "d8ab493736da02f11ed682f88339e720fb0379d1" , "d8ab4937" , "1Lke9bXGhn5VPrBuXgN12uGUphrttUErmk" , "14MFLsfx1nc4RKiaH9khqDTNL9CRz3q347" , "877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93" , "L1m5VpbXmMp57P3knskwhoMTLdhAAaXiHvnGLMribbfwzVRpz2Sr" , "03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b" , "be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9" , "0488b21e025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d903c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b" , "0488ade4025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d900877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93" , "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a" , "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9" ] , [ "m/0/2147483647'/1" , "78412e3a2296a40de124307b6485bd19833e2e34" , "78412e3a" , "1BxrAr2pHpeBheusmd6fHDP2tSLAUa3qsW" , "19ou31MGyGW9VFx7woKBqwLe5JHhQBYaDD" , "704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7" , "KzyzXnznxSv249b4KuNkBwowaN3akiNeEHy5FWoPCJpStZbEKXN2" , "03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9" , "f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb" , "0488b21e03d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9" , "0488ade403d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb00704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7" , "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon" , "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef" ] , [ "m/0/2147483647'/1/2147483646'" , "31a507b815593dfc51ffc7245ae7e5aee304246e" , "31a507b8" , "15XVotxCAV7sRx1PSCkQNsGw3W9jT9A94R" , "18GYmRm4nyjk8ydvoVXFxMWQvxhksEFDZR" , "f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d" , "L5KhaMvPYRW1ZoFmRjUtxxPypQ94m6BcDrPhqArhggdaTbbAFJEF" , "02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0" , "637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29" , "0488b21e0478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e2902d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0" , "0488ade40478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e2900f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d" , "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL" , "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc" ] , [ "m/0/2147483647'/1/2147483646'/2" , "26132fdbe7bf89cbc64cf8dafa3f9f88b8666220" , "26132fdb" , "14UKfRV9ZPUp6ZC9PLhqbRtxdihW9em3xt" , "1758mgwNZhyzpRLe4u7FjqpJtqKpaGhXh7" , "bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23" , "L3WAYNAZPxx1fr7KCz7GN9nD5qMBnNiqEJNJMU1z9MMaannAt4aK" , "024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c" , "9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271" , "0488b21e0531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c" , "0488ade40531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed27100bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23" , "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt" , "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j" ] ] m3 :: TestKey m3 = "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be" vector3 :: [TestVector] vector3 = [ [ "m" , "41d63b50d8dd5e730cdf4c79a56fc929a757c548" , "41d63b50" , "1717ZYpXhZW5CqAbWSjDJbCey3FyKUmCSf" , "17rxURoF96VhmkcEGCj5LNQkmN9HVhWb7F" , "00ddb80b067e0d4993197fe10f2657a844a384589847602d56f0c629c81aae32" , "KwFPqAq9SKx1sPg15Qk56mqkHwrfGPuywtLUxoWPkiTSBoxCs8am" , "03683af1ba5743bdfc798cf814efeeab2735ec52d95eced528e692b8e34c4e5669" , "01d28a3e53cffa419ec122c968b3259e16b65076495494d97cae10bbfec3c36f" , "0488b21e00000000000000000001d28a3e53cffa419ec122c968b3259e16b65076495494d97cae10bbfec3c36f03683af1ba5743bdfc798cf814efeeab2735ec52d95eced528e692b8e34c4e5669" , "0488ade400000000000000000001d28a3e53cffa419ec122c968b3259e16b65076495494d97cae10bbfec3c36f0000ddb80b067e0d4993197fe10f2657a844a384589847602d56f0c629c81aae32" , "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13" , "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6" ] , [ "m/0'" , "c61368bb50e066acd95bd04a0b23d3837fb75698" , "c61368bb" , "1K4L3YxEwg8HkSEapM4iSiGuR6HeQ53KPX" , "13QeQVJNNakdUU55P1fc8xPMkkeYVzn4o6" , "491f7a2eebc7b57028e0d3faa0acda02e75c33b03c48fb288c41e2ea44e1daef" , "KyfrPaeirL5yYAoZvfzyoKXSdszeLqg5vb6dNy9ymvjzZrMZY8GW" , "026557fdda1d5d43d79611f784780471f086d58e8126b8c40acb82272a7712e7f2" , "e5fea12a97b927fc9dc3d2cb0d1ea1cf50aa5a1fdc1f933e8906bb38df3377bd" , "0488b21e0141d63b5080000000e5fea12a97b927fc9dc3d2cb0d1ea1cf50aa5a1fdc1f933e8906bb38df3377bd026557fdda1d5d43d79611f784780471f086d58e8126b8c40acb82272a7712e7f2" , "0488ade40141d63b5080000000e5fea12a97b927fc9dc3d2cb0d1ea1cf50aa5a1fdc1f933e8906bb38df3377bd00491f7a2eebc7b57028e0d3faa0acda02e75c33b03c48fb288c41e2ea44e1daef" , "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y" , "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L" ] ]