bitcoin-payment-channel-0.6.0.0: src/Data/Bitcoin/PaymentChannel/Internal/Settlement.hs
module Data.Bitcoin.PaymentChannel.Internal.Settlement
(
createSignedSettlementTx
, signedSettlementTxFromState
)
where
import Data.Bitcoin.PaymentChannel.Internal.Types
import Data.Bitcoin.PaymentChannel.Internal.Payment
import Data.Bitcoin.PaymentChannel.Internal.Bitcoin.Script
import Data.Bitcoin.PaymentChannel.Internal.Bitcoin.Util
import Data.Bitcoin.PaymentChannel.Internal.Util
import Data.Bitcoin.PaymentChannel.Internal.Bitcoin.Fee
import qualified Network.Haskoin.Transaction as HT
import qualified Network.Haskoin.Crypto as HC
import qualified Network.Haskoin.Script as HS
-- |Sign everything, and do not allow additional inputs to be added afterwards.
serverSigHash = HS.SigAll False
toUnsignedSettlementTx :: ClientSignedPayment -> HC.Address -> BitcoinAmount -> HT.Tx
toUnsignedSettlementTx
(ClientSignedPayment
unsignedPayment@(UnsignedPayment _ valueAvailable _ _ senderVal)
(CPaymentSignature _ sigHash) ) recvAddr txFee =
let
baseTx = toUnsignedBitcoinTx unsignedPayment
adjustedTx = if sigHash == HS.SigNone True then removeOutputs baseTx else baseTx
-- TODO: check dust?
receiverAmount = valueAvailable - senderVal - txFee
recvOut = HT.TxOut
(fromIntegral . toInteger $ receiverAmount)
(addressToScriptPubKeyBS recvAddr)
in
appendOutput adjustedTx recvOut
getSettlementTxHashForSigning
:: ClientSignedPayment
-> ChannelParameters
-> HC.Address -- ^Receiver destination address
-> BitcoinAmount -- ^Bitcoin transaction fee
-> HC.Hash256
getSettlementTxHashForSigning csPayment cp recvAddr txFee =
HS.txSigHash tx (getRedeemScript cp) 0 serverSigHash
where tx = toUnsignedSettlementTx csPayment recvAddr txFee
getSignedSettlementTx
:: ClientSignedPayment
-> ChannelParameters
-> HC.Address -- ^Receiver/server funds destination address
-> (HC.Hash256 -> HC.Signature) -- ^ Server/receiver's signing function. Produces a signature which verifies against 'cpReceiverPubKey'
-> BitcoinAmount -- ^Bitcoin tx fee
-> HT.Tx
getSignedSettlementTx csPayment@(ClientSignedPayment _ clientSig)
cp recvAddr signFunc txFee =
let
rawServerSig = signFunc $ getSettlementTxHashForSigning csPayment cp recvAddr txFee
unsignedTx = toUnsignedSettlementTx csPayment recvAddr txFee
serverSig = CPaymentSignature rawServerSig serverSigHash
inputScript = getP2SHInputScript cp $ paymentTxScriptSig clientSig serverSig
in
replaceScriptInput 0 (serialize inputScript) unsignedTx
createSignedSettlementTx
:: HasFee fee
=> ClientSignedPayment
-> ChannelParameters
-> HC.Address -- ^Receiver/server funds destination address
-> (HC.Hash256 -> HC.Signature) -- ^Server/receiver's signing function. Produces a signature which verifies against 'cpReceiverPubKey'
-> fee -- ^Bitcoin tx fee
-> HT.Tx
createSignedSettlementTx csp cp addr signFunc fee =
getSignedSettlementTx csp cp addr signFunc (absoluteFee (calcTxSize zeroFeeTx) fee)
where
zeroFeeTx = getSignedSettlementTx csp cp addr signFunc (0 :: BitcoinAmount)
signedSettlementTxFromState
:: HasFee fee
=> PaymentChannelState
-> HC.Address -- ^Receiver/server funds destination address
-> (HC.Hash256 -> HC.Signature) -- ^ Server/receiver's signing function. Produces a signature which verifies against 'cpReceiverPubKey'
-> fee -- ^Bitcoin tx fee
-> HT.Tx
signedSettlementTxFromState cs@(CPaymentChannelState _ cp _ _ _ _ _) =
createSignedSettlementTx (cPaymentFromState cs) cp
cPaymentFromState :: PaymentChannelState -> ClientSignedPayment
cPaymentFromState cs@(CPaymentChannelState _ _ _ _ _ _ clientSig) =
ClientSignedPayment (fromState cs) clientSig