lnwallet: make second level sigs using sighash single|anyonecanpay

This commit is contained in:
Johan T. Halseth 2020-03-06 16:11:47 +01:00
parent d1089fb449
commit bddd3e128c
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26
5 changed files with 82 additions and 34 deletions

View File

@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/input"
@ -144,7 +145,8 @@ func TestHtlcTimeoutResolver(t *testing.T) {
timeout: true,
txToBroadcast: func() (*wire.MsgTx, error) {
witness, err := input.SenderHtlcSpendTimeout(
nil, signer, fakeSignDesc, sweepTx,
nil, txscript.SigHashAll, signer,
fakeSignDesc, sweepTx,
)
if err != nil {
return nil, err
@ -163,7 +165,8 @@ func TestHtlcTimeoutResolver(t *testing.T) {
timeout: false,
txToBroadcast: func() (*wire.MsgTx, error) {
witness, err := input.ReceiverHtlcSpendRedeem(
nil, fakePreimageBytes, signer,
nil, txscript.SigHashAll,
fakePreimageBytes, signer,
fakeSignDesc, sweepTx,
)
if err != nil {

View File

@ -343,8 +343,10 @@ func SenderHtlcSpendRedeem(signer Signer, signDesc *SignDescriptor,
// HTLC to activate the time locked covenant clause of a soon to be expired
// HTLC. This script simply spends the multi-sig output using the
// pre-generated HTLC timeout transaction.
func SenderHtlcSpendTimeout(receiverSig []byte, signer Signer,
signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) (wire.TxWitness, error) {
func SenderHtlcSpendTimeout(receiverSig []byte,
receiverSigHash txscript.SigHashType, signer Signer,
signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) (
wire.TxWitness, error) {
sweepSig, err := signer.SignOutputRaw(htlcTimeoutTx, signDesc)
if err != nil {
@ -357,7 +359,7 @@ func SenderHtlcSpendTimeout(receiverSig []byte, signer Signer,
// original OP_CHECKMULTISIG.
witnessStack := wire.TxWitness(make([][]byte, 5))
witnessStack[0] = nil
witnessStack[1] = append(receiverSig, byte(txscript.SigHashAll))
witnessStack[1] = append(receiverSig, byte(receiverSigHash))
witnessStack[2] = append(sweepSig, byte(signDesc.HashType))
witnessStack[3] = nil
witnessStack[4] = signDesc.WitnessScript
@ -506,9 +508,10 @@ func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
// signed has a relative timelock delay enforced by its sequence number. This
// delay give the sender of the HTLC enough time to revoke the output if this
// is a breach commitment transaction.
func ReceiverHtlcSpendRedeem(senderSig, paymentPreimage []byte,
signer Signer, signDesc *SignDescriptor,
htlcSuccessTx *wire.MsgTx) (wire.TxWitness, error) {
func ReceiverHtlcSpendRedeem(senderSig []byte,
senderSigHash txscript.SigHashType, paymentPreimage []byte,
signer Signer, signDesc *SignDescriptor, htlcSuccessTx *wire.MsgTx) (
wire.TxWitness, error) {
// First, we'll generate a signature for the HTLC success transaction.
// The signDesc should be signing with the public key used as the
@ -524,7 +527,7 @@ func ReceiverHtlcSpendRedeem(senderSig, paymentPreimage []byte,
// order to consume the extra pop within OP_CHECKMULTISIG.
witnessStack := wire.TxWitness(make([][]byte, 5))
witnessStack[0] = nil
witnessStack[1] = append(senderSig, byte(txscript.SigHashAll))
witnessStack[1] = append(senderSig, byte(senderSigHash))
witnessStack[2] = append(sweepSig, byte(signDesc.HashType))
witnessStack[3] = paymentPreimage
witnessStack[4] = signDesc.WitnessScript

View File

@ -227,6 +227,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
sweepTxSigHashes *txscript.TxSigHashes
senderCommitTx, sweepTx *wire.MsgTx
bobRecvrSig []byte
bobSigHash txscript.SigHashType
)
// genCommitTx generates a commitment tx where the htlc output requires
@ -260,7 +261,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
}
// genSweepTx generates a sweep of the senderCommitTx, and sets the
// sequence if confirmed is true.
// sequence and sighash single|anyonecanspend if confirmed is true.
genSweepTx := func(confirmed bool) {
prevOut := &wire.OutPoint{
Hash: senderCommitTx.TxHash(),
@ -283,6 +284,11 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
sweepTxSigHashes = txscript.NewTxSigHashes(sweepTx)
bobSigHash = txscript.SigHashAll
if confirmed {
bobSigHash = txscript.SigHashSingle | txscript.SigHashAnyOneCanPay
}
// We'll also generate a signature on the sweep transaction above
// that will act as Bob's signature to Alice for the second level HTLC
// transaction.
@ -293,7 +299,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
SingleTweak: bobCommitTweak,
WitnessScript: htlcWitnessScript,
Output: htlcOutput,
HashType: txscript.SigHashAll,
HashType: bobSigHash,
SigHashes: sweepTxSigHashes,
InputIndex: 0,
}
@ -458,8 +464,10 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
InputIndex: 0,
}
return SenderHtlcSpendTimeout(bobRecvrSig, aliceSigner,
signDesc, sweepTx)
return SenderHtlcSpendTimeout(
bobRecvrSig, bobSigHash, aliceSigner,
signDesc, sweepTx,
)
}),
true,
},
@ -487,8 +495,10 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
InputIndex: 0,
}
return SenderHtlcSpendTimeout(bobRecvrSig, aliceSigner,
signDesc, sweepTx)
return SenderHtlcSpendTimeout(
bobRecvrSig, bobSigHash, aliceSigner,
signDesc, sweepTx,
)
}),
true,
},
@ -517,8 +527,10 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
InputIndex: 0,
}
return SenderHtlcSpendTimeout(bobRecvrSig, aliceSigner,
signDesc, sweepTx)
return SenderHtlcSpendTimeout(
bobRecvrSig, bobSigHash, aliceSigner,
signDesc, sweepTx,
)
}),
false,
},
@ -611,6 +623,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
receiverCommitTx, sweepTx *wire.MsgTx
sweepTxSigHashes *txscript.TxSigHashes
aliceSenderSig []byte
aliceSigHash txscript.SigHashType
)
genCommitTx := func(confirmed bool) {
@ -663,6 +676,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
)
sweepTxSigHashes = txscript.NewTxSigHashes(sweepTx)
aliceSigHash = txscript.SigHashAll
if confirmed {
aliceSigHash = txscript.SigHashSingle | txscript.SigHashAnyOneCanPay
}
// We'll also generate a signature on the sweep transaction above
// that will act as Alice's signature to Bob for the second level HTLC
// transaction.
@ -673,7 +691,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
SingleTweak: aliceCommitTweak,
WitnessScript: htlcWitnessScript,
Output: htlcOutput,
HashType: txscript.SigHashAll,
HashType: aliceSigHash,
SigHashes: sweepTxSigHashes,
InputIndex: 0,
}
@ -706,9 +724,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
InputIndex: 0,
}
return ReceiverHtlcSpendRedeem(aliceSenderSig,
return ReceiverHtlcSpendRedeem(
aliceSenderSig, aliceSigHash,
bytes.Repeat([]byte{1}, 45), bobSigner,
signDesc, sweepTx)
signDesc, sweepTx,
)
}),
false,
@ -731,9 +751,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
InputIndex: 0,
}
return ReceiverHtlcSpendRedeem(aliceSenderSig,
paymentPreimage[:], bobSigner,
signDesc, sweepTx)
return ReceiverHtlcSpendRedeem(
aliceSenderSig, aliceSigHash,
paymentPreimage, bobSigner,
signDesc, sweepTx,
)
}),
true,
},
@ -783,9 +805,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
InputIndex: 0,
}
return ReceiverHtlcSpendRedeem(aliceSenderSig,
return ReceiverHtlcSpendRedeem(
aliceSenderSig, aliceSigHash,
paymentPreimage, bobSigner,
signDesc, sweepTx)
signDesc, sweepTx,
)
}),
true,
},
@ -813,9 +837,11 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
InputIndex: 0,
}
return ReceiverHtlcSpendRedeem(aliceSenderSig,
paymentPreimage, bobSigner,
signDesc, sweepTx)
return ReceiverHtlcSpendRedeem(
aliceSenderSig, aliceSigHash,
paymentPreimage, bobSigner, signDesc,
sweepTx,
)
}),
false,
},

View File

@ -2748,6 +2748,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
txHash := remoteCommitView.txn.TxHash()
dustLimit := remoteChanCfg.DustLimit
feePerKw := remoteCommitView.feePerKw
sigHashType := HtlcSigHashType(chanType)
// With the keys generated, we'll make a slice with enough capacity to
// hold potentially all the HTLCs. The actual slice may be a bit
@ -2807,7 +2808,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
Output: &wire.TxOut{
Value: int64(htlc.Amount.ToSatoshis()),
},
HashType: txscript.SigHashAll,
HashType: sigHashType,
SigHashes: txscript.NewTxSigHashes(sigJob.Tx),
InputIndex: 0,
}
@ -2858,7 +2859,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
Output: &wire.TxOut{
Value: int64(htlc.Amount.ToSatoshis()),
},
HashType: txscript.SigHashAll,
HashType: sigHashType,
SigHashes: txscript.NewTxSigHashes(sigJob.Tx),
InputIndex: 0,
}
@ -3811,6 +3812,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
txHash := localCommitmentView.txn.TxHash()
feePerKw := localCommitmentView.feePerKw
sigHashType := HtlcSigHashType(chanType)
// With the required state generated, we'll create a slice with large
// enough capacity to hold verification jobs for all HTLC's in this
@ -3865,7 +3867,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
hashCache := txscript.NewTxSigHashes(successTx)
sigHash, err := txscript.CalcWitnessSigHash(
htlc.ourWitnessScript, hashCache,
txscript.SigHashAll, successTx, 0,
sigHashType, successTx, 0,
int64(htlc.Amount.ToSatoshis()),
)
if err != nil {
@ -3919,7 +3921,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
hashCache := txscript.NewTxSigHashes(timeoutTx)
sigHash, err := txscript.CalcWitnessSigHash(
htlc.ourWitnessScript, hashCache,
txscript.SigHashAll, timeoutTx, 0,
sigHashType, timeoutTx, 0,
int64(htlc.Amount.ToSatoshis()),
)
if err != nil {
@ -5403,8 +5405,9 @@ func newOutgoingHtlcResolution(signer input.Signer,
// With the sign desc created, we can now construct the full witness
// for the timeout transaction, and populate it as well.
sigHashType := HtlcSigHashType(chanType)
timeoutWitness, err := input.SenderHtlcSpendTimeout(
htlc.Signature, signer, &timeoutSignDesc, timeoutTx,
htlc.Signature, sigHashType, signer, &timeoutSignDesc, timeoutTx,
)
if err != nil {
return nil, err
@ -5530,8 +5533,10 @@ func newIncomingHtlcResolution(signer input.Signer,
// the success transaction. Don't specify the preimage yet. The preimage
// will be supplied by the contract resolver, either directly or when it
// becomes known.
sigHashType := HtlcSigHashType(chanType)
successWitness, err := input.ReceiverHtlcSpendRedeem(
htlc.Signature, nil, signer, &successSignDesc, successTx,
htlc.Signature, sigHashType, nil, signer, &successSignDesc,
successTx,
)
if err != nil {
return nil, err

View File

@ -5,6 +5,7 @@ import (
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/channeldb"
@ -224,6 +225,16 @@ func CommitScriptToRemote(chanType channeldb.ChannelType,
}, 0, nil
}
// HtlcSigHashType returns the sighash type to use for HTLC success and timeout
// transactions given the channel type.
func HtlcSigHashType(chanType channeldb.ChannelType) txscript.SigHashType {
if chanType.HasAnchors() {
return txscript.SigHashSingle | txscript.SigHashAnyOneCanPay
}
return txscript.SigHashAll
}
// CommitWeight returns the base commitment weight before adding HTLCs.
func CommitWeight(chanType channeldb.ChannelType) int64 {
// If this commitment has anchors, it will be slightly heavier.