Skip to content

Commit 4120388

Browse files
committed
tapdb: fix bug by ensuring that we write the full keydesc to disk
This fixes a bug that would cause a spend of a supply commitment output to fail. We weren't storing the full key desc, so lnd wasn't able to sign the PSBT, as the bip32 information didn't match up (derived wrong key).
1 parent 92c96c2 commit 4120388

File tree

4 files changed

+23
-18
lines changed

4 files changed

+23
-18
lines changed

tapdb/supply_commit.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ func (s *SupplyCommitMachine) InsertSignedCommitTx(ctx context.Context,
855855
groupKeyBytes := groupKey.SerializeCompressed()
856856

857857
commitTx := commitDetails.Txn
858-
internalKey := commitDetails.InternalKey
858+
internalKeyDesc := commitDetails.InternalKey
859859
outputKey := commitDetails.OutputKey
860860
outputIndex := commitDetails.OutputIndex
861861

@@ -897,15 +897,17 @@ func (s *SupplyCommitMachine) InsertSignedCommitTx(ctx context.Context,
897897
"%w", err)
898898
}
899899

900-
// Upsert the internal key to get its ID. We assume key family
901-
// and index 0 for now, as this key is likely externally.
900+
// Upsert the internal key to get its ID, preserving the full
901+
// key derivation information for proper PSBT signing later.
902902
internalKeyID, err := db.UpsertInternalKey(ctx, InternalKey{
903-
RawKey: internalKey.SerializeCompressed(),
903+
RawKey: internalKeyDesc.PubKey.SerializeCompressed(),
904+
KeyFamily: int32(internalKeyDesc.Family),
905+
KeyIndex: int32(internalKeyDesc.Index),
904906
})
905907
if err != nil {
906908
return fmt.Errorf("failed to upsert internal key %x: "+
907909
"%w",
908-
internalKey.SerializeCompressed(), err)
910+
internalKeyDesc.PubKey.SerializeCompressed(), err)
909911
}
910912

911913
// Insert the new commitment record. Chain details (block

tapdb/supply_commit_test.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/lightninglabs/taproot-assets/tapdb/sqlc"
2121
"github.com/lightninglabs/taproot-assets/universe/supplycommit"
2222
lfn "github.com/lightningnetwork/lnd/fn/v2"
23+
"github.com/lightningnetwork/lnd/keychain"
2324
"github.com/lightningnetwork/lnd/lnutils"
2425
"github.com/stretchr/testify/require"
2526
)
@@ -126,8 +127,8 @@ func (h *supplyCommitTestHarness) addTestMintingBatch() ([]byte, int64,
126127
Txid: mintTxID[:],
127128
RawTx: mintTxBytes,
128129
})
129-
require.NoError(h.t, err)
130130

131+
require.NoError(h.t, err)
131132
genesisPointBytes, err := encodeOutpoint(genesisPoint)
132133
require.NoError(h.t, err)
133134
err = db.AnchorGenesisPoint(ctx, sqlc.AnchorGenesisPointParams{
@@ -158,7 +159,7 @@ func (h *supplyCommitTestHarness) addTestMintingBatch() ([]byte, int64,
158159
// transition performed by performSingleTransition.
159160
type stateTransitionOutput struct {
160161
appliedUpdates []supplycommit.SupplyUpdateEvent
161-
internalKey *btcec.PublicKey
162+
internalKey keychain.KeyDescriptor
162163
outputKey *btcec.PublicKey
163164
commitTx *wire.MsgTx
164165
chainProof supplycommit.ChainProof
@@ -720,6 +721,7 @@ func (h *supplyCommitTestHarness) performSingleTransition(
720721
// Next, we'll generate a new "fake" commitment transaction along with
721722
// sample internal and output keys.
722723
commitTx := randTx(h.t, 1)
724+
723725
// Add inputs to the transaction that spend the pre-commitment outputs.
724726
for _, outpoint := range preCommitOutpoints {
725727
commitTx.TxIn = append(commitTx.TxIn, &wire.TxIn{
@@ -735,7 +737,7 @@ func (h *supplyCommitTestHarness) performSingleTransition(
735737
// and commit that.
736738
commitDetails := supplycommit.SupplyCommitTxn{
737739
Txn: commitTx,
738-
InternalKey: internalKey.PubKey,
740+
InternalKey: internalKey,
739741
OutputKey: outputKey,
740742
OutputIndex: 1,
741743
}
@@ -810,7 +812,7 @@ func (h *supplyCommitTestHarness) performSingleTransition(
810812

811813
return stateTransitionOutput{
812814
appliedUpdates: updates,
813-
internalKey: internalKey.PubKey,
815+
internalKey: internalKey,
814816
outputKey: outputKey,
815817
commitTx: commitTx,
816818
chainProof: chainProof,
@@ -1017,7 +1019,7 @@ func (h *supplyCommitTestHarness) assertTransitionApplied(
10171019
// The keys should also be inserted, and the db commitment should match
10181020
// what we inserted.
10191021
require.Equal(
1020-
h.t, internalKey.SerializeCompressed(),
1022+
h.t, internalKey.PubKey.SerializeCompressed(),
10211023
h.fetchInternalKeyByID(dbCommitment.InternalKeyID).RawKey,
10221024
"internalKey mismatch",
10231025
)
@@ -1161,7 +1163,7 @@ func (h *supplyCommitTestHarness) assertTransitionApplied(
11611163
"SupplyCommit returned wrong Txn hash",
11621164
)
11631165
require.Equal(
1164-
h.t, output.internalKey.SerializeCompressed(),
1166+
h.t, output.internalKey.PubKey.SerializeCompressed(),
11651167
fetchedCommit.InternalKey.PubKey.SerializeCompressed(),
11661168
"SupplyCommit returned wrong InternalKey",
11671169
)
@@ -1401,7 +1403,7 @@ func TestSupplyCommitInsertSignedCommitTx(t *testing.T) {
14011403
commitTxid2 := commitTx2.TxHash()
14021404

14031405
// Insert the signed commitment with the updated transaction.
1404-
internalKey := test.RandPubKey(t)
1406+
internalKey, _ := test.RandKeyDesc(t)
14051407
outputKey := test.RandPubKey(t)
14061408
commitDetails := supplycommit.SupplyCommitTxn{
14071409
Txn: commitTx2,
@@ -1440,7 +1442,7 @@ func TestSupplyCommitInsertSignedCommitTx(t *testing.T) {
14401442
require.NoError(t, err)
14411443
require.Equal(t, chainTx2Record.TxnID, newDbCommitment.ChainTxnID)
14421444
require.Equal(t,
1443-
internalKey.SerializeCompressed(),
1445+
internalKey.PubKey.SerializeCompressed(),
14441446
h.fetchInternalKeyByID(newDbCommitment.InternalKeyID).RawKey,
14451447
)
14461448
require.Equal(
@@ -1463,7 +1465,7 @@ func TestSupplyCommitInsertSignedCommitTx(t *testing.T) {
14631465
t, commitTxid2, fetchedTransition.NewCommitment.Txn.TxHash(),
14641466
)
14651467
require.Equal(
1466-
t, internalKey.SerializeCompressed(),
1468+
t, internalKey.PubKey.SerializeCompressed(),
14671469
fetchedTransition.NewCommitment.InternalKey.PubKey.SerializeCompressed(), //nolint:lll
14681470
)
14691471
require.Equal(
@@ -1577,7 +1579,7 @@ func TestSupplyCommitFetchState(t *testing.T) {
15771579

15781580
// Next, we'll insert a signed commitment transaction.
15791581
commitTx := randTx(t, 1)
1580-
internalKey := test.RandPubKey(t)
1582+
internalKey, _ := test.RandKeyDesc(t)
15811583
outputKey := test.RandPubKey(t)
15821584

15831585
commitDetails := supplycommit.SupplyCommitTxn{

universe/supplycommit/env.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,9 @@ type SupplyCommitTxn struct {
517517
// Txn is the transaction that creates the supply commitment.
518518
Txn *wire.MsgTx
519519

520-
// InternalKey is the internal key used for the commitment output.
521-
InternalKey *btcec.PublicKey
520+
// InternalKey is the internal key descriptor used for the commitment
521+
// output. This preserves the full key derivation information.
522+
InternalKey keychain.KeyDescriptor
522523

523524
// OutputKey is the taproot output key used for the commitment output.
524525
OutputKey *btcec.PublicKey

universe/supplycommit/transitions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ func (s *CommitTxSignState) ProcessEvent(event Event,
750750
newCommit := &stateTransition.NewCommitment
751751
commitTxnDetails := SupplyCommitTxn{
752752
Txn: commitTx,
753-
InternalKey: newCommit.InternalKey.PubKey,
753+
InternalKey: newCommit.InternalKey,
754754
OutputKey: newCommit.OutputKey,
755755
OutputIndex: newCommit.TxOutIdx,
756756
}

0 commit comments

Comments
 (0)