lnwallet: update the witness generation funcs for sender's HTLC output

This commit updates all the spendHtlcSpend* functions which are used to
spend each of the possible clauses within the HTLC contract placed on
the sender’s commitment transaction.
This commit is contained in:
Olaoluwa Osuntokun 2017-07-29 18:03:56 -07:00
parent 8f5129e08f
commit d697c6ca9a
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
1 changed files with 44 additions and 68 deletions

View File

@ -270,32 +270,29 @@ func senderHTLCScript(senderKey, receiverKey, revocationKey *btcec.PublicKey,
} }
// senderHtlcSpendRevoke constructs a valid witness allowing the receiver of an // senderHtlcSpendRevoke constructs a valid witness allowing the receiver of an
// HTLC to claim the output with knowledge of the revocation preimage in the // HTLC to claim the output with knowledge of the revocation private key in the
// scenario that the sender of the HTLC broadcasts a previously revoked // scenario that the sender of the HTLC broadcasts a previously revoked
// commitment transaction. A valid spend requires knowledge of the preimage to // commitment transaction. A valid spend requires knowledge of the private key
// the commitment transaction's revocation hash, and a valid signature under // that corresponds to their revocation base point and also the private key fro
// the receiver's public key. // the per commitment point, and a valid signature under the combined public
func senderHtlcSpendRevoke(commitScript []byte, outputAmt btcutil.Amount, // key.
reciverKey *btcec.PrivateKey, sweepTx *wire.MsgTx, func senderHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
revokePreimage []byte) (wire.TxWitness, error) { revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) {
hashCache := txscript.NewTxSigHashes(sweepTx) sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
sweepSig, err := txscript.RawTxInWitnessSignature(
sweepTx, hashCache, 0, int64(outputAmt), commitScript,
txscript.SigHashAll, reciverKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// In order to force script execution to enter the revocation clause, // The stack required to sweep a revoke HTLC output consists simply of
// we place two one's as the first items in the final evaluated witness // the exact witness stack as one of a regular p2wkh spend. The only
// stack. // difference is that the keys used were derived in an adversarial
witnessStack := wire.TxWitness(make([][]byte, 5)) // manner in order to encode the revocation contract into a sig+key
witnessStack[0] = sweepSig // pair.
witnessStack[1] = revokePreimage witnessStack := wire.TxWitness(make([][]byte, 3))
witnessStack[2] = []byte{1} witnessStack[0] = append(sweepSig, byte(txscript.SigHashAll))
witnessStack[3] = []byte{1} witnessStack[1] = revokeKey.SerializeCompressed()
witnessStack[4] = commitScript witnessStack[2] = signDesc.WitnessScript
return witnessStack, nil return witnessStack, nil
} }
@ -303,70 +300,49 @@ func senderHtlcSpendRevoke(commitScript []byte, outputAmt btcutil.Amount,
// senderHtlcSpendRedeem constructs a valid witness allowing the receiver of an // senderHtlcSpendRedeem constructs a valid witness allowing the receiver of an
// HTLC to redeem the pending output in the scenario that the sender broadcasts // HTLC to redeem the pending output in the scenario that the sender broadcasts
// their version of the commitment transaction. A valid spend requires // their version of the commitment transaction. A valid spend requires
// knowledge of the payment preimage, and a valid signature under the // knowledge of the payment preimage, and a valid signature under the receivers
// receivers public key. // public key.
func senderHtlcSpendRedeem(commitScript []byte, outputAmt btcutil.Amount, func senderHtlcSpendRedeem(signer Signer, signDesc *SignDescriptor,
reciverKey *btcec.PrivateKey, sweepTx *wire.MsgTx, sweepTx *wire.MsgTx, paymentPreimage []byte) (wire.TxWitness, error) {
paymentPreimage []byte) (wire.TxWitness, error) {
hashCache := txscript.NewTxSigHashes(sweepTx) sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
sweepSig, err := txscript.RawTxInWitnessSignature(
sweepTx, hashCache, 0, int64(outputAmt), commitScript,
txscript.SigHashAll, reciverKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// We force script execution into the HTLC redemption clause by placing // The stack require to spend this output is simply the signature
// a one, then a zero as the first items in the final evaluated // generated above under the receiver's public key, and the payment
// witness stack. // pre-image.
witnessStack := wire.TxWitness(make([][]byte, 5)) witnessStack := wire.TxWitness(make([][]byte, 3))
witnessStack[0] = sweepSig witnessStack[0] = append(sweepSig, byte(txscript.SigHashAll))
witnessStack[1] = paymentPreimage witnessStack[1] = paymentPreimage
witnessStack[2] = nil witnessStack[2] = signDesc.WitnessScript
witnessStack[3] = []byte{1}
witnessStack[4] = commitScript
return witnessStack, nil return witnessStack, nil
} }
// htlcSpendTimeout constructs a valid witness allowing the sender of an HTLC // senderHtlcSpendTimeout constructs a valid witness allowing the sender of an
// to recover the pending funds after an absolute, then relative locktime // HTLC to activate the time locked covenant clause of a soon to be expired
// period. // HTLC. This script simply spends the multi-sig output using the
func senderHtlcSpendTimeout(commitScript []byte, outputAmt btcutil.Amount, // pre-generated HTLC timeout transaction.
senderKey *btcec.PrivateKey, sweepTx *wire.MsgTx, func senderHtlcSpendTimeout(reciverSig []byte, signer Signer,
absoluteTimeout, relativeTimeout uint32) (wire.TxWitness, error) { signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) (wire.TxWitness, error) {
// Since the HTLC output has an absolute timeout before we're permitted sweepSig, err := signer.SignOutputRaw(htlcTimeoutTx, signDesc)
// to sweep the output, we need to set the locktime of this sweeping
// transaction to that absolute value in order to pass Script
// verification.
sweepTx.LockTime = absoluteTimeout
// Additionally, we're required to wait a relative period of time
// before we can sweep the output in order to allow the other party to
// contest our claim of validity to this version of the commitment
// transaction.
sweepTx.TxIn[0].Sequence = lockTimeToSequence(false, relativeTimeout)
// Finally, OP_CSV requires that the version of the transaction
// spending a pkscript with OP_CSV within it *must* be >= 2.
sweepTx.Version = 2
hashCache := txscript.NewTxSigHashes(sweepTx)
sweepSig, err := txscript.RawTxInWitnessSignature(
sweepTx, hashCache, 0, int64(outputAmt), commitScript,
txscript.SigHashAll, senderKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// We place a zero as the first item of the evaluated witness stack in // We place a zero as the first item of the evaluated witness stack in
// order to force Script execution to the HTLC timeout clause. // order to force Script execution to the HTLC timeout clause. The
witnessStack := wire.TxWitness(make([][]byte, 3)) // second zero is require to consume the extra pop due to a bug in the
witnessStack[0] = sweepSig // original OP_CHECKMULTISIG.
witnessStack[1] = nil witnessStack := wire.TxWitness(make([][]byte, 5))
witnessStack[2] = commitScript witnessStack[0] = nil
witnessStack[1] = append(reciverSig, byte(txscript.SigHashAll))
witnessStack[2] = append(sweepSig, byte(txscript.SigHashAll))
witnessStack[3] = nil
witnessStack[4] = signDesc.WitnessScript
return witnessStack, nil return witnessStack, nil
} }