packages feed

bitcoin-payment-channel-0.1.0.0: src/Data/Bitcoin/PaymentChannel/Internal/Script.hs

-- {-# OPTIONS_GHC -fwarn-incomplete-patterns -Werror #-}

module Data.Bitcoin.PaymentChannel.Internal.Script where

import Data.Bitcoin.PaymentChannel.Internal.Types
import Data.Bitcoin.PaymentChannel.Internal.Util

import qualified  Network.Haskoin.Internals as HI
import qualified  Network.Haskoin.Util as HU
import qualified  Network.Haskoin.Crypto as HC
import Network.Haskoin.Script

import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as C
import qualified Data.ByteString.Lazy as BL
import qualified Data.Binary as Bin
import Data.Word
import Data.Char as CH

valReceiverSigHash = SigAll True

getSigHashFlag :: BitcoinAmount -> SigHash
getSigHashFlag valueToSender =
    if valueToSender == 0 then
        SigNone True
    else
        SigSingle True

sigHashToByte :: SigHash -> Word8
sigHashToByte = fromIntegral . ord . head . C.unpack . serialize

-- |Generates OP_CHECKLOCKTIMEVERIFY redeemScript
paymentChannelRedeemScript :: HC.PubKey -> HC.PubKey -> Word32 -> Script
paymentChannelRedeemScript clientPK serverPK lockTime = Script
     [OP_IF,
         opPushData (serialize serverPK), OP_CHECKSIGVERIFY,
     OP_ELSE,
         encodeScriptInt lockTime, op_CHECKLOCKTIMEVERIFY, OP_DROP,
     OP_ENDIF,
     opPushData (serialize clientPK), OP_CHECKSIG]
         where encodeScriptInt i = opPushData $ B.pack $ HI.encodeInt (fromIntegral i)
            -- Note: HI.encodeInt encodes values up to and including 2^31-1 as 4 bytes
            --      and values 2^31 through 2^32-1 (upper limit) as 5 bytes.

-- |scriptSig fulfilling a payment channel redeemScript
paymentTxScriptSig :: PaymentSignature -> PaymentSignature -> Script --ScriptSig
paymentTxScriptSig clientSig serverSig = Script
    [opPushData $ serialize clientSig, --sig including SigHash byte
    opPushData $ serialize serverSig, --sig including SigHash byte
    OP_1]

-- |scriptSig used for the valueSender refund transaction
refundTxScriptSig :: HC.Signature -> Script
refundTxScriptSig clientSig = Script
    [opPushData (B.append (serialize clientSig) hashTypeByte),
    OP_0]
        where hashTypeByte = serialize (SigAll False)

-----Util-----

op_CHECKLOCKTIMEVERIFY = OP_NOP2

scriptToP2SHAddress :: Script -> HC.Address
scriptToP2SHAddress = HC.ScriptAddress . HC.hash160 . HC.getHash256 . HC.hash256 . serialize


getP2SHFundingAddress :: ChannelParameters -> HC.Address
getP2SHFundingAddress = scriptToP2SHAddress . getRedeemScript

getRedeemScript :: ChannelParameters -> Script --RedeemScript
getRedeemScript (CChannelParameters senderPK recvrPK lockTime) =
    paymentChannelRedeemScript senderPK recvrPK (toWord32 lockTime)

getRedeemScriptBS :: ChannelParameters -> B.ByteString
getRedeemScriptBS = serialize . getRedeemScript

getInputScript :: ChannelParameters -> Script -> Script
getInputScript cp scriptSig =
    Script $ scriptOps scriptSig ++ redeemScript
        where
             redeemScript = [opPushData $ getRedeemScriptBS cp]