haskoin-core 0.6.1 → 0.7.0
raw patch · 5 files changed
+119/−88 lines, 5 files
Files
- CHANGELOG.md +8/−0
- haskoin-core.cabal +2/−2
- src/Network/Haskoin/Address.hs +85/−4
- src/Network/Haskoin/Constants.hs +10/−0
- src/Network/Haskoin/Script/Standard.hs +14/−82
CHANGELOG.md view
@@ -4,6 +4,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 0.7.0+### Added+- Add `Serialize` instance for network constants.+- Add `Serialize` instance for addresses that includes network constants.++### Changed+- Move functions related to addresses from `Script` to `Address` module.+ ## 0.6.1 ### Added - Compatibility with latest GHC and base.
haskoin-core.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: a15368965c6befac912e285d4519667d835f4c9330b283af73a732d62915c260+-- hash: bee4365adfac078ce0642cae3009ffca1f4cb61498f0b9fe7aec964ff232a650 name: haskoin-core-version: 0.6.1+version: 0.7.0 synopsis: Bitcoin & Bitcoin Cash library for Haskell description: Haskoin Core is a complete Bitcoin and Bitcoin Cash library of functions and data types for Haskell developers. category: Bitcoin, Finance, Network
src/Network/Haskoin/Address.hs view
@@ -29,6 +29,15 @@ , p2wpkhAddr , p2shAddr , p2wshAddr+ , inputAddress+ , outputAddress+ , addressToScript+ , addressToScriptBS+ , addressToOutput+ , payToScriptAddress+ , payToWitnessScriptAddress+ , scriptToAddress+ , scriptToAddressBS -- * Private Key Wallet Import Format (WIF) , fromWif , toWif@@ -39,6 +48,7 @@ import Control.Monad import Data.Aeson as A import Data.Aeson.Types+import Data.ByteString (ByteString) import qualified Data.ByteString as B import Data.Function import Data.Hashable@@ -54,6 +64,7 @@ import Network.Haskoin.Constants import Network.Haskoin.Crypto import Network.Haskoin.Keys.Common+import Network.Haskoin.Script import Network.Haskoin.Util import Text.Read as R @@ -62,29 +73,42 @@ -- | pay to public key hash (regular) = PubKeyAddress { getAddrHash160 :: !Hash160 -- ^ RIPEMD160 hash of public key's SHA256 hash- , getAddrNet :: !Network+ , getAddrNet :: !Network -- ^ address network } -- | pay to script hash | ScriptAddress { getAddrHash160 :: !Hash160 -- ^ RIPEMD160 hash of script's SHA256 hash- , getAddrNet :: !Network+ , getAddrNet :: !Network -- ^ address network } -- | pay to witness public key hash | WitnessPubKeyAddress { getAddrHash160 :: !Hash160 -- ^ RIPEMD160 hash of public key's SHA256 hash- , getAddrNet :: !Network+ , getAddrNet :: !Network -- ^ address network } -- | pay to witness script hash | WitnessScriptAddress { getAddrHash256 :: !Hash256 -- ^ HASH256 hash of script- , getAddrNet :: !Network+ , getAddrNet :: !Network -- ^ address network } deriving (Eq, G.Generic) +instance Serialize Address where+ put a = do+ put $ getAddrNet a+ let bs = addressToScriptBS a+ put $ B.length bs+ putByteString bs+ get = do+ net <- S.get+ bs <- getByteString =<< S.get+ case scriptToAddressBS net bs of+ Nothing -> fail "Could not decode address"+ Just a -> return a+ instance Hashable Address where hashWithSalt i (PubKeyAddress h _) = i `hashWithSalt` h hashWithSalt i (ScriptAddress h _) = i `hashWithSalt` h@@ -255,6 +279,63 @@ p2wshAddr net h | getSegWit net = Just $ WitnessScriptAddress h net | otherwise = Nothing++-- | Compute a pay-to-script-hash address for an output script.+payToScriptAddress :: Network -> ScriptOutput -> Address+payToScriptAddress net out = p2shAddr net (addressHash (encodeOutputBS out))++-- | Compute a pay-to-witness-script-hash address for an output script. Only on+-- SegWit networks.+payToWitnessScriptAddress :: Network -> ScriptOutput -> Maybe Address+payToWitnessScriptAddress net out = p2wshAddr net (sha256 (encodeOutputBS out))++-- | Encode an output script from an address. Will fail if using a+-- pay-to-witness address on a non-SegWit network.+addressToOutput :: Address -> ScriptOutput+addressToOutput a+ | isPubKeyAddress a = PayPKHash (getAddrHash160 a)+ | isScriptAddress a = PayScriptHash (getAddrHash160 a)+ | isWitnessPubKeyAddress a = PayWitnessPKHash (getAddrHash160 a)+ | isWitnessScriptAddress a = PayWitnessScriptHash (getAddrHash256 a)+ | otherwise = undefined++-- | Get output script AST for an 'Address'.+addressToScript :: Address -> Script+addressToScript = encodeOutput . addressToOutput++-- | Encode address as output script in 'ByteString' form.+addressToScriptBS :: Address -> ByteString+addressToScriptBS = S.encode . addressToScript++-- | Decode an output script into an 'Address' if it has such representation.+scriptToAddress :: Network -> Script -> Maybe Address+scriptToAddress net = eitherToMaybe . (outputAddress net <=< decodeOutput)++-- | Decode a serialized script into an 'Address'.+scriptToAddressBS :: Network -> ByteString -> Maybe Address+scriptToAddressBS net = eitherToMaybe . (outputAddress net <=< decodeOutputBS)++-- | Get the 'Address' of a 'ScriptOutput'.+outputAddress :: Network -> ScriptOutput -> Either String Address+outputAddress net s =+ case s of+ PayPKHash h -> Right $ p2pkhAddr net h+ PayScriptHash h -> Right $ p2shAddr net h+ PayPK k -> Right $ pubKeyAddr net k+ PayWitnessPKHash h ->+ maybeToEither "outputAddress: segwit not supported in this network" $+ p2wpkhAddr net h+ PayWitnessScriptHash h ->+ maybeToEither "outputAddress: segwit not supported in this network" $+ p2wshAddr net h+ _ -> Left "outputAddress: bad output script type"++-- | Infer the address of a 'ScriptInput'+inputAddress :: Network -> ScriptInput -> Either String Address+inputAddress net s = case s of+ RegularInput (SpendPKHash _ key) -> return $ pubKeyAddr net key+ ScriptHashInput _ rdm -> return $ payToScriptAddress net rdm+ _ -> Left "inputAddress: bad input script type" -- | Decode private key from WIF (wallet import format) string. fromWif :: Network -> Base58 -> Maybe SecKeyI
src/Network/Haskoin/Constants.hs view
@@ -28,6 +28,7 @@ import Data.ByteString (ByteString) import Data.List import Data.Maybe+import Data.Serialize import Data.String import Data.Text (Text) import Data.Version@@ -106,6 +107,15 @@ -- | Replace-By-Fee (BIP-125) , getReplaceByFee :: !Bool } deriving (Eq, Generic)++instance Serialize Network where+ put net =+ putWord32be $ getNetworkMagic net+ get = do+ magic <- getWord32be+ case find ((== magic) . getNetworkMagic) allNets of+ Nothing -> fail $ "Network magic unknown: " <> show magic+ Just net -> return net instance NFData Network
src/Network/Haskoin/Script/Standard.hs view
@@ -11,29 +11,20 @@ pay-to-script-hash, pay-to-multisig and corresponding SegWit variants. -} module Network.Haskoin.Script.Standard-( ScriptInput(..)-, SimpleInput(..)-, RedeemScript-, inputAddress-, outputAddress-, encodeInput-, encodeInputBS-, decodeInput-, decodeInputBS-, addressToScript-, addressToScriptBS-, addressToOutput-, payToScriptAddress-, payToWitnessScriptAddress-, scriptToAddress-, scriptToAddressBS-, sortMulSig-, scriptOpToInt-, isSpendPK-, isSpendPKHash-, isSpendMulSig-, isScriptHashInput-) where+ ( ScriptInput(..)+ , SimpleInput(..)+ , RedeemScript+ , encodeInput+ , encodeInputBS+ , decodeInput+ , decodeInputBS+ , sortMulSig+ , scriptOpToInt+ , isSpendPK+ , isSpendPKHash+ , isSpendMulSig+ , isScriptHashInput+ ) where import Control.Applicative ((<|>)) import Control.DeepSeq (NFData, rnf)@@ -42,9 +33,7 @@ import Data.Function (on) import Data.List (sortBy) import Data.Serialize (decode, encode)-import Network.Haskoin.Address import Network.Haskoin.Constants-import Network.Haskoin.Crypto.Hash import Network.Haskoin.Keys.Common import Network.Haskoin.Script.Common import Network.Haskoin.Script.SigHash@@ -120,63 +109,6 @@ instance NFData ScriptInput where rnf (RegularInput i) = rnf i rnf (ScriptHashInput i o) = rnf i `seq` rnf o---- | Compute a pay-to-script-hash address for an output script.-payToScriptAddress :: Network -> ScriptOutput -> Address-payToScriptAddress net out = p2shAddr net (addressHash (encodeOutputBS out))---- | Compute a pay-to-witness-script-hash address for an output script. Only on--- SegWit networks.-payToWitnessScriptAddress :: Network -> ScriptOutput -> Maybe Address-payToWitnessScriptAddress net out = p2wshAddr net (sha256 (encodeOutputBS out))---- | Encode an output script from an address. Will fail if using a--- pay-to-witness address on a non-SegWit network.-addressToOutput :: Address -> ScriptOutput-addressToOutput a- | isPubKeyAddress a = PayPKHash (getAddrHash160 a)- | isScriptAddress a = PayScriptHash (getAddrHash160 a)- | isWitnessPubKeyAddress a = PayWitnessPKHash (getAddrHash160 a)- | isWitnessScriptAddress a = PayWitnessScriptHash (getAddrHash256 a)- | otherwise = undefined---- | Get output script AST for an 'Address'.-addressToScript :: Address -> Script-addressToScript = encodeOutput . addressToOutput---- | Encode address as output script in 'ByteString' form.-addressToScriptBS :: Address -> ByteString-addressToScriptBS = encode . addressToScript---- | Decode an output script into an 'Address' if it has such representation.-scriptToAddress :: Network -> Script -> Maybe Address-scriptToAddress net = eitherToMaybe . (outputAddress net <=< decodeOutput)---- | Decode a serialized script into an 'Address'.-scriptToAddressBS :: Network -> ByteString -> Maybe Address-scriptToAddressBS net = eitherToMaybe . (outputAddress net <=< decodeOutputBS)---- | Get the 'Address' of a 'ScriptOutput'.-outputAddress :: Network -> ScriptOutput -> Either String Address-outputAddress net s =- case s of- PayPKHash h -> Right $ p2pkhAddr net h- PayScriptHash h -> Right $ p2shAddr net h- PayPK k -> Right $ pubKeyAddr net k- PayWitnessPKHash h ->- maybeToEither "outputAddress: segwit not supported in this network" $- p2wpkhAddr net h- PayWitnessScriptHash h ->- maybeToEither "outputAddress: segwit not supported in this network" $- p2wshAddr net h- _ -> Left "outputAddress: bad output script type"---- | Infer the address of a 'ScriptInput'-inputAddress :: Network -> ScriptInput -> Either String Address-inputAddress net s = case s of- RegularInput (SpendPKHash _ key) -> return $ pubKeyAddr net key- ScriptHashInput _ rdm -> return $ payToScriptAddress net rdm- _ -> Left "inputAddress: bad input script type" -- | Heuristic to decode an input script into one of the standard types. decodeSimpleInput :: Network -> Script -> Either String SimpleInput