mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-10-10 02:33:02 +02:00
input+lnwallet: update taproot scripts to accept optional aux leaf
In this commit, we update all the taproot scripts to also accept an optional aux leaf. This aux leaf can be used to add more redemption paths for advanced channels, or just as an extra commitment space.
This commit is contained in:
committed by
Oliver Gugger
parent
8588c9bfd7
commit
1aae47fd71
@@ -1,13 +1,16 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -31,7 +34,9 @@ type testSenderHtlcScriptTree struct {
|
||||
htlcAmt int64
|
||||
}
|
||||
|
||||
func newTestSenderHtlcScriptTree(t *testing.T) *testSenderHtlcScriptTree {
|
||||
func newTestSenderHtlcScriptTree(t *testing.T,
|
||||
auxLeaf AuxTapLeaf) *testSenderHtlcScriptTree {
|
||||
|
||||
var preImage lntypes.Preimage
|
||||
_, err := rand.Read(preImage[:])
|
||||
require.NoError(t, err)
|
||||
@@ -48,7 +53,7 @@ func newTestSenderHtlcScriptTree(t *testing.T) *testSenderHtlcScriptTree {
|
||||
payHash := preImage.Hash()
|
||||
htlcScriptTree, err := SenderHTLCScriptTaproot(
|
||||
senderKey.PubKey(), receiverKey.PubKey(), revokeKey.PubKey(),
|
||||
payHash[:], lntypes.Remote,
|
||||
payHash[:], lntypes.Remote, auxLeaf,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -207,13 +212,9 @@ func htlcSenderTimeoutWitnessGen(sigHash txscript.SigHashType,
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootSenderHtlcSpend tests that all the positive and negative paths
|
||||
// for the sender HTLC tapscript tree work as expected.
|
||||
func TestTaprootSenderHtlcSpend(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
func testTaprootSenderHtlcSpend(t *testing.T, auxLeaf AuxTapLeaf) {
|
||||
// First, create a new test script tree.
|
||||
htlcScriptTree := newTestSenderHtlcScriptTree(t)
|
||||
htlcScriptTree := newTestSenderHtlcScriptTree(t, auxLeaf)
|
||||
|
||||
spendTx := wire.NewMsgTx(2)
|
||||
spendTx.AddTxIn(&wire.TxIn{})
|
||||
@@ -432,6 +433,26 @@ func TestTaprootSenderHtlcSpend(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootSenderHtlcSpend tests that all the positive and negative paths
|
||||
// for the sender HTLC tapscript tree work as expected.
|
||||
func TestTaprootSenderHtlcSpend(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, hasAuxLeaf := range []bool{true, false} {
|
||||
name := fmt.Sprintf("aux_leaf=%v", hasAuxLeaf)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var auxLeaf AuxTapLeaf
|
||||
if hasAuxLeaf {
|
||||
auxLeaf = fn.Some(txscript.NewBaseTapLeaf(
|
||||
bytes.Repeat([]byte{0x01}, 32),
|
||||
))
|
||||
}
|
||||
|
||||
testTaprootSenderHtlcSpend(t, auxLeaf)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type testReceiverHtlcScriptTree struct {
|
||||
preImage lntypes.Preimage
|
||||
|
||||
@@ -452,7 +473,9 @@ type testReceiverHtlcScriptTree struct {
|
||||
lockTime int32
|
||||
}
|
||||
|
||||
func newTestReceiverHtlcScriptTree(t *testing.T) *testReceiverHtlcScriptTree {
|
||||
func newTestReceiverHtlcScriptTree(t *testing.T,
|
||||
auxLeaf AuxTapLeaf) *testReceiverHtlcScriptTree {
|
||||
|
||||
var preImage lntypes.Preimage
|
||||
_, err := rand.Read(preImage[:])
|
||||
require.NoError(t, err)
|
||||
@@ -471,7 +494,7 @@ func newTestReceiverHtlcScriptTree(t *testing.T) *testReceiverHtlcScriptTree {
|
||||
payHash := preImage.Hash()
|
||||
htlcScriptTree, err := ReceiverHTLCScriptTaproot(
|
||||
cltvExpiry, senderKey.PubKey(), receiverKey.PubKey(),
|
||||
revokeKey.PubKey(), payHash[:], lntypes.Remote,
|
||||
revokeKey.PubKey(), payHash[:], lntypes.Remote, auxLeaf,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -629,15 +652,11 @@ func htlcReceiverSuccessWitnessGen(sigHash txscript.SigHashType,
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootReceiverHtlcSpend tests that all possible paths for redeeming an
|
||||
// accepted HTLC (on the commitment transaction) of the receiver work properly.
|
||||
func TestTaprootReceiverHtlcSpend(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
func testTaprootReceiverHtlcSpend(t *testing.T, auxLeaf AuxTapLeaf) {
|
||||
// We'll start by creating the HTLC script tree (contains all 3 valid
|
||||
// spend paths), and also a mock spend transaction that we'll be
|
||||
// signing below.
|
||||
htlcScriptTree := newTestReceiverHtlcScriptTree(t)
|
||||
htlcScriptTree := newTestReceiverHtlcScriptTree(t, auxLeaf)
|
||||
|
||||
// TODO(roasbeef): issue with revoke key??? ctrl block even/odd
|
||||
|
||||
@@ -891,6 +910,28 @@ func TestTaprootReceiverHtlcSpend(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootReceiverHtlcSpend tests that all possible paths for redeeming an
|
||||
// accepted HTLC (on the commitment transaction) of the receiver work properly.
|
||||
func TestTaprootReceiverHtlcSpend(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, hasAuxLeaf := range []bool{true, false} {
|
||||
name := fmt.Sprintf("aux_leaf=%v", hasAuxLeaf)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var auxLeaf AuxTapLeaf
|
||||
if hasAuxLeaf {
|
||||
auxLeaf = fn.Some(
|
||||
txscript.NewBaseTapLeaf(
|
||||
bytes.Repeat([]byte{0x01}, 32),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
testTaprootReceiverHtlcSpend(t, auxLeaf)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type testCommitScriptTree struct {
|
||||
csvDelay uint32
|
||||
|
||||
@@ -905,7 +946,9 @@ type testCommitScriptTree struct {
|
||||
*CommitScriptTree
|
||||
}
|
||||
|
||||
func newTestCommitScriptTree(local bool) (*testCommitScriptTree, error) {
|
||||
func newTestCommitScriptTree(local bool,
|
||||
auxLeaf AuxTapLeaf) (*testCommitScriptTree, error) {
|
||||
|
||||
selfKey, err := btcec.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -925,10 +968,11 @@ func newTestCommitScriptTree(local bool) (*testCommitScriptTree, error) {
|
||||
if local {
|
||||
commitScriptTree, err = NewLocalCommitScriptTree(
|
||||
csvDelay, selfKey.PubKey(), revokeKey.PubKey(),
|
||||
auxLeaf,
|
||||
)
|
||||
} else {
|
||||
commitScriptTree, err = NewRemoteCommitScriptTree(
|
||||
selfKey.PubKey(),
|
||||
selfKey.PubKey(), auxLeaf,
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -1020,12 +1064,8 @@ func localCommitRevokeWitGen(sigHash txscript.SigHashType,
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootCommitScriptToSelf tests that the taproot script for redeeming
|
||||
// one's output after a force close behaves as expected.
|
||||
func TestTaprootCommitScriptToSelf(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
commitScriptTree, err := newTestCommitScriptTree(true)
|
||||
func testTaprootCommitScriptToSelf(t *testing.T, auxLeaf AuxTapLeaf) {
|
||||
commitScriptTree, err := newTestCommitScriptTree(true, auxLeaf)
|
||||
require.NoError(t, err)
|
||||
|
||||
spendTx := wire.NewMsgTx(2)
|
||||
@@ -1187,6 +1227,26 @@ func TestTaprootCommitScriptToSelf(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootCommitScriptToSelf tests that the taproot script for redeeming
|
||||
// one's output after a force close behaves as expected.
|
||||
func TestTaprootCommitScriptToSelf(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, hasAuxLeaf := range []bool{true, false} {
|
||||
name := fmt.Sprintf("aux_leaf=%v", hasAuxLeaf)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var auxLeaf AuxTapLeaf
|
||||
if hasAuxLeaf {
|
||||
auxLeaf = fn.Some(txscript.NewBaseTapLeaf(
|
||||
bytes.Repeat([]byte{0x01}, 32),
|
||||
))
|
||||
}
|
||||
|
||||
testTaprootCommitScriptToSelf(t, auxLeaf)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func remoteCommitSweepWitGen(sigHash txscript.SigHashType,
|
||||
commitScriptTree *testCommitScriptTree) witnessGen {
|
||||
|
||||
@@ -1220,12 +1280,8 @@ func remoteCommitSweepWitGen(sigHash txscript.SigHashType,
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootCommitScriptRemote tests that the remote party can properly sweep
|
||||
// their output after force close.
|
||||
func TestTaprootCommitScriptRemote(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
commitScriptTree, err := newTestCommitScriptTree(false)
|
||||
func testTaprootCommitScriptRemote(t *testing.T, auxLeaf AuxTapLeaf) {
|
||||
commitScriptTree, err := newTestCommitScriptTree(false, auxLeaf)
|
||||
require.NoError(t, err)
|
||||
|
||||
spendTx := wire.NewMsgTx(2)
|
||||
@@ -1364,6 +1420,26 @@ func TestTaprootCommitScriptRemote(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootCommitScriptRemote tests that the remote party can properly sweep
|
||||
// their output after force close.
|
||||
func TestTaprootCommitScriptRemote(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, hasAuxLeaf := range []bool{true, false} {
|
||||
name := fmt.Sprintf("aux_leaf=%v", hasAuxLeaf)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var auxLeaf AuxTapLeaf
|
||||
if hasAuxLeaf {
|
||||
auxLeaf = fn.Some(txscript.NewBaseTapLeaf(
|
||||
bytes.Repeat([]byte{0x01}, 32),
|
||||
))
|
||||
}
|
||||
|
||||
testTaprootCommitScriptRemote(t, auxLeaf)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type testAnchorScriptTree struct {
|
||||
sweepKey *btcec.PrivateKey
|
||||
|
||||
@@ -1599,25 +1675,21 @@ type testSecondLevelHtlcTree struct {
|
||||
tapScriptRoot []byte
|
||||
}
|
||||
|
||||
func newTestSecondLevelHtlcTree() (*testSecondLevelHtlcTree, error) {
|
||||
func newTestSecondLevelHtlcTree(t *testing.T,
|
||||
auxLeaf AuxTapLeaf) *testSecondLevelHtlcTree {
|
||||
|
||||
delayKey, err := btcec.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
revokeKey, err := btcec.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
const csvDelay = 6
|
||||
|
||||
scriptTree, err := SecondLevelHtlcTapscriptTree(
|
||||
delayKey.PubKey(), csvDelay,
|
||||
delayKey.PubKey(), csvDelay, auxLeaf,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
tapScriptRoot := scriptTree.RootNode.TapHash()
|
||||
|
||||
@@ -1626,9 +1698,7 @@ func newTestSecondLevelHtlcTree() (*testSecondLevelHtlcTree, error) {
|
||||
)
|
||||
|
||||
pkScript, err := PayToTaprootScript(htlcKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
const amt = 100
|
||||
|
||||
@@ -1643,7 +1713,7 @@ func newTestSecondLevelHtlcTree() (*testSecondLevelHtlcTree, error) {
|
||||
amt: amt,
|
||||
scriptTree: scriptTree,
|
||||
tapScriptRoot: tapScriptRoot[:],
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func secondLevelHtlcSuccessWitGen(sigHash txscript.SigHashType,
|
||||
@@ -1713,13 +1783,8 @@ func secondLevelHtlcRevokeWitnessgen(sigHash txscript.SigHashType,
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootSecondLevelHtlcScript tests that a channel peer can properly
|
||||
// spend the second level HTLC script to resolve HTLCs.
|
||||
func TestTaprootSecondLevelHtlcScript(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
htlcScriptTree, err := newTestSecondLevelHtlcTree()
|
||||
require.NoError(t, err)
|
||||
func testTaprootSecondLevelHtlcScript(t *testing.T, auxLeaf AuxTapLeaf) {
|
||||
htlcScriptTree := newTestSecondLevelHtlcTree(t, auxLeaf)
|
||||
|
||||
spendTx := wire.NewMsgTx(2)
|
||||
spendTx.AddTxIn(&wire.TxIn{})
|
||||
@@ -1879,3 +1944,23 @@ func TestTaprootSecondLevelHtlcScript(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaprootSecondLevelHtlcScript tests that a channel peer can properly
|
||||
// spend the second level HTLC script to resolve HTLCs.
|
||||
func TestTaprootSecondLevelHtlcScript(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, hasAuxLeaf := range []bool{true, false} {
|
||||
name := fmt.Sprintf("aux_leaf=%v", hasAuxLeaf)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var auxLeaf AuxTapLeaf
|
||||
if hasAuxLeaf {
|
||||
auxLeaf = fn.Some(txscript.NewBaseTapLeaf(
|
||||
bytes.Repeat([]byte{0x01}, 32),
|
||||
))
|
||||
}
|
||||
|
||||
testTaprootSecondLevelHtlcScript(t, auxLeaf)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user