Skip to content

Commit 869063c

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 5c5d5d9 commit 869063c

File tree

4 files changed

+26
-20
lines changed

4 files changed

+26
-20
lines changed

tapdb/supply_commit.go

Lines changed: 10 additions & 7 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,18 @@ 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 {
906-
return fmt.Errorf("failed to upsert internal key %x: "+
907-
"%w",
908-
internalKey.SerializeCompressed(), err)
908+
return fmt.Errorf("failed to upsert "+
909+
"internal key %x: %w",
910+
internalKeyDesc.PubKey.SerializeCompressed(),
911+
err)
909912
}
910913

911914
// 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
@@ -721,6 +722,7 @@ func (h *supplyCommitTestHarness) performSingleTransition(
721722
// Next, we'll generate a new "fake" commitment transaction along with
722723
// sample internal and output keys.
723724
commitTx := randTx(h.t, 1)
725+
724726
// Add inputs to the transaction that spend the pre-commitment outputs.
725727
for _, outpoint := range preCommitOutpoints {
726728
commitTx.TxIn = append(commitTx.TxIn, &wire.TxIn{
@@ -736,7 +738,7 @@ func (h *supplyCommitTestHarness) performSingleTransition(
736738
// and commit that.
737739
commitDetails := supplycommit.SupplyCommitTxn{
738740
Txn: commitTx,
739-
InternalKey: internalKey.PubKey,
741+
InternalKey: internalKey,
740742
OutputKey: outputKey,
741743
OutputIndex: 1,
742744
}
@@ -811,7 +813,7 @@ func (h *supplyCommitTestHarness) performSingleTransition(
811813

812814
return stateTransitionOutput{
813815
appliedUpdates: updates,
814-
internalKey: internalKey.PubKey,
816+
internalKey: internalKey,
815817
outputKey: outputKey,
816818
commitTx: commitTx,
817819
chainProof: chainProof,
@@ -1018,7 +1020,7 @@ func (h *supplyCommitTestHarness) assertTransitionApplied(
10181020
// The keys should also be inserted, and the db commitment should match
10191021
// what we inserted.
10201022
require.Equal(
1021-
h.t, internalKey.SerializeCompressed(),
1023+
h.t, internalKey.PubKey.SerializeCompressed(),
10221024
h.fetchInternalKeyByID(dbCommitment.InternalKeyID).RawKey,
10231025
"internalKey mismatch",
10241026
)
@@ -1162,7 +1164,7 @@ func (h *supplyCommitTestHarness) assertTransitionApplied(
11621164
"SupplyCommit returned wrong Txn hash",
11631165
)
11641166
require.Equal(
1165-
h.t, output.internalKey.SerializeCompressed(),
1167+
h.t, output.internalKey.PubKey.SerializeCompressed(),
11661168
fetchedCommit.InternalKey.PubKey.SerializeCompressed(),
11671169
"SupplyCommit returned wrong InternalKey",
11681170
)
@@ -1404,7 +1406,7 @@ func TestSupplyCommitInsertSignedCommitTx(t *testing.T) {
14041406
commitTxid2 := commitTx2.TxHash()
14051407

14061408
// Insert the signed commitment with the updated transaction.
1407-
internalKey := test.RandPubKey(t)
1409+
internalKey, _ := test.RandKeyDesc(t)
14081410
outputKey := test.RandPubKey(t)
14091411
commitDetails := supplycommit.SupplyCommitTxn{
14101412
Txn: commitTx2,
@@ -1443,7 +1445,7 @@ func TestSupplyCommitInsertSignedCommitTx(t *testing.T) {
14431445
require.NoError(t, err)
14441446
require.Equal(t, chainTx2Record.TxnID, newDbCommitment.ChainTxnID)
14451447
require.Equal(t,
1446-
internalKey.SerializeCompressed(),
1448+
internalKey.PubKey.SerializeCompressed(),
14471449
h.fetchInternalKeyByID(newDbCommitment.InternalKeyID).RawKey,
14481450
)
14491451
require.Equal(
@@ -1466,7 +1468,7 @@ func TestSupplyCommitInsertSignedCommitTx(t *testing.T) {
14661468
t, commitTxid2, fetchedTransition.NewCommitment.Txn.TxHash(),
14671469
)
14681470
require.Equal(
1469-
t, internalKey.SerializeCompressed(),
1471+
t, internalKey.PubKey.SerializeCompressed(),
14701472
fetchedTransition.NewCommitment.InternalKey.PubKey.SerializeCompressed(), //nolint:lll
14711473
)
14721474
require.Equal(
@@ -1580,7 +1582,7 @@ func TestSupplyCommitFetchState(t *testing.T) {
15801582

15811583
// Next, we'll insert a signed commitment transaction.
15821584
commitTx := randTx(t, 1)
1583-
internalKey := test.RandPubKey(t)
1585+
internalKey, _ := test.RandKeyDesc(t)
15841586
outputKey := test.RandPubKey(t)
15851587

15861588
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
@@ -768,7 +768,7 @@ func (s *CommitTxSignState) ProcessEvent(event Event,
768768
newCommit := &stateTransition.NewCommitment
769769
commitTxnDetails := SupplyCommitTxn{
770770
Txn: commitTx,
771-
InternalKey: newCommit.InternalKey.PubKey,
771+
InternalKey: newCommit.InternalKey,
772772
OutputKey: newCommit.OutputKey,
773773
OutputIndex: newCommit.TxOutIdx,
774774
}

0 commit comments

Comments
 (0)