Skip to content

Commit f93cd77

Browse files
authored
Merge pull request #1655 from lightninglabs/wip/supplycommit/bugfix-state-machine
Bugfix supply commit state machine
2 parents 7d8ab6c + dd17a24 commit f93cd77

File tree

9 files changed

+198
-91
lines changed

9 files changed

+198
-91
lines changed

tapdb/sqlc/querier.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tapdb/sqlc/queries/supply_commit.sql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,11 @@ DELETE FROM supply_update_events
137137
WHERE transition_id = @transition_id;
138138

139139
-- name: FetchUnspentPrecommits :many
140+
-- Fetch unspent pre-commitment outputs. A pre-commitment output is a mint
141+
-- anchor transaction output which relates to the supply commitment feature.
140142
SELECT
141143
mac.tx_output_index,
142-
ik.raw_key AS taproot_internal_key,
144+
sqlc.embed(ik),
143145
mac.group_key,
144146
mint_txn.block_height,
145147
mint_txn.raw_tx
@@ -159,7 +161,7 @@ SELECT
159161
sc.commit_id,
160162
sc.output_index,
161163
sc.output_key,
162-
ik.raw_key AS internal_key,
164+
sqlc.embed(ik),
163165
txn.raw_tx,
164166
sc.supply_root_hash AS root_hash,
165167
sc.supply_root_sum AS root_sum

tapdb/sqlc/supply_commit.sql.go

Lines changed: 18 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tapdb/supply_commit.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,10 @@ func (s *SupplyCommitMachine) UnspentPrecommits(ctx context.Context,
245245
// interface.
246246
preCommits = make(supplycommit.PreCommits, 0, len(rows))
247247
for _, row := range rows {
248-
internalKey, err := btcec.ParsePubKey(
249-
row.TaprootInternalKey,
250-
)
248+
internalKey, err := parseInternalKey(row.InternalKey)
251249
if err != nil {
252-
return fmt.Errorf("error parsing internal "+
253-
"key: %w", err)
250+
return fmt.Errorf("failed to parse "+
251+
"pre-commitment internal key: %w", err)
254252
}
255253

256254
groupPubKey, err := btcec.ParsePubKey(row.GroupKey)
@@ -272,7 +270,7 @@ func (s *SupplyCommitMachine) UnspentPrecommits(ctx context.Context,
272270
),
273271
MintingTxn: &mintingTx,
274272
OutIdx: uint32(row.TxOutputIndex),
275-
InternalKey: *internalKey,
273+
InternalKey: internalKey,
276274
GroupPubKey: *groupPubKey,
277275
}
278276
preCommits = append(preCommits, preCommit)
@@ -315,7 +313,7 @@ func (s *SupplyCommitMachine) SupplyCommit(ctx context.Context,
315313
err)
316314
}
317315

