Skip to content

Commit 1435ef3

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 6e920d0 commit 1435ef3

File tree

1 file changed

+83
-34
lines changed

1 file changed

+83
-34
lines changed

tapchannel/aux_sweeper.go

+83-34
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,42 @@ func (a *AuxSweeper) importCommitScriptKeys(req lnwallet.ResolutionReq) error {
12501250
return nil
12511251
}
12521252

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

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

16511663
switch req.Type {
@@ -1754,6 +1766,8 @@ func (a *AuxSweeper) resolveContract(
17541766
// desc.
17551767
sweepDesc = localHtlcTimeoutSweepDesc(req)
17561768

1769+
needsSecondLevel = true
1770+
17571771
// In this case, we've broadcast a commitment, with an incoming HTLC
17581772
// that we can sweep. We'll annotate the sweepDesc with the information
17591773
// needed to sweep both this output, as well as the second level
@@ -1768,26 +1782,61 @@ func (a *AuxSweeper) resolveContract(
17681782
// desc.
17691783
sweepDesc = localHtlcSucessSweepDesc(req)
17701784

1785+
needsSecondLevel = true
1786+
17711787
default:
17721788
return lfn.Errf[returnType]("unknown resolution type: %v",
17731789
req.Type)
17741790
// TODO(roasbeef): need to do HTLC revocation casesj:w
17751791
}
17761792

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

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

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

0 commit comments

Comments
 (0)