Skip to content

Commit 74efdef

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 f9f7b55 commit 74efdef

File tree

1 file changed

+76
-32
lines changed

1 file changed

+76
-32
lines changed

tapchannel/aux_sweeper.go

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,42 @@ func (a *AuxSweeper) importCommitScriptKeys(req lnwallet.ResolutionReq) error {
12491249
return nil
12501250
}
12511251

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

1623-
// To be able to construct all the proofs we need to spend later, we'll
1624-
// make sure that this commitment transaction exists in our database.
1625-
// If not, then we'll complete the proof, register the script keys, and
1626-
// ship the pre-signed commitment transaction.
1627-
ctx := context.Background()
1628-
commitParcel, err := a.cfg.TxSender.QueryParcels(
1629-
ctx, fn.Some(req.CommitTx.TxHash()), false,
1630-
)
1631-
if err != nil {
1632-
return lfn.Err[returnType](err)
1633-
}
1634-
if len(commitParcel) == 0 {
1635-
log.Infof("First time seeing commit_txid=%v, importing",
1636-
req.CommitTx.TxHash())
1637-
1638-
err := a.importCommitTx(req, commitState, fundingInfo)
1639-
if err != nil {
1640-
return lfn.Errf[returnType]("unable to import "+
1641-
"commitment txn: %w", err)
1642-
}
1643-
} else {
1644-
log.Infof("Commitment commit_txid=%v already imported, "+
1645-
"skipping", req.CommitTx.TxHash())
1646-
}
1647-
16481659
var (
16491660
sweepDesc lfn.Result[tapscriptSweepDescs]
16501661
assetOutputs []*cmsg.AssetOutput
@@ -1775,20 +1786,53 @@ func (a *AuxSweeper) resolveContract(
17751786
// TODO(roasbeef): need to do HTLC revocation casesj:w
17761787
}
17771788

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

1785-
log.Infof("Sweeping %v asset outputs: %v", len(assetOutputs),
1786-
limitSpewer.Sdump(assetOutputs))
1787-
1788-
tapSweepDesc, err := sweepDesc.Unpack()
1789-
if err != nil {
1790-
return lfn.Err[tlv.Blob](err)
1791-
}
1834+
log.Infof("Sweeping %v asset outputs (second_level=%v): %v",
1835+
len(assetOutputs), needsSecondLevel, spew.Sdump(assetOutputs))
17921836

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

0 commit comments

Comments
 (0)