Skip to content

Commit cb4f1f1

Browse files
committed
tapchannel: import script keys of all HTLC outputs, as known
If we don't import these script keys, spends will fail later as we didn't credit the balance, so we can't spend them.
1 parent 92f83fa commit cb4f1f1

File tree

1 file changed

+76
-32
lines changed

1 file changed

+76
-32
lines changed

tapchannel/aux_sweeper.go

+76-32
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,42 @@ func (a *AuxSweeper) importCommitScriptKeys(req lnwallet.ResolutionReq) error {
12421242
return nil
12431243
}
12441244

1245+
// importOutputScriptKey imports the output script key that this scriptDesc can
1246+
// spend into the local addr book.
1247+
func (a *AuxSweeper) importOutputScriptKeys(desc tapscriptSweepDescs) error {
1248+
ctxb := context.Background()
1249+
1250+
importScriptKey := func(desc tapscriptSweepDesc) error {
1251+
scriptTree := desc.scriptTree.Tree()
1252+
1253+
outputKey := asset.NewScriptKey(scriptTree.TaprootKey).PubKey
1254+
scriptKey := asset.ScriptKey{
1255+
PubKey: outputKey,
1256+
TweakedScriptKey: &asset.TweakedScriptKey{
1257+
RawKey: keychain.KeyDescriptor{
1258+
PubKey: scriptTree.InternalKey,
1259+
},
1260+
Tweak: scriptTree.TapscriptRoot,
1261+
},
1262+
}
1263+
1264+
log.Debugf("Importing script_keys=%v", spew.Sdump(scriptKey))
1265+
1266+
return a.cfg.AddrBook.InsertScriptKey(ctxb, scriptKey, true)
1267+
}
1268+
1269+
if err := importScriptKey(desc.firstLevel); err != nil {
1270+
return err
1271+
}
1272+
1273+
return lfn.MapOptionZ(
1274+
desc.secondLevel,
1275+
func(secondary tapscriptSweepDesc) error {
1276+
return importScriptKey(secondary)
1277+
},
1278+
)
1279+
}
1280+
12451281
// importOutputProofs imports the output proofs into the pending asset funding
12461282
// into our local database. This preps us to be able to detect force closes.
12471283
func importOutputProofs(scid lnwire.ShortChannelID,
@@ -1610,31 +1646,6 @@ func (a *AuxSweeper) resolveContract(
16101646
return lfn.Err[returnType](err)
16111647
}
16121648

1613-
// To be able to construct all the proofs we need to spend later, we'll
1614-
// make sure that this commitment transaction exists in our database.
1615-
// If not, then we'll complete the proof, register the script keys, and
1616-
// ship the pre-signed commitment transaction.
1617-
ctx := context.Background()
1618-
commitParcel, err := a.cfg.TxSender.QueryParcels(
1619-
ctx, fn.Some(req.CommitTx.TxHash()), false,
1620-
)
1621-
if err != nil {
1622-
return lfn.Err[returnType](err)
1623-
}
1624-
if len(commitParcel) == 0 {
1625-
log.Infof("First time seeing commit_txid=%v, importing",
1626-
req.CommitTx.TxHash())
1627-
1628-
err := a.importCommitTx(req, commitState, fundingInfo)
1629-
if err != nil {
1630-
return lfn.Errf[returnType]("unable to import "+
1631-
"commitment txn: %w", err)
1632-
}
1633-
} else {
1634-
log.Infof("Commitment commit_txid=%v already imported, "+
1635-
"skipping", req.CommitTx.TxHash())
1636-
}
1637-
16381649
var (
16391650
sweepDesc lfn.Result[tapscriptSweepDescs]
16401651
assetOutputs []*cmsg.AssetOutput
@@ -1771,20 +1782,53 @@ func (a *AuxSweeper) resolveContract(
17711782
// TODO(roasbeef): need to do HTLC revocation casesj:w
17721783
}
17731784

1785+
tapSweepDesc, err := sweepDesc.Unpack()
1786+
if err != nil {
1787+
return lfn.Err[tlv.Blob](err)
1788+
}
1789+
1790+
// Now that we know what output we're sweeping, before we proceed, we'll
1791+
// import the relevant script key to disk. This way, we'll properly
1792+
// recognize spends of it.
1793+
if err := a.importOutputScriptKeys(tapSweepDesc); err != nil {
1794+
return lfn.Errf[tlv.Blob]("unable to import output script "+
1795+
"key: %w", err)
1796+
}
1797+
1798+
// To be able to construct all the proofs we need to spend later, we'll
1799+
// make sure that this commitment transaction exists in our database. If
1800+
// not, then we'll complete the proof, register the script keys, and
1801+
// ship the pre-signed commitment transaction.
1802+
ctx := context.Background()
1803+
commitParcel, err := a.cfg.TxSender.QueryParcels(
1804+
ctx, fn.Some(req.CommitTx.TxHash()), false,
1805+
)
1806+
if err != nil {
1807+
return lfn.Err[returnType](err)
1808+
}
1809+
if len(commitParcel) == 0 {
1810+
log.Infof("First time seeing commit_txid=%v, importing",
1811+
req.CommitTx.TxHash())
1812+
1813+
err := a.importCommitTx(req, commitState, fundingInfo)
1814+
if err != nil {
1815+
return lfn.Errf[returnType]("unable to import "+
1816+
"commitment txn: %w", err)
1817+
}
1818+
} else {
1819+
log.Infof("Commitment commit_txid=%v already imported, "+
1820+
"skipping", req.CommitTx.TxHash())
1821+
}
1822+
17741823
// The input proofs above were made originally using the fake commit tx
17751824
// as an anchor. We now know the real commit tx, so we'll swap that in
17761825
// to ensure the outpoints used below are correct.
17771826
for _, assetOut := range assetOutputs {
17781827
assetOut.Proof.Val.AnchorTx = *req.CommitTx
17791828
}
17801829

1781-
log.Infof("Sweeping %v asset outputs: %v", len(assetOutputs),
1782-
limitSpewer.Sdump(assetOutputs))
1783-
1784-
tapSweepDesc, err := sweepDesc.Unpack()
1785-
if err != nil {
1786-
return lfn.Err[tlv.Blob](err)
1787-
}
1830+
log.Infof("Sweeping %v asset outputs (second_level=%v): %v",
1831+
len(assetOutputs), needsSecondLevel, spew.Sdump(assetOutputs))
17881832

17891833
// With the sweep desc constructed above, we'll create vPackets for each
17901834
// of the local assets, then sign them all.

0 commit comments

Comments
 (0)