mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-02 17:52:28 +02:00
input: add scripts for new script enforced lease commitment type
The new commitment type consists of adding an additional CLTV requirement to guarantee a leased channel's expiration on any commitment and HTLC outputs that pay directly to the channel initiator.
This commit is contained in:
committed by
Olaoluwa Osuntokun
parent
564ec0fd9b
commit
b84307e62e
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// assertEngineExecution executes the VM returned by the newEngine closure,
|
||||
@@ -1184,6 +1185,452 @@ func TestSecondLevelHtlcSpends(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestLeaseSecondLevelHtlcSpends tests all the possible redemption clauses from
|
||||
// the HTLC success and timeout covenant transactions in script enforced lease
|
||||
// commitments.
|
||||
func TestLeaseSecondLevelHtlcSpends(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// We'll start be creating a creating a 2BTC HTLC.
|
||||
const htlcAmt = btcutil.Amount(2 * 10e8)
|
||||
|
||||
// In all of our scenarios, the CSV timeout to claim a self output will
|
||||
// be 5 blocks.
|
||||
const claimDelay = 5
|
||||
|
||||
// In all of our scenarios, the CLTV timelock will expire at height
|
||||
// 1337.
|
||||
const leaseExpiry = 1337
|
||||
|
||||
// First we'll set up some initial key state for Alice and Bob that
|
||||
// will be used in the scripts we created below.
|
||||
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(
|
||||
btcec.S256(), testWalletPrivKey,
|
||||
)
|
||||
bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(
|
||||
btcec.S256(), bobsPrivKey,
|
||||
)
|
||||
|
||||
revokePreimage := testHdSeed.CloneBytes()
|
||||
commitSecret, commitPoint := btcec.PrivKeyFromBytes(
|
||||
btcec.S256(), revokePreimage,
|
||||
)
|
||||
|
||||
// As we're modeling this as Bob sweeping the HTLC on-chain from his
|
||||
// commitment transaction after a period of time, we'll be using a
|
||||
// revocation key derived from Alice's base point and his secret.
|
||||
revocationKey := DeriveRevocationPubkey(aliceKeyPub, commitPoint)
|
||||
|
||||
// Next, craft a fake HTLC outpoint that we'll use to generate the
|
||||
// sweeping transaction using.
|
||||
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
||||
require.NoError(t, err)
|
||||
htlcOutPoint := &wire.OutPoint{
|
||||
Hash: *txid,
|
||||
Index: 0,
|
||||
}
|
||||
sweepTx := wire.NewMsgTx(2)
|
||||
sweepTx.AddTxIn(wire.NewTxIn(htlcOutPoint, nil, nil))
|
||||
sweepTx.AddTxOut(
|
||||
&wire.TxOut{
|
||||
PkScript: []byte("doesn't matter"),
|
||||
Value: 1 * 10e8,
|
||||
},
|
||||
)
|
||||
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
||||
|
||||
// The delay key will be crafted using Bob's public key as the output
|
||||
// we created will be spending from Alice's commitment transaction.
|
||||
delayKey := TweakPubKey(bobKeyPub, commitPoint)
|
||||
|
||||
// The commit tweak will be required in order for Bob to derive the
|
||||
// proper key need to spend the output.
|
||||
commitTweak := SingleTweakBytes(commitPoint, bobKeyPub)
|
||||
|
||||
// Finally we'll generate the HTLC script itself that we'll be spending
|
||||
// from. The revocation clause can be claimed by Alice, while Bob can
|
||||
// sweep the output after a particular delay.
|
||||
htlcWitnessScript, err := LeaseSecondLevelHtlcScript(
|
||||
revocationKey, delayKey, claimDelay, leaseExpiry,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
htlcPkScript, err := WitnessScriptHash(htlcWitnessScript)
|
||||
require.NoError(t, err)
|
||||
|
||||
htlcOutput := &wire.TxOut{
|
||||
PkScript: htlcPkScript,
|
||||
Value: int64(htlcAmt),
|
||||
}
|
||||
|
||||
// Finally, we'll create mock signers for both of them based on their
|
||||
// private keys. This test simplifies a bit and uses the same key as
|
||||
// the base point for all scripts and derivations.
|
||||
bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
||||
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
||||
|
||||
testCases := []struct {
|
||||
witness func() wire.TxWitness
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
// Sender of the HTLC attempts to activate the
|
||||
// revocation clause, but uses the wrong key (fails to
|
||||
// use the double tweak in this case).
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: aliceKeyPub,
|
||||
},
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: htlcOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return HtlcSpendRevoke(
|
||||
aliceSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
},
|
||||
{
|
||||
// Sender of HTLC activates the revocation clause.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: aliceKeyPub,
|
||||
},
|
||||
DoubleTweak: commitSecret,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: htlcOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return HtlcSpendRevoke(
|
||||
aliceSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
true,
|
||||
},
|
||||
{
|
||||
// Receiver of the HTLC attempts to sweep, but tries to
|
||||
// do so pre-maturely with a smaller CSV delay (2
|
||||
// blocks instead of 5 blocks), even after the CLTV
|
||||
// timelock expires.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = leaseExpiry
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: bobKeyPub,
|
||||
},
|
||||
SingleTweak: commitTweak,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: htlcOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return HtlcSpendSuccess(
|
||||
bobSigner, signDesc, sweepTx, claimDelay-3,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
},
|
||||
{
|
||||
// Receiver of the HTLC sweeps with the proper CSV delay
|
||||
// and after the CLTV timelock expires, but uses the
|
||||
// wrong key (leaves off the single tweak).
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = leaseExpiry
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: bobKeyPub,
|
||||
},
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: htlcOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return HtlcSpendSuccess(
|
||||
bobSigner, signDesc, sweepTx, claimDelay,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
},
|
||||
{
|
||||
// Receiver of the HTLC sweeps with the proper CSV
|
||||
// delay, and the correct key, but before the CTLV
|
||||
// timelock expires.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = 0
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: bobKeyPub,
|
||||
},
|
||||
SingleTweak: commitTweak,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: htlcOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return HtlcSpendSuccess(
|
||||
bobSigner, signDesc, sweepTx, claimDelay,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
},
|
||||
{
|
||||
// Receiver of the HTLC sweeps with the proper CSV
|
||||
// delay, and the correct key after the CTLV timelock
|
||||
// expires.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = leaseExpiry
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: bobKeyPub,
|
||||
},
|
||||
SingleTweak: commitTweak,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: htlcOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return HtlcSpendSuccess(
|
||||
bobSigner, signDesc, sweepTx, claimDelay,
|
||||
)
|
||||
}),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
sweepTx.TxIn[0].Witness = testCase.witness()
|
||||
|
||||
newEngine := func() (*txscript.Engine, error) {
|
||||
return txscript.NewEngine(htlcPkScript,
|
||||
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
||||
nil, int64(htlcAmt))
|
||||
}
|
||||
|
||||
assertEngineExecution(t, i, testCase.valid, newEngine)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLeaseCommmitSpendToSelf tests all the possible redemption clauses from
|
||||
// the to_self output in a script enforced lease commitment transaction.
|
||||
func TestLeaseCommmitSpendToSelf(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const (
|
||||
outputVal = btcutil.Amount(2 * 10e8)
|
||||
csvDelay = 5
|
||||
leaseExpiry = 1337
|
||||
)
|
||||
|
||||
// Set up some initial key state for Alice and Bob that will be used in
|
||||
// the scripts we created below.
|
||||
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(
|
||||
btcec.S256(), testWalletPrivKey,
|
||||
)
|
||||
bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(
|
||||
btcec.S256(), bobsPrivKey,
|
||||
)
|
||||
|
||||
// We'll have Bob take the revocation path in some cases.
|
||||
revokePreimage := testHdSeed.CloneBytes()
|
||||
commitSecret, commitPoint := btcec.PrivKeyFromBytes(
|
||||
btcec.S256(), revokePreimage,
|
||||
)
|
||||
revocationKey := DeriveRevocationPubkey(bobKeyPub, commitPoint)
|
||||
|
||||
// Construct the script enforced lease to_self commitment transaction
|
||||
// output.
|
||||
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
||||
require.NoError(t, err)
|
||||
commitOut := &wire.OutPoint{
|
||||
Hash: *txid,
|
||||
Index: 0,
|
||||
}
|
||||
commitScript, err := LeaseCommitScriptToSelf(
|
||||
aliceKeyPub, revocationKey, csvDelay, leaseExpiry,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
commitPkScript, err := WitnessScriptHash(commitScript)
|
||||
require.NoError(t, err)
|
||||
|
||||
commitOutput := &wire.TxOut{
|
||||
PkScript: commitPkScript,
|
||||
Value: int64(outputVal),
|
||||
}
|
||||
|
||||
sweepTx := wire.NewMsgTx(2)
|
||||
sweepTx.AddTxIn(wire.NewTxIn(commitOut, nil, nil))
|
||||
sweepTx.AddTxOut(
|
||||
&wire.TxOut{
|
||||
PkScript: []byte("doesn't matter"),
|
||||
Value: 1 * 10e8,
|
||||
},
|
||||
)
|
||||
|
||||
// Create mock signers for both parties to ensure signatures are
|
||||
// produced and verified correctly.
|
||||
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
||||
bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
||||
|
||||
testCases := []struct {
|
||||
witness func() wire.TxWitness
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
// Bob can spend with his revocation key, but not
|
||||
// without the proper tweak.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: bobKeyPub,
|
||||
},
|
||||
WitnessScript: commitScript,
|
||||
Output: commitOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return CommitSpendRevoke(
|
||||
bobSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
},
|
||||
{
|
||||
// Bob can spend with his revocation key with the proper
|
||||
// tweak.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: bobKeyPub,
|
||||
},
|
||||
DoubleTweak: commitSecret,
|
||||
WitnessScript: commitScript,
|
||||
Output: commitOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return CommitSpendRevoke(
|
||||
bobSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
true,
|
||||
},
|
||||
{
|
||||
// Alice cannot spend with the proper key before the CSV
|
||||
// delay and after the CLTV timelock has expired.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = leaseExpiry
|
||||
sweepTx.TxIn[0].Sequence = LockTimeToSequence(
|
||||
false, csvDelay/2,
|
||||
)
|
||||
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: aliceKeyPub,
|
||||
},
|
||||
DoubleTweak: commitSecret,
|
||||
WitnessScript: commitScript,
|
||||
Output: commitOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return CommitSpendTimeout(
|
||||
aliceSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
},
|
||||
{
|
||||
// Alice cannot spend with the proper key after the CSV
|
||||
// delay and before the CLTV timelock has expired.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = 0
|
||||
sweepTx.TxIn[0].Sequence = LockTimeToSequence(
|
||||
false, csvDelay,
|
||||
)
|
||||
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: aliceKeyPub,
|
||||
},
|
||||
DoubleTweak: commitSecret,
|
||||
WitnessScript: commitScript,
|
||||
Output: commitOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return CommitSpendTimeout(
|
||||
aliceSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
},
|
||||
{
|
||||
// Alice can spend with the proper key after the CSV
|
||||
// delay and CLTV timelock have expired.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = leaseExpiry
|
||||
sweepTx.TxIn[0].Sequence = LockTimeToSequence(
|
||||
false, csvDelay,
|
||||
)
|
||||
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: aliceKeyPub,
|
||||
},
|
||||
WitnessScript: commitScript,
|
||||
Output: commitOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return CommitSpendTimeout(
|
||||
aliceSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
sweepTx.TxIn[0].Witness = testCase.witness()
|
||||
|
||||
newEngine := func() (*txscript.Engine, error) {
|
||||
return txscript.NewEngine(commitPkScript,
|
||||
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
||||
nil, int64(outputVal))
|
||||
}
|
||||
|
||||
assertEngineExecution(t, i, testCase.valid, newEngine)
|
||||
}
|
||||
}
|
||||
|
||||
// TestCommitSpendToRemoteConfirmed checks that the delayed version of the
|
||||
// to_remote version can only be spent by the owner, and after one
|
||||
// confirmation.
|
||||
@@ -1291,6 +1738,148 @@ func TestCommitSpendToRemoteConfirmed(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestLeaseCommitSpendToRemoteConfirmed checks that the delayed version of the
|
||||
// to_remote version can only be spent by the owner, after one confirmation, and
|
||||
// after the lease expiration has been met.
|
||||
func TestLeaseCommitSpendToRemoteConfirmed(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const (
|
||||
outputVal = btcutil.Amount(2 * 10e8)
|
||||
leaseExpiry = 1337
|
||||
)
|
||||
|
||||
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(
|
||||
btcec.S256(), testWalletPrivKey,
|
||||
)
|
||||
|
||||
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
||||
require.NoError(t, err)
|
||||
commitOut := &wire.OutPoint{
|
||||
Hash: *txid,
|
||||
Index: 0,
|
||||
}
|
||||
commitScript, err := LeaseCommitScriptToRemoteConfirmed(
|
||||
aliceKeyPub, leaseExpiry,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
commitPkScript, err := WitnessScriptHash(commitScript)
|
||||
require.NoError(t, err)
|
||||
|
||||
commitOutput := &wire.TxOut{
|
||||
PkScript: commitPkScript,
|
||||
Value: int64(outputVal),
|
||||
}
|
||||
|
||||
sweepTx := wire.NewMsgTx(2)
|
||||
sweepTx.AddTxIn(wire.NewTxIn(commitOut, nil, nil))
|
||||
sweepTx.AddTxOut(
|
||||
&wire.TxOut{
|
||||
PkScript: []byte("doesn't matter"),
|
||||
Value: 1 * 10e8,
|
||||
},
|
||||
)
|
||||
|
||||
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
||||
|
||||
testCases := []struct {
|
||||
witness func() wire.TxWitness
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
// Alice can spend after the CSV delay and CLTV timelock
|
||||
// has passed.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = leaseExpiry
|
||||
sweepTx.TxIn[0].Sequence = LockTimeToSequence(
|
||||
false, 1,
|
||||
)
|
||||
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
||||
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: aliceKeyPub,
|
||||
},
|
||||
WitnessScript: commitScript,
|
||||
Output: commitOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return CommitSpendToRemoteConfirmed(
|
||||
aliceSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
true,
|
||||
},
|
||||
{
|
||||
// Alice cannot spend output without sequence set, even
|
||||
// once the CLTV timelock has expired.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = leaseExpiry
|
||||
sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum
|
||||
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
||||
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: aliceKeyPub,
|
||||
},
|
||||
WitnessScript: commitScript,
|
||||
Output: commitOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return CommitSpendToRemoteConfirmed(
|
||||
aliceSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
},
|
||||
{
|
||||
// Alice cannot spend output without sequence or
|
||||
// locktime set.
|
||||
makeWitnessTestCase(t, func() (wire.TxWitness, error) {
|
||||
sweepTx.LockTime = 0
|
||||
sweepTx.TxIn[0].Sequence = wire.MaxTxInSequenceNum
|
||||
sweepTxSigHashes := txscript.NewTxSigHashes(sweepTx)
|
||||
|
||||
signDesc := &SignDescriptor{
|
||||
KeyDesc: keychain.KeyDescriptor{
|
||||
PubKey: aliceKeyPub,
|
||||
},
|
||||
WitnessScript: commitScript,
|
||||
Output: commitOutput,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: sweepTxSigHashes,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
return CommitSpendToRemoteConfirmed(
|
||||
aliceSigner, signDesc, sweepTx,
|
||||
)
|
||||
}),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
sweepTx.TxIn[0].Witness = testCase.witness()
|
||||
|
||||
newEngine := func() (*txscript.Engine, error) {
|
||||
return txscript.NewEngine(
|
||||
commitPkScript, sweepTx, 0,
|
||||
txscript.StandardVerifyFlags, nil, nil,
|
||||
int64(outputVal),
|
||||
)
|
||||
}
|
||||
|
||||
assertEngineExecution(t, i, testCase.valid, newEngine)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSpendAnchor checks that we can spend the anchors using the various spend
|
||||
// paths.
|
||||
func TestSpendAnchor(t *testing.T) {
|
||||
|
Reference in New Issue
Block a user