bitcoin-scripting-0.3.0: src/Language/Bitcoin/Script/Descriptors/Syntax.hs
module Language.Bitcoin.Script.Descriptors.Syntax (
OutputDescriptor (..),
ScriptDescriptor (..),
KeyDescriptor (..),
isDefinite,
keyDescPubKey,
keyBytes,
Origin (..),
Key (..),
KeyCollection (..),
pubKey,
secKey,
) where
import Data.ByteString (ByteString)
import Haskoin (
Address,
DerivPath,
Fingerprint,
PubKeyI (..),
SecKeyI,
XPubKey (xPubKey),
derivePubKeyI,
derivePubPath,
exportPubKey,
toSoft,
)
-- | High level description for a bitcoin output
data OutputDescriptor
= -- | The output is secured by the given script.
ScriptPubKey ScriptDescriptor
| -- | P2SH embed the argument.
P2SH ScriptDescriptor
| -- | P2WPKH output for the given compressed pubkey.
P2WPKH KeyDescriptor
| -- | P2WSH embed the argument.
P2WSH ScriptDescriptor
| -- | P2SH-P2WPKH the given compressed pubkey.
WrappedWPkh KeyDescriptor
| -- | P2SH-P2WSH the given script
WrappedWSh ScriptDescriptor
| -- | An alias for the collection of pk(KEY) and pkh(KEY). If the key is
-- compressed, it also includes wpkh(KEY) and sh(wpkh(KEY)).
Combo KeyDescriptor
| -- | The script which ADDR expands to.
Addr Address
deriving (Eq, Show)
-- | High level description of a bitcoin script
data ScriptDescriptor
= -- | Require a signature for this key
Pk KeyDescriptor
| -- | Require a key matching this hash and a signature for that key
Pkh KeyDescriptor
| -- | k-of-n multisig script.
Multi Int [KeyDescriptor]
| -- | k-of-n multisig script with keys sorted lexicographically in the resulting script.
SortedMulti Int [KeyDescriptor]
| -- | the script whose hex encoding is HEX.
Raw ByteString
deriving (Eq, Show)
data KeyDescriptor = KeyDescriptor
{ origin :: Maybe Origin
, keyDef :: Key
}
deriving (Eq, Show)
data Origin = Origin
{ fingerprint :: Fingerprint
, derivation :: DerivPath
}
deriving (Eq, Ord, Show)
data Key
= -- | DER-hex encoded secp256k1 public key
Pubkey PubKeyI
| -- | (de)serialized as WIF
SecretKey SecKeyI
| XPub XPubKey DerivPath KeyCollection
deriving (Eq, Show)
-- | Simple explicit public key with no origin information
pubKey :: PubKeyI -> KeyDescriptor
pubKey = KeyDescriptor Nothing . Pubkey
-- | Simple explicit secret key with no origin information
secKey :: SecKeyI -> KeyDescriptor
secKey = KeyDescriptor Nothing . SecretKey
-- | Represent whether the key corresponds to a collection (and how) or a single key.
data KeyCollection
= Single
| -- | immediate hardened children
HardKeys
| -- | immediate non-hardened children
SoftKeys
deriving (Eq, Ord, Show)
-- | Produce a key literal if possible
keyBytes :: KeyDescriptor -> Maybe ByteString
keyBytes = fmap toBytes . keyDescPubKey
where
toBytes (PubKeyI pk c) = exportPubKey c pk
-- | Produce a pubkey if possible
keyDescPubKey :: KeyDescriptor -> Maybe PubKeyI
keyDescPubKey (KeyDescriptor _ k) = case k of
Pubkey pk -> Just pk
SecretKey sk -> Just $ derivePubKeyI sk
XPub xpub path Single -> (`PubKeyI` True) . xPubKey . (`derivePubPath` xpub) <$> toSoft path
_ -> Nothing
-- | Test whether the key descriptor corresponds to a single key
isDefinite :: KeyDescriptor -> Bool
isDefinite (KeyDescriptor _ k) = case k of
XPub _ _ HardKeys -> False
XPub _ _ SoftKeys -> False
_ -> True