mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-10-10 05:12:34 +02:00
chanbackup: add Single.CloseTxInputs field
The field is optional. It stores inputs needed to produce signed commit tx using chantools scbforceclose, which calls function GetSignedCommitTx. New backups have this field filled if commit tx is available (for all cases except when DLP is active). If a backup has this data, the field is filled from it, otherwise it is kept empty. Modified test function genRandomOpenChannelShell to cover new types of channels (simple taproot channel and custom channel) and to cover combinations of bits. Make sure that TapscriptRoot field is properly packed and unpacked.
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnencrypt"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
@@ -95,6 +96,29 @@ func assertSingleEqual(t *testing.T, a, b Single) {
|
||||
a.Addresses[i], b.Addresses[i])
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that CloseTxInputs are present either in both backups,
|
||||
// or in none of them.
|
||||
require.Equal(t, a.CloseTxInputs.IsSome(), b.CloseTxInputs.IsSome())
|
||||
|
||||
if a.CloseTxInputs.IsSome() {
|
||||
// Cache CloseTxInputs into short variables.
|
||||
ai := a.CloseTxInputs.UnwrapOrFail(t)
|
||||
bi := b.CloseTxInputs.UnwrapOrFail(t)
|
||||
|
||||
// Compare serialized unsigned transactions.
|
||||
var abuf, bbuf bytes.Buffer
|
||||
require.NoError(t, ai.CommitTx.Serialize(&abuf))
|
||||
require.NoError(t, bi.CommitTx.Serialize(&bbuf))
|
||||
aBytes := abuf.Bytes()
|
||||
bBytes := bbuf.Bytes()
|
||||
require.Equal(t, aBytes, bBytes)
|
||||
|
||||
// Compare counterparty's signature and commit height.
|
||||
require.Equal(t, ai.CommitSig, bi.CommitSig)
|
||||
require.Equal(t, ai.CommitHeight, bi.CommitHeight)
|
||||
require.Equal(t, ai.TapscriptRoot, bi.TapscriptRoot)
|
||||
}
|
||||
}
|
||||
|
||||
func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
|
||||
@@ -124,7 +148,7 @@ func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
|
||||
isInitiator = true
|
||||
}
|
||||
|
||||
chanType := channeldb.ChannelType(rand.Intn(8))
|
||||
chanType := channeldb.ChannelType(rand.Intn(1 << 12))
|
||||
|
||||
localCfg := channeldb.ChannelConfig{
|
||||
ChannelStateBounds: channeldb.ChannelStateBounds{},
|
||||
@@ -184,6 +208,29 @@ func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
|
||||
},
|
||||
}
|
||||
|
||||
var localCommit channeldb.ChannelCommitment
|
||||
if chanType.IsTaproot() {
|
||||
var commitSig [64]byte
|
||||
if _, err := rand.Read(commitSig[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
localCommit = channeldb.ChannelCommitment{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: commitSig[:],
|
||||
CommitHeight: rand.Uint64(),
|
||||
}
|
||||
}
|
||||
|
||||
var tapscriptRootOption fn.Option[chainhash.Hash]
|
||||
if chanType.HasTapscriptRoot() {
|
||||
var tapscriptRoot chainhash.Hash
|
||||
if _, err := rand.Read(tapscriptRoot[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tapscriptRootOption = fn.Some(tapscriptRoot)
|
||||
}
|
||||
|
||||
return &channeldb.OpenChannel{
|
||||
ChainHash: chainHash,
|
||||
ChanType: chanType,
|
||||
@@ -196,10 +243,61 @@ func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
|
||||
IdentityPub: pub,
|
||||
LocalChanCfg: localCfg,
|
||||
RemoteChanCfg: remoteCfg,
|
||||
LocalCommitment: localCommit,
|
||||
RevocationProducer: shaChainProducer,
|
||||
TapscriptRoot: tapscriptRootOption,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TestVersionEncoding tests encoding and decoding of version byte.
|
||||
func TestVersionEncoding(t *testing.T) {
|
||||
cases := []struct {
|
||||
version SingleBackupVersion
|
||||
hasCloseTx bool
|
||||
versionByte byte
|
||||
}{
|
||||
{
|
||||
version: DefaultSingleVersion,
|
||||
hasCloseTx: false,
|
||||
versionByte: DefaultSingleVersion,
|
||||
},
|
||||
{
|
||||
version: DefaultSingleVersion,
|
||||
hasCloseTx: true,
|
||||
versionByte: DefaultSingleVersion | closeTxVersionMask,
|
||||
},
|
||||
{
|
||||
version: AnchorsCommitVersion,
|
||||
hasCloseTx: false,
|
||||
versionByte: AnchorsCommitVersion,
|
||||
},
|
||||
{
|
||||
version: AnchorsCommitVersion,
|
||||
hasCloseTx: true,
|
||||
versionByte: AnchorsCommitVersion | closeTxVersionMask,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
gotVersionByte := tc.version.Encode(tc.hasCloseTx)
|
||||
require.Equal(t, tc.versionByte, gotVersionByte)
|
||||
|
||||
gotVersion, gotHasCloseTx := DecodeVersion(tc.versionByte)
|
||||
require.Equal(t, tc.version, gotVersion)
|
||||
require.Equal(t, tc.hasCloseTx, gotHasCloseTx)
|
||||
}
|
||||
}
|
||||
|
||||
var sampleCommitTx = &wire.MsgTx{
|
||||
TxIn: []*wire.TxIn{
|
||||
{PreviousOutPoint: wire.OutPoint{Hash: [32]byte{1}}},
|
||||
},
|
||||
TxOut: []*wire.TxOut{
|
||||
{Value: 1e8, PkScript: []byte("1")},
|
||||
{Value: 2e8, PkScript: []byte("2")},
|
||||
},
|
||||
}
|
||||
|
||||
// TestSinglePackUnpack tests that we're able to unpack a previously packed
|
||||
// channel backup.
|
||||
func TestSinglePackUnpack(t *testing.T) {
|
||||
@@ -220,6 +318,9 @@ func TestSinglePackUnpack(t *testing.T) {
|
||||
// decode/encode the final SCB.
|
||||
version SingleBackupVersion
|
||||
|
||||
// closeTxInputs is the data needed to produce a force close tx.
|
||||
closeTxInputs fn.Option[CloseTxInputs]
|
||||
|
||||
// valid tests us if this test case should pass or not.
|
||||
valid bool
|
||||
}{
|
||||
@@ -269,11 +370,92 @@ func TestSinglePackUnpack(t *testing.T) {
|
||||
version: 99,
|
||||
valid: false,
|
||||
},
|
||||
|
||||
// Versions with CloseTxInputs.
|
||||
{
|
||||
version: DefaultSingleVersion,
|
||||
closeTxInputs: fn.Some(CloseTxInputs{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: []byte("signature"),
|
||||
}),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
version: TweaklessCommitVersion,
|
||||
closeTxInputs: fn.Some(CloseTxInputs{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: []byte("signature"),
|
||||
}),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
version: AnchorsCommitVersion,
|
||||
closeTxInputs: fn.Some(CloseTxInputs{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: []byte("signature"),
|
||||
}),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
version: ScriptEnforcedLeaseVersion,
|
||||
closeTxInputs: fn.Some(CloseTxInputs{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: []byte("signature"),
|
||||
}),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
version: SimpleTaprootVersion,
|
||||
closeTxInputs: fn.Some(CloseTxInputs{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: []byte("signature"),
|
||||
CommitHeight: 42,
|
||||
}),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
version: TapscriptRootVersion,
|
||||
closeTxInputs: fn.Some(CloseTxInputs{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: []byte("signature"),
|
||||
CommitHeight: 42,
|
||||
TapscriptRoot: fn.Some(chainhash.Hash{1}),
|
||||
}),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
version: 99,
|
||||
closeTxInputs: fn.Some(CloseTxInputs{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: []byte("signature"),
|
||||
}),
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
version: 99,
|
||||
closeTxInputs: fn.Some(CloseTxInputs{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: []byte("signature"),
|
||||
CommitHeight: 42,
|
||||
}),
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
version: TapscriptRootVersion,
|
||||
closeTxInputs: fn.Some(CloseTxInputs{
|
||||
CommitTx: sampleCommitTx,
|
||||
CommitSig: []byte("signature"),
|
||||
CommitHeight: 42,
|
||||
// TapscriptRoot is not filled.
|
||||
}),
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
for i, versionCase := range versionTestCases {
|
||||
// First, we'll re-assign SCB version to what was indicated in
|
||||
// the test case.
|
||||
singleChanBackup.Version = versionCase.version
|
||||
singleChanBackup.CloseTxInputs = versionCase.closeTxInputs
|
||||
|
||||
var b bytes.Buffer
|
||||
|
||||
|
Reference in New Issue
Block a user