ppad-bip32 0.1.0 → 0.1.1
raw patch · 4 files changed
+66/−13 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG +3/−0
- bench/Main.hs +1/−0
- lib/Crypto/HDKey/BIP32.hs +61/−12
- ppad-bip32.cabal +1/−1
CHANGELOG view
@@ -1,5 +1,8 @@ # Changelog +- 0.1.1 (2025-02-23)+ * Haddock improvements and examples.+ - 0.1.0 (2025-02-22) * Initial release, supporting basic HD wallet functionality.
bench/Main.hs view
@@ -29,6 +29,7 @@ , bench_derive_priv , bench_xpub , bench_xprv+ , bench_parse ] ]
lib/Crypto/HDKey/BIP32.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_HADDOCK prune #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE BinaryLiterals #-} {-# LANGUAGE LambdaCase #-}@@ -26,6 +27,9 @@ , XPub(..) , XPrv(..) , X(..)+ , ckd_pub+ , ckd_priv+ , n -- * Child derivation via path , derive@@ -96,14 +100,10 @@ !w1 = fi (w .>>. 16) .&. mask !w2 = fi (w .>>. 08) .&. mask !w3 = fi w .&. mask- in BS.cons w0 (BS.cons w1 (BS.cons w2 (BS.singleton w3))) -- XX+ in BS.cons w0 (BS.cons w1 (BS.cons w2 (BS.singleton w3))) -- extended keys -------------------------------------------------------------- --- | A public or private key, extended with a chain code.-data X a = X !a !BS.ByteString- deriving (Eq, Show)- -- | An extended public key. newtype XPub = XPub (X Secp256k1.Projective) deriving (Eq, Show)@@ -112,7 +112,22 @@ newtype XPrv = XPrv (X Integer) deriving (Eq, Show) +-- | A public or private key, extended with a chain code.+data X a = X !a !BS.ByteString+ deriving (Eq, Show)+ -- | Key types supporting identifier/fingerprint calculation.+--+-- >>> let Just hd = master "my very secret entropy"+-- >>> let Right my_xprv = hd_key hd+-- >>> let my_xpub = n k+-- >>> -- all have the same fingerprint+-- >>> fingerprint hd+-- "G\157\&8\146"+-- >>> fingerprint my_xprv+-- "G\157\&8\146"+-- >>> fingerprint my_xpub+-- "G\157\&8\146" class Extended k where -- | Calculate the identifier for an extended key. identifier :: k -> BS.ByteString@@ -206,6 +221,10 @@ -- | Derive a master 'HDKey' from a master seed. -- -- Fails with 'Nothing' if the provided seed has an invalid length.+--+--- >>> let Just hd = master "my very secret entropy"+-- >>> xpub hd+-- "xpub661MyMwAqRbcGTJPtZRqZyrvjxHCfhqXeiqb5GVU3EGuFBy4QxT3yt8iiHwZTiCzZFyuyNiqXB3eqzqFZ8z4L6HCrPSkDVFNuW59LXYvMjs" master :: BS.ByteString -> Maybe HDKey master seed = do m <- _master seed@@ -219,6 +238,10 @@ -- | Derive a private child node at the provided index. -- -- Fails with 'Nothing' if derivation is impossible.+--+-- >>> let Just child_prv = derive_child_priv hd 0+-- >>> xpub child_prv+-- "xpub68R2ZbtFeJTFJApdEdPqW5cy3d5wF96tTfJErhu3mTi2Ttaqvc88BMPrgS3hQSrHj91kRbzVLM9pue9f8219szRKZuTAx1LWbdLDLFDm6Ly" derive_child_priv :: HDKey -> Word32 -> Maybe HDKey derive_child_priv HDKey {..} i = case hd_key of Left _ -> Nothing@@ -232,18 +255,23 @@ -- | Derive a public child node at the provided index. -- -- Fails with 'Nothing' if derivation is impossible.+--+-- >>> :set -XNumericUnderscores+-- >>> let Just child_pub = derive_child_pub child_prv 0x8000_0000+-- >>> xpub child_pub+-- "xpub6B6LoU83Cpyx1UVMwuoQdQvY2BuGbPd2xsEVxCnj85UGgDN9bRz82hQhe9UFmyo4Pokuhjc8M1Cfc8ufLxcL6FkCF7Zc2eajEfWfZwMFF6X" derive_child_pub :: HDKey -> Word32 -> Maybe HDKey derive_child_pub HDKey {..} i = do (key, parent) <- case hd_key of Left _xpub -> do pub <- ckd_pub _xpub i- pure (pub, fingerprint _xpub)+ pure $! (pub, fingerprint _xpub) Right _xprv -> let pub = n (ckd_priv _xprv i)- in pure (pub, fingerprint _xprv)+ in pure $! (pub, fingerprint _xprv) let depth = hd_depth + 1 child = ser32 i- pure $ HDKey (Left key) depth parent child+ pure $! HDKey (Left key) depth parent child -- derivation path expression ------------------------------------------------- @@ -284,8 +312,10 @@ -- Fails with 'Nothing' if derivation is impossible, or if the -- provided path is invalid. ----- >>> let hd = master "my very secret master seed"--- >>> derive hd "m/44'/0'/0'/0/0"+-- >>> let Just hd = master "my very secret master seed"+-- >>> let Just child = derive hd "m/44'/0'/0'/0/0"+-- >>> xpub child+-- "xpub6FvaeGNFmCkLky6jwefrUfyH7gCGSAUckRBANT6wLQkm4eWZApsf4LqAadtbM8EBFfuKGFgzhgta4ByP6xnBodk2EV7BiwxCPLgu13oYWGp" derive :: HDKey -> BS.ByteString -- ^ derivation path@@ -308,8 +338,9 @@ -- Fails with 'error' if derivation is impossible, or if the provided -- path is invalid. ----- >>> let hd = master "my very secret master seed"--- >>> derive hd "m/44'/0'/0'/0/0"+-- >>> let Just other_child = derive hd "m/44'/0'/0'/0/1"+-- >>> xpub other_child+-- "xpub6FvaeGNFmCkLpkT3uahJnGPTfEX62PtH7uZAyjtru8S2FvPuYTQKn8ct6CNQAwHMXaGN6EYuwi1Tz2VD7msftH8VTAtzgNra9CForA9FBP4" derive_partial :: HDKey -> BS.ByteString@@ -339,6 +370,10 @@ _TESTNET_PRV_BYTES = "\EOT5\131\148" -- | Serialize a mainnet extended public key in base58check format.+--+-- >>> let Just hd = master "my very secret entropy"+-- >>> xpub hd+-- "xpub661MyMwAqRbcGTJPtZRqZyrvjxHCfhqXeiqb5GVU3EGuFBy4QxT3yt8iiHwZTiCzZFyuyNiqXB3eqzqFZ8z4L6HCrPSkDVFNuW59LXYvMjs" xpub :: HDKey -> BS.ByteString xpub x@HDKey {..} = B58C.encode . BS.toStrict . BSB.toLazyByteString $ case hd_key of@@ -349,6 +384,9 @@ } -- | Serialize a mainnet extended private key in base58check format.+--+-- >>> xprv hd+-- "xprv9s21ZrQH143K3yDvnXtqCqvCBvSiGF7gHVuzGt5rUtjvNPdusR8oS5pErywDM1jDDTcLpNNCbg9a9NuidBczRzSUp7seDeu8am64h6nfdrg" xprv :: HDKey -> BS.ByteString xprv x@HDKey {..} = B58C.encode . BS.toStrict . BSB.toLazyByteString $ case hd_key of@@ -356,6 +394,9 @@ Right _ -> _serialize _MAINNET_PRV x -- | Serialize a testnet extended public key in base58check format.+--+-- >>> tpub hd+-- "tpubD6NzVbkrYhZ4YFVFLkQvmuCJ55Nrf6LbCMRtRpYcP92nzUdmVBJ98KoYxL2LzDAEMAWpaxEi4GshYBKrwzqJDXjVuzC3u1ucVTfZ6ZD415x" tpub :: HDKey -> BS.ByteString tpub x@HDKey {..} = B58C.encode . BS.toStrict . BSB.toLazyByteString $ case hd_key of@@ -366,6 +407,9 @@ } -- | Serialize a testnet extended private key in base58check format.+--+-- >>> tprv hd+-- "tprv8ZgxMBicQKsPenTTT6kLNVYBW3rvVm9gd3q79JWJxsEQ9zNzrnUYwqBgnA6sMP7Xau97pTyxm2jNcETTkPxwF3i5Lm5wt1dBVrqV8kKi5v5" tprv :: HDKey -> BS.ByteString tprv x@HDKey {..} = B58C.encode . BS.toStrict . BSB.toLazyByteString $ case hd_key of@@ -396,6 +440,11 @@ -- | Parse a base58check-encoded 'ByteString' into a 'HDKey'. -- -- Fails with 'Nothing' if the provided key is invalid.+--+-- >>> let Just hd = master "my very secret entropy"+-- >>> let Just my_xprv = parse (xprv hd)+-- >>> my_xprv == hd+-- True parse :: BS.ByteString -> Maybe HDKey parse b58 = do bs <- B58C.decode b58
ppad-bip32.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: ppad-bip32-version: 0.1.0+version: 0.1.1 synopsis: BIP32 hierarchical deterministic wallets. license: MIT license-file: LICENSE