private Transaction BuildHtlcTransaction(Htlc htlc) { bool incoming = htlc.Direction == Direction.Incoming; var fee = TransactionFee.CalculateFee(FeeratePerKw, incoming ? TransactionFee.HtlcSuccessWeight : TransactionFee.HtlcTimeoutWeight); var witnessScript = CreateHtlcWitnessScript(htlc); var outputScript = OutputScripts.ToLocal(CommitmentTxParams.RevocationPublicKey.ToPubKey(), CommitmentTxParams.DelayedPaymentPublicKey.ToPubKey(), ChannelParameters.ToSelfDelay); var outputIndex = _htlcOutputIndexMap[htlc]; var amount = htlc.AmountMsat.MSatToSatoshi() - fee; if (amount < ChannelParameters.DustLimitSatoshis) { throw new InvalidOperationException("HTLC amount below dust limit"); } Transaction tx = Transaction.Create(Network); TxIn txIn = new TxIn(new OutPoint(_commitmentTransaction, outputIndex)); txIn.Sequence = 0; txIn.ScriptSig = witnessScript.WitHash.ScriptPubKey; tx.Inputs.Add(txIn); TxOut txOut = new TxOut(Money.Satoshis(amount), outputScript.WitHash.ScriptPubKey); tx.Outputs.Add(txOut); tx.Version = 2; tx.LockTime = incoming ? 0 : htlc.Expiry; return(tx); }
private TxOut BuildReceivedHtlcOutput(Htlc trimmedReceivedHtlc) { PubKey localHtlcPubkey = new PubKey(CommitmentTxParams.HtlcPublicKey.PublicKeyCompressed); PubKey remoteHtlcPubkey = new PubKey(RemoteHtlcPubkey.PublicKeyCompressed); PubKey localRevocationPubkey = new PubKey(CommitmentTxParams.RevocationPublicKey.PublicKeyCompressed); Script script = OutputScripts.ReceivedHtlc(localHtlcPubkey, remoteHtlcPubkey, localRevocationPubkey, trimmedReceivedHtlc.PaymentHash, trimmedReceivedHtlc.Expiry); return(new TxOut(Money.Satoshis(trimmedReceivedHtlc.AmountMsat.MSatToSatoshi()), script.WitHash.ScriptPubKey)); }
private WitScript CreateHtlcWitnessScript(Htlc htlc, byte[] localPubKeySignature, byte[] remotePubKeySignature, Script witnessScript) { bool incoming = htlc.Direction == Direction.Incoming; return(new WitScript(new List <byte[]>() { new byte[] { 0 }, remotePubKeySignature, localPubKeySignature, incoming ? htlc.PaymentPreImage : new byte[] { 0 }, witnessScript.ToBytes() })); }
private Script CreateHtlcWitnessScript(Htlc htlc) { return(htlc.Direction == Direction.Incoming ? OutputScripts.ReceivedHtlc(CommitmentTxParams.HtlcPublicKey.ToPubKey(), RemoteHtlcPubkey.ToPubKey(), CommitmentTxParams.RevocationPublicKey.ToPubKey(), htlc.PaymentHash, htlc.Expiry) : OutputScripts.OfferedHtlc(CommitmentTxParams.HtlcPublicKey.ToPubKey(), RemoteHtlcPubkey.ToPubKey(), CommitmentTxParams.RevocationPublicKey.ToPubKey(), htlc.PaymentHash)); }
public Transaction SignHtlcTransaction(Htlc htlc, Transaction transaction, byte[] htlcRemoteSignature, Key fundingPrivateKey) { var witnessScript = CreateHtlcWitnessScript(htlc); var input = transaction.Inputs[0]; var outputIndex = _htlcOutputIndexMap[htlc]; var amount = _commitmentTransaction.Outputs[outputIndex].Value; var inputCoin = new Coin(input.PrevOut, new TxOut(Money.Satoshis(amount), input.ScriptSig)); var scriptCoin = inputCoin.ToScriptCoin(witnessScript); TransactionBuilder builder2 = new TransactionBuilder(); builder2.AddCoins(scriptCoin); builder2.AddKeys(fundingPrivateKey); var signature = transaction.SignInput(fundingPrivateKey, scriptCoin); var witScript = CreateHtlcWitnessScript(htlc, signature.ToBytes(), htlcRemoteSignature, witnessScript); transaction.Inputs[0].ScriptSig = Script.Empty; transaction.Inputs[0].WitScript = witScript; return(transaction); }