module Data.Bitcoin.PaymentChannel.Internal.Payment where
import Data.Bitcoin.PaymentChannel.Internal.Types
import Data.Bitcoin.PaymentChannel.Internal.State
import Data.Bitcoin.PaymentChannel.Internal.Script
import Data.Bitcoin.PaymentChannel.Internal.Util
import Data.Bitcoin.PaymentChannel.Internal.Error
import qualified Network.Haskoin.Transaction as HT
import qualified Network.Haskoin.Internals as HI
import qualified Network.Haskoin.Crypto as HC
import qualified Network.Haskoin.Script as HS
import Data.Word (Word32, Word64, Word8)
import Data.Maybe (fromJust, isJust)
import qualified Data.ByteString as B
buildEmptyPaymentTx :: FundingTxInfo -> HT.Tx
buildEmptyPaymentTx (CFundingTxInfo hash idx _) =
HT.Tx 1
[HT.TxIn
(HT.OutPoint hash idx)
B.empty
maxBound]
[]
0
paymentTxAddOutput :: HT.TxOut -> HT.Tx -> (HT.Tx, HS.SigHash)
paymentTxAddOutput addOut tx@(HT.Tx _ _ outs _)
| HT.outValue addOut >= fromIntegral dUST_LIMIT =
(tx { HT.txOut = outs ++ [addOut] }, HS.SigSingle True)
| otherwise =
(tx, HS.SigNone True)
getPaymentTxForSigning ::
PaymentChannelState
-> BitcoinAmount
-> (HT.Tx, HS.SigHash)
getPaymentTxForSigning st@(CPaymentChannelState _ fti
(CPaymentTxConfig sendAddr) chanValLeft _) newValueLeft =
paymentTxAddOutput senderOut $ buildEmptyPaymentTx fti
where senderOut = HT.TxOut (fromIntegral . toInteger $ newValueLeft) (addressToScriptPubKeyBS sendAddr)
getPaymentTxHashForSigning ::
PaymentChannelState
-> BitcoinAmount
-> (HC.Hash256, HS.SigHash)
getPaymentTxHashForSigning st@(CPaymentChannelState cp _ _ _ _) newValueLeft =
(HS.txSigHash tx (getRedeemScript cp) 0 sigHash, sigHash)
where (tx,sigHash) = getPaymentTxForSigning st newValueLeft
verifyPaymentSig ::
PaymentChannelState
-> Payment
-> (HC.Hash256 -> SendPubKey -> HC.Signature -> Bool)
-> Bool
verifyPaymentSig pcs
(CPayment newSenderVal (CPaymentSignature sig sigHash)) verifyFunc =
let (hash,_) = case sigHash of
HS.SigSingle True -> getPaymentTxHashForSigning pcs newSenderVal
HS.SigNone True -> getPaymentTxHashForSigning pcs 0
unknownSigHash -> (dummyHash256,sigHash)
in
verifyFunc hash (pcsClientPubKey pcs) sig
createPayment ::
PaymentChannelState
-> BitcoinAmount
-> (HC.Hash256 -> HC.Signature)
-> Payment
createPayment pcs@(CPaymentChannelState _ _ _ currSenderVal _)
newSenderVal signFunc =
let
(hash,sigHash) = getPaymentTxHashForSigning pcs newSenderVal
sig = signFunc hash
pSig = CPaymentSignature sig sigHash
in
case sigHash of
HS.SigSingle _ -> CPayment newSenderVal pSig
HS.SigNone _ -> CPayment 0 pSig
_ -> error
"BUG: unsupported SigHash created by 'getPaymentTxHashForSigning'"