318-
internalKey, err := btcec.ParsePubKey(row.InternalKey)
316+
internalKey, err := parseInternalKey(row.InternalKey)
319317
if err != nil {
320318
return fmt.Errorf("error parsing internal key: %w", err)
321319
}
@@ -828,7 +826,11 @@ func fetchCommitment(ctx context.Context, db SupplyCommitStore,
828826
"fetch internal key %d for commit %d: %w",
829827
commit.InternalKeyID, commitID.Int64, err)
830828
}
831-
internalKey, err := btcec.ParsePubKey(internalKeyRow.RawKey)
829+
internalKey, err := parseInternalKey(sqlc.InternalKey{
830+
RawKey: internalKeyRow.RawKey,
831+
KeyFamily: internalKeyRow.KeyFamily,
832+
KeyIndex: internalKeyRow.KeyIndex,
833+
})
832834
if err != nil {
833835
return noneRootCommit, noneChainInfo, fmt.Errorf("failed to "+
834836
"parse internal key for commit %d: %w", commitID.Int64,

tapdb/supply_commit_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -681,15 +681,15 @@ func (h *supplyCommitTestHarness) performSingleTransition(
681681
// Next, we'll generate a new "fake" commitment transaction along with
682682
// sample internal and output keys.
683683
commitTx := randTx(h.t, 1)
684-
internalKey := test.RandPubKey(h.t)
684+
internalKey, _ := test.RandKeyDesc(h.t)
685685
outputKey := test.RandPubKey(h.t)
686686

687687
// We'll now simulate the next phase of the state transition where we
688688
// make the new commitment, capture that in a new commit tx, then sign
689689
// and commit that.
690690
commitDetails := supplycommit.SupplyCommitTxn{
691691
Txn: commitTx,
692-
InternalKey: internalKey,
692+
InternalKey: internalKey.PubKey,
693693
OutputKey: outputKey,
694694
OutputIndex: 1,
695695
}
@@ -764,7 +764,7 @@ func (h *supplyCommitTestHarness) performSingleTransition(
764764

765765
return stateTransitionOutput{
766766
appliedUpdates: updates,
767-
internalKey: internalKey,
767+
internalKey: internalKey.PubKey,
768768
outputKey: outputKey,
769769
commitTx: commitTx,
770770
chainProof: chainProof,
@@ -1116,7 +1116,7 @@ func (h *supplyCommitTestHarness) assertTransitionApplied(
11161116
)
11171117
require.Equal(
11181118
h.t, output.internalKey.SerializeCompressed(),
1119-
fetchedCommit.InternalKey.SerializeCompressed(),
1119+
fetchedCommit.InternalKey.PubKey.SerializeCompressed(),
11201120
"SupplyCommit returned wrong InternalKey",
11211121
)
11221122
require.Equal(
@@ -1321,7 +1321,7 @@ func TestSupplyCommitInsertSignedCommitTx(t *testing.T) {
13211321
)
13221322
require.Equal(
13231323
t, internalKey.SerializeCompressed(),
1324-
fetchedTransition.NewCommitment.InternalKey.SerializeCompressed(), //nolint:lll
1324+
fetchedTransition.NewCommitment.InternalKey.PubKey.SerializeCompressed(), //nolint:lll
13251325
)
13261326
require.Equal(
13271327
t, outputKey.SerializeCompressed(),
@@ -1714,7 +1714,7 @@ func TestSupplyCommitMachineFetch(t *testing.T) {
17141714
require.NoError(t, err)
17151715
require.Equal(
17161716
t, dbInternalKeyRow.RawKey,
1717-
rootCommit.InternalKey.SerializeCompressed(),
1717+
rootCommit.InternalKey.PubKey.SerializeCompressed(),
17181718
)
17191719
require.Equal(
17201720
t, dbCommit.OutputKey,

universe/supplycommit/env.go

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ type PreCommitment struct {
123123

124124
// InternalKey is the Taproot internal public key associated with the
125125
// pre-commitment output.
126-
InternalKey btcec.PublicKey
126+
InternalKey keychain.KeyDescriptor
127127

128128
// GroupPubKey is the asset group public key associated with this
129129
// pre-commitment output.
@@ -154,7 +154,7 @@ type RootCommitment struct {
154154
TxOutIdx uint32
155155

156156
// InternalKey is the internal key used to create the commitment output.
157-
InternalKey *btcec.PublicKey
157+
InternalKey keychain.KeyDescriptor
158158

159159
// Output key is the taproot output key used to create the commitment
160160
// output.
@@ -182,11 +182,21 @@ func (r *RootCommitment) TxIn() *wire.TxIn {
182182
//
183183
// TODO(roasbeef): expand, add support for tapscript as well
184184
func (r *RootCommitment) TxOut() (*wire.TxOut, error) {
185-
// First, obtain the root hash of the supply tree.
186-
supplyRootHash := r.SupplyRoot.NodeHash()
185+
txOut, _, err := RootCommitTxOut(
186+
r.InternalKey.PubKey, r.OutputKey, r.SupplyRoot.NodeHash(),
187+
)
188+
189+
return txOut, err
190+
}
187191

188-
var taprootKey *btcec.PublicKey
189-
if r.OutputKey == nil {
192+
// RootCommitTxOut returns the transaction output that corresponds to the root
193+
// commitment. This is used to create a new commitment output.
194+
func RootCommitTxOut(internalKey *btcec.PublicKey,
195+
tapOutKey *btcec.PublicKey, supplyRootHash mssmt.NodeHash) (*wire.TxOut,
196+
*btcec.PublicKey, error) {
197+
198+
var taprootOutputKey *btcec.PublicKey
199+
if tapOutKey == nil {
190200
// We'll create a new unspendable output that contains a
191201
// commitment to the root.
192202
//
@@ -195,28 +205,32 @@ func (r *RootCommitment) TxOut() (*wire.TxOut, error) {
195205
asset.PedersenVersion, supplyRootHash[:],
196206
)
197207
if err != nil {
198-
return nil, fmt.Errorf("unable to create leaf: %w", err)
208+
return nil, nil, fmt.Errorf("unable to create leaf: %w",
209+
err)
199210
}
200211

201212
tapscriptTree := txscript.AssembleTaprootScriptTree(tapLeaf)
202213

203214
rootHash := tapscriptTree.RootNode.TapHash()
204-
taprootKey = txscript.ComputeTaprootOutputKey(
205-
r.InternalKey, rootHash[:],
215+
taprootOutputKey = txscript.ComputeTaprootOutputKey(
216+
internalKey, rootHash[:],
206217
)
207218
} else {
208-
taprootKey = r.OutputKey
219+
taprootOutputKey = tapOutKey
209220
}
210221

211-
pkScript, err := txscript.PayToTaprootScript(taprootKey)
222+
pkScript, err := txscript.PayToTaprootScript(taprootOutputKey)
212223
if err != nil {
213-
return nil, fmt.Errorf("unable to create pk script: %w", err)
224+
return nil, nil, fmt.Errorf("unable to create pk script: %w",
225+
err)
214226
}
215227

216-
return &wire.TxOut{
228+
txOut := wire.TxOut{
217229
Value: int64(tapsend.DummyAmtSats),
218230
PkScript: pkScript,
219-
}, nil
231+
}
232+
233+
return &txOut, taprootOutputKey, nil
220234
}
221235

222236
// ChainProof stores the information needed to prove that a given supply commit
@@ -293,9 +307,8 @@ type Wallet interface {
293307
feeRate chainfee.SatPerKWeight,
294308
changeIdx int32) (*tapsend.FundedPsbt, error)
295309

296-
// SignAndFinalizePsbt fully signs and finalizes the target PSBT
297-
// packet.
298-
SignAndFinalizePsbt(context.Context, *psbt.Packet) (*psbt.Packet, error)
310+
// SignPsbt fully signs the target PSBT packet.
311+
SignPsbt(context.Context, *psbt.Packet) (*psbt.Packet, error)
299312

300313
// ImportTaprootOutput imports a new taproot output key into the wallet.
301314
ImportTaprootOutput(context.Context, *btcec.PublicKey) (btcutil.Address,

universe/supplycommit/mock.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,9 @@ type fundPsbtMockFn func(
7575
chainfee.SatPerKWeight, int32,
7676
) (*tapsend.FundedPsbt, error)
7777

78-
// signAndFinalizePsbtMockFn defines a type for the mock function used in
78+
// signPsbtMockFn defines a type for the mock function used in
7979
// SignAndFinalizePsbt, to simplify a long type assertion.
80-
type signAndFinalizePsbtMockFn func(
81-
context.Context, *psbt.Packet,
82-
) (*psbt.Packet, error)
80+
type signPsbtMockFn func(context.Context, *psbt.Packet) (*psbt.Packet, error)
8381

8482
// mockWallet is a mock implementation of the Wallet interface.
8583
type mockWallet struct {
@@ -107,7 +105,7 @@ func (m *mockWallet) FundPsbt(
107105
return args.Get(0).(*tapsend.FundedPsbt), args.Error(1)
108106
}
109107

110-
func (m *mockWallet) SignAndFinalizePsbt(ctx context.Context,
108+
func (m *mockWallet) SignPsbt(ctx context.Context,
111109
packet *psbt.Packet) (*psbt.Packet, error) {
112110

113111
args := m.Called(ctx, packet)
@@ -116,7 +114,7 @@ func (m *mockWallet) SignAndFinalizePsbt(ctx context.Context,
116114
// If so, this indicates a custom mock implementation that should be
117115
// executed to get the actual return values.
118116
arg0 := args.Get(0)
119-
if fn, ok := arg0.(signAndFinalizePsbtMockFn); ok {
117+
if fn, ok := arg0.(signPsbtMockFn); ok {
120118
return fn(ctx, packet)
121119
}
122120

universe/supplycommit/state_machine_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ func (h *supplyCommitTestHarness) expectPsbtFunding() {
418418
}
419419

420420
func (h *supplyCommitTestHarness) expectPsbtSigning() {
421-
signFn := signAndFinalizePsbtMockFn(func(
421+
signFn := signPsbtMockFn(func(
422422
_ context.Context, pkt *psbt.Packet,
423423
) (*psbt.Packet, error) {
424424
// The transaction from the PSBT is extracted and used to create
@@ -428,7 +428,7 @@ func (h *supplyCommitTestHarness) expectPsbtSigning() {
428428
return newTestSignedPsbt(h.t, pkt.UnsignedTx), nil
429429
})
430430
h.mockWallet.On(
431-
"SignAndFinalizePsbt", mock.Anything, mock.Anything,
431+
"SignPsbt", mock.Anything, mock.Anything,
432432
).Return(signFn, nil).Once()
433433
}
434434

@@ -791,10 +791,13 @@ func TestSupplyCommitTxSignStateTransitions(t *testing.T) {
791791
defaultAssetSpec := asset.NewSpecifierFromId(testAssetID)
792792
dummyTx := wire.NewMsgTx(2)
793793
dummyTx.AddTxOut(&wire.TxOut{PkScript: []byte("test"), Value: 1})
794+
795+
internalKey, _ := test.RandKeyDesc(t)
796+
794797
initialTransition := SupplyStateTransition{
795798
NewCommitment: RootCommitment{
796799
Txn: dummyTx,
797-
InternalKey: test.RandPubKey(t),
800+
InternalKey: internalKey,
798801
TxOutIdx: 0,
799802
},
800803
}

0 commit comments

Comments
 (0)