Skip to content

Commit 24c02af

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 4649a67 commit 24c02af

File tree

1 file changed

+82
-33
lines changed

1 file changed

+82
-33
lines changed

tapchannel/aux_sweeper.go

Lines changed: 82 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,42 @@ func (a *AuxSweeper) importCommitScriptKeys(req lnwallet.ResolutionReq) error {
12181218
return nil
12191219
}
12201220

1221+
// importOutputScriptKey imports the output script key that this scriptDesc can
1222+
// spend into the local addr book.
1223+
func (a *AuxSweeper) importOutputScriptKeys(desc tapscriptSweepDescs) error {
1224+
ctxb := context.Background()
1225+
1226+
importScriptKey := func(desc tapscriptSweepDesc) error {
1227+
scriptTree := desc.scriptTree.Tree()
1228+
1229+
outputKey := asset.NewScriptKey(scriptTree.TaprootKey).PubKey
1230+
scriptKey := asset.ScriptKey{
1231+
PubKey: outputKey,
1232+
TweakedScriptKey: &asset.TweakedScriptKey{
1233+
RawKey: keychain.KeyDescriptor{
1234+
PubKey: scriptTree.InternalKey,
1235+
},
1236+
Tweak: scriptTree.TapscriptRoot,
1237+
},
1238+
}
1239+
1240+
log.Debugf("Importing script_keys=%v", spew.Sdump(scriptKey))
1241+
1242+
return a.cfg.AddrBook.InsertScriptKey(ctxb, scriptKey, true)
1243+
}
1244+
1245+
if err := importScriptKey(desc.firstLevel); err != nil {
1246+
return err
1247+
}
1248+
1249+
return lfn.MapOptionZ(
1250+
desc.secondLevel,
1251+
func(secondary tapscriptSweepDesc) error {
1252+
return importScriptKey(secondary)
1253+
},
1254+
)
1255+
}
1256+
12211257
// importOutputProofs imports the output proofs into the pending asset funding
12221258
// into our local database. This preps us to be able to detect force closes.
12231259
func importOutputProofs(scid lnwire.ShortChannelID,
@@ -1586,34 +1622,10 @@ func (a *AuxSweeper) resolveContract(
15861622
return lfn.Err[returnType](err)
15871623
}
15881624

1589-
// To be able to construct all the proofs we need to spend later, we'll
1590-
// make sure that this commitment transaction exists in our database.
1591-
// If not, then we'll complete the proof, register the script keys, and
1592-
// ship the pre-signed commitment transaction.
1593-
ctx := context.Background()
1594-
commitParcel, err := a.cfg.TxSender.QueryParcels(
1595-
ctx, fn.Some(req.CommitTx.TxHash()), false,
1596-
)
1597-
if err != nil {
1598-
return lfn.Err[returnType](err)
1599-
}
1600-
if len(commitParcel) == 0 {
1601-
log.Infof("First time seeing commit_txid=%v, importing",
1602-
req.CommitTx.TxHash())
1603-
1604-
err := a.importCommitTx(req, commitState, fundingInfo)
1605-
if err != nil {
1606-
return lfn.Errf[returnType]("unable to import "+
1607-
"commitment txn: %w", err)
1608-
}
1609-
} else {
1610-
log.Infof("Commitment commit_txid=%v already imported, "+
1611-
"skipping", req.CommitTx.TxHash())
1612-
}
1613-
16141625
var (
1615-
sweepDesc lfn.Result[tapscriptSweepDescs]
1616-
assetOutputs []*cmsg.AssetOutput
1626+
sweepDesc lfn.Result[tapscriptSweepDescs]
1627+
assetOutputs []*cmsg.AssetOutput
1628+
needsSecondLevel bool
16171629
)
16181630

16191631
switch req.Type {
@@ -1722,6 +1734,8 @@ func (a *AuxSweeper) resolveContract(
17221734
// desc.
17231735
sweepDesc = localHtlcTimeoutSweepDesc(req)
17241736

1737+
needsSecondLevel = true
1738+
17251739
// In this case, we've broadcast a commitment, with an incoming HTLC
17261740
// that we can sweep. We'll annotate the sweepDesc with the information
17271741
// needed to sweep both this output, as well as the second level
@@ -1736,12 +1750,52 @@ func (a *AuxSweeper) resolveContract(
17361750
// desc.
17371751
sweepDesc = localHtlcSucessSweepDesc(req)
17381752

1753+
needsSecondLevel = true
1754+
17391755
default:
17401756
return lfn.Errf[returnType]("unknown resolution type: %v",
17411757
req.Type)
17421758
// TODO(roasbeef): need to do HTLC revocation casesj:w
17431759
}
17441760

1761+
tapSweepDesc, err := sweepDesc.Unpack()
1762+
if err != nil {
1763+
return lfn.Err[tlv.Blob](err)
1764+
}
1765+
1766+
// Now that we know what output we're sweeping, before we proceed, we'll
1767+
// import the relevant script key to disk. This way, we'll properly
1768+
// recognize spends of it.
1769+
if err := a.importOutputScriptKeys(tapSweepDesc); err != nil {
1770+
return lfn.Errf[tlv.Blob]("unable to import output script "+
1771+
"key: %w", err)
1772+
}
1773+
1774+
// To be able to construct all the proofs we need to spend later, we'll
1775+
// make sure that this commitment transaction exists in our database. If
1776+
// not, then we'll complete the proof, register the script keys, and
1777+
// ship the pre-signed commitment transaction.
1778+
ctx := context.Background()
1779+
commitParcel, err := a.cfg.TxSender.QueryParcels(
1780+
ctx, fn.Some(req.CommitTx.TxHash()), false,
1781+
)
1782+
if err != nil {
1783+
return lfn.Err[returnType](err)
1784+
}
1785+
if len(commitParcel) == 0 {
1786+
log.Infof("First time seeing commit_txid=%v, importing",
1787+
req.CommitTx.TxHash())
1788+
1789+
err := a.importCommitTx(req, commitState, fundingInfo)
1790+
if err != nil {
1791+
return lfn.Errf[returnType]("unable to import "+
1792+
"commitment txn: %w", err)
1793+
}
1794+
} else {
1795+
log.Infof("Commitment commit_txid=%v already imported, "+
1796+
"skipping", req.CommitTx.TxHash())
1797+
}
1798+
17451799
// The input proofs above were made originally using the fake commit tx
17461800
// as an anchor. We now know the real commit tx, so we'll swap that in
17471801
// to ensure the outpoints used below are correct.
@@ -1752,15 +1806,10 @@ func (a *AuxSweeper) resolveContract(
17521806
log.Infof("Sweeping %v asset outputs: %v", len(assetOutputs),
17531807
limitSpewer.Sdump(assetOutputs))
17541808

1755-
tapSweepDesc, err := sweepDesc.Unpack()
1756-
if err != nil {
1757-
return lfn.Err[tlv.Blob](err)
1758-
}
1759-
17601809
// With the sweep desc constructed above, we'll create vPackets for each
17611810
// of the local assets, then sign them all.
17621811
firstLevelPkts, err := a.createAndSignSweepVpackets(
1763-
lfn.Ok(tapSweepDesc.firstLevel), assetOutputs, req,
1812+
assetOutputs, req, lfn.Ok(tapSweepDesc.firstLevel),
17641813
).Unpack()
17651814
if err != nil {
17661815
return lfn.Err[tlv.Blob](err)

0 commit comments

Comments
 (0)