module Data.Bitcoin.PaymentChannel.Internal.State where
import Data.Bitcoin.PaymentChannel.Internal.Types
import Data.Bitcoin.PaymentChannel.Internal.Error
import Data.Bitcoin.PaymentChannel.Internal.Util (addressToScriptPubKeyBS)
import Data.Bitcoin.PaymentChannel.Internal.Bitcoin.Script
import qualified Network.Haskoin.Transaction as HT
import qualified Network.Haskoin.Crypto as HC
import qualified Network.Haskoin.Script as HS
pcsChannelTotalValue = ftiOutValue . pcsFundingTxInfo
pcsValueTransferred cs = pcsChannelTotalValue cs pcsClientChangeVal cs
pcsChannelValueLeft = pcsClientChangeVal
pcsClientPubKey = cpSenderPubKey . pcsParameters
pcsServerPubKey = cpReceiverPubKey . pcsParameters
pcsDustLimit = cpDustLimit . pcsParameters
pcsExpirationDate = cpLockTime . pcsParameters
pcsClientChangeAddress = ptcSenderChangeAddress . pcsPaymentConfig
pcsClientChangeScriptPubKey = addressToScriptPubKeyBS . pcsClientChangeAddress
pcsLockTime = cpLockTime . pcsParameters
pcsPrevOut (CPaymentChannelState _ (CFundingTxInfo h i _) _ _ _) = OutPoint h i
pcsChannelID :: PaymentChannelState -> HT.OutPoint
pcsChannelID pcs = HT.OutPoint (ftiHash fti) (ftiOutIndex fti)
where fti = pcsFundingTxInfo pcs
pcsGetPayment :: PaymentChannelState -> Payment
pcsGetPayment (CPaymentChannelState _ _ _ val sig) = CPayment val sig
setClientChangeAddress :: PaymentChannelState -> HC.Address -> PaymentChannelState
setClientChangeAddress pcs@(CPaymentChannelState _ _ pConf _ _) addr =
pcs { pcsPaymentConfig = newPayConf }
where newPayConf = pConf { ptcSenderChangeAddress = addr }
setFundingSource :: PaymentChannelState -> FundingTxInfo -> PaymentChannelState
setFundingSource pcs fti =
pcs { pcsFundingTxInfo = fti }
channelValueLeft :: PaymentChannelState -> BitcoinAmount
channelValueLeft pcs@(CPaymentChannelState (CChannelParameters _ _ _ dustLimit) _ _ _ _) =
pcsClientChangeVal pcs dustLimit
channelIsExhausted :: PaymentChannelState -> Bool
channelIsExhausted pcs =
psSigHash (pcsPaymentSignature pcs) == HS.SigNone True ||
channelValueLeft pcs == 0
newPaymentChannelState channelParameters fundingTxInfo paymentConfig paySig =
CPaymentChannelState {
pcsParameters = channelParameters,
pcsFundingTxInfo = fundingTxInfo,
pcsPaymentConfig = paymentConfig,
pcsClientChangeVal = ftiOutValue fundingTxInfo,
pcsPaymentSignature = paySig
}
updatePaymentChannelState ::
PaymentChannelState
-> FullPayment
-> Either PayChanError PaymentChannelState
updatePaymentChannelState (CPaymentChannelState cp fun@(CFundingTxInfo h i _)
pconf@(CPaymentTxConfig addr) oldSenderVal _)
(CFullPayment payment@(CPayment newSenderVal _) payOP payScript payChgAddr)
| (HT.outPointHash payOP /= h) || (HT.outPointIndex payOP /= i) =
Left $ OutPointMismatch $ OutPoint h i
| payChgAddr /= addr =
Left $ ChangeAddrMismatch addr
| payScript /= getRedeemScript cp =
Left $ RedeemScriptMismatch $ getRedeemScript cp
| newSenderVal <= oldSenderVal =
CPaymentChannelState cp fun pconf newSenderVal . cpSignature <$>
checkDustLimit cp payment
| otherwise = Left $ BadPaymentValue (newSenderVal oldSenderVal)
checkDustLimit :: ChannelParameters -> Payment -> Either PayChanError Payment
checkDustLimit (CChannelParameters _ _ _ dustLimit) payment@(CPayment senderChangeVal _)
| senderChangeVal < dustLimit =
Left $ DustOutput dustLimit
| otherwise = Right payment