mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-04 09:48:19 +01:00
lnwallet: thread thru input.AuxTapleaf to all relevant areas
In this commit, we start to thread thru the new aux tap leaf structures to all relevant areas. This includes: commitment outputs, resolution creation, breach handling, and also HTLC scripts.
This commit is contained in:
parent
2ab22b0f0b
commit
9dfbde7013
6 changed files with 345 additions and 76 deletions
|
@ -426,15 +426,36 @@ func (c *chainWatcher) handleUnknownLocalState(
|
||||||
&c.cfg.chanState.LocalChanCfg, &c.cfg.chanState.RemoteChanCfg,
|
&c.cfg.chanState.LocalChanCfg, &c.cfg.chanState.RemoteChanCfg,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
auxResult, err := fn.MapOptionZ(
|
||||||
|
c.cfg.auxLeafStore,
|
||||||
|
//nolint:lll
|
||||||
|
func(s lnwallet.AuxLeafStore) fn.Result[lnwallet.CommitDiffAuxResult] {
|
||||||
|
return s.FetchLeavesFromCommit(
|
||||||
|
lnwallet.NewAuxChanState(c.cfg.chanState),
|
||||||
|
c.cfg.chanState.LocalCommitment, *commitKeyRing,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
).Unpack()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("unable to fetch aux leaves: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// With the keys derived, we'll construct the remote script that'll be
|
// With the keys derived, we'll construct the remote script that'll be
|
||||||
// present if they have a non-dust balance on the commitment.
|
// present if they have a non-dust balance on the commitment.
|
||||||
var leaseExpiry uint32
|
var leaseExpiry uint32
|
||||||
if c.cfg.chanState.ChanType.HasLeaseExpiration() {
|
if c.cfg.chanState.ChanType.HasLeaseExpiration() {
|
||||||
leaseExpiry = c.cfg.chanState.ThawHeight
|
leaseExpiry = c.cfg.chanState.ThawHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remoteAuxLeaf := fn.ChainOption(
|
||||||
|
func(l lnwallet.CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return l.RemoteAuxLeaf
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
remoteScript, _, err := lnwallet.CommitScriptToRemote(
|
remoteScript, _, err := lnwallet.CommitScriptToRemote(
|
||||||
c.cfg.chanState.ChanType, c.cfg.chanState.IsInitiator,
|
c.cfg.chanState.ChanType, c.cfg.chanState.IsInitiator,
|
||||||
commitKeyRing.ToRemoteKey, leaseExpiry, input.NoneTapLeaf(),
|
commitKeyRing.ToRemoteKey, leaseExpiry,
|
||||||
|
remoteAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -443,11 +464,16 @@ func (c *chainWatcher) handleUnknownLocalState(
|
||||||
// Next, we'll derive our script that includes the revocation base for
|
// Next, we'll derive our script that includes the revocation base for
|
||||||
// the remote party allowing them to claim this output before the CSV
|
// the remote party allowing them to claim this output before the CSV
|
||||||
// delay if we breach.
|
// delay if we breach.
|
||||||
|
localAuxLeaf := fn.ChainOption(
|
||||||
|
func(l lnwallet.CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return l.LocalAuxLeaf
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
localScript, err := lnwallet.CommitScriptToSelf(
|
localScript, err := lnwallet.CommitScriptToSelf(
|
||||||
c.cfg.chanState.ChanType, c.cfg.chanState.IsInitiator,
|
c.cfg.chanState.ChanType, c.cfg.chanState.IsInitiator,
|
||||||
commitKeyRing.ToLocalKey, commitKeyRing.RevocationKey,
|
commitKeyRing.ToLocalKey, commitKeyRing.RevocationKey,
|
||||||
uint32(c.cfg.chanState.LocalChanCfg.CsvDelay), leaseExpiry,
|
uint32(c.cfg.chanState.LocalChanCfg.CsvDelay), leaseExpiry,
|
||||||
input.NoneTapLeaf(),
|
localAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
|
@ -1388,7 +1388,7 @@ func genTimeoutTx(t *testing.T,
|
||||||
// Create the unsigned timeout tx.
|
// Create the unsigned timeout tx.
|
||||||
timeoutTx, err := lnwallet.CreateHtlcTimeoutTx(
|
timeoutTx, err := lnwallet.CreateHtlcTimeoutTx(
|
||||||
chanType, false, testOutPoint, testAmt, testCLTVExpiry,
|
chanType, false, testOutPoint, testAmt, testCLTVExpiry,
|
||||||
testCSVDelay, 0, testPubkey, testPubkey,
|
testCSVDelay, 0, testPubkey, testPubkey, input.NoneTapLeaf(),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -1457,7 +1457,7 @@ func genSuccessTx(t *testing.T, chanType channeldb.ChannelType) *wire.MsgTx {
|
||||||
// Create the unsigned success tx.
|
// Create the unsigned success tx.
|
||||||
successTx, err := lnwallet.CreateHtlcSuccessTx(
|
successTx, err := lnwallet.CreateHtlcSuccessTx(
|
||||||
chanType, false, testOutPoint, testAmt, testCSVDelay, 0,
|
chanType, false, testOutPoint, testAmt, testCSVDelay, 0,
|
||||||
testPubkey, testPubkey,
|
testPubkey, testPubkey, input.NoneTapLeaf(),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
@ -576,7 +576,8 @@ func (c *commitment) toDiskCommit(
|
||||||
// restart a channel session.
|
// restart a channel session.
|
||||||
func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
||||||
htlc *channeldb.HTLC, commitKeys lntypes.Dual[*CommitmentKeyRing],
|
htlc *channeldb.HTLC, commitKeys lntypes.Dual[*CommitmentKeyRing],
|
||||||
whoseCommit lntypes.ChannelParty) (PaymentDescriptor, error) {
|
whoseCommit lntypes.ChannelParty,
|
||||||
|
auxLeaf input.AuxTapLeaf) (PaymentDescriptor, error) {
|
||||||
|
|
||||||
// The proper pkScripts for this PaymentDescriptor must be
|
// The proper pkScripts for this PaymentDescriptor must be
|
||||||
// generated so we can easily locate them within the commitment
|
// generated so we can easily locate them within the commitment
|
||||||
|
@ -602,6 +603,7 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
||||||
scriptInfo, err := genHtlcScript(
|
scriptInfo, err := genHtlcScript(
|
||||||
chanType, htlc.Incoming, lntypes.Local,
|
chanType, htlc.Incoming, lntypes.Local,
|
||||||
htlc.RefundTimeout, htlc.RHash, localCommitKeys,
|
htlc.RefundTimeout, htlc.RHash, localCommitKeys,
|
||||||
|
auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pd, err
|
return pd, err
|
||||||
|
@ -618,6 +620,7 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
||||||
scriptInfo, err := genHtlcScript(
|
scriptInfo, err := genHtlcScript(
|
||||||
chanType, htlc.Incoming, lntypes.Remote,
|
chanType, htlc.Incoming, lntypes.Remote,
|
||||||
htlc.RefundTimeout, htlc.RHash, remoteCommitKeys,
|
htlc.RefundTimeout, htlc.RHash, remoteCommitKeys,
|
||||||
|
auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pd, err
|
return pd, err
|
||||||
|
@ -667,7 +670,8 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
||||||
// for each side.
|
// for each side.
|
||||||
func (lc *LightningChannel) extractPayDescs(feeRate chainfee.SatPerKWeight,
|
func (lc *LightningChannel) extractPayDescs(feeRate chainfee.SatPerKWeight,
|
||||||
htlcs []channeldb.HTLC, commitKeys lntypes.Dual[*CommitmentKeyRing],
|
htlcs []channeldb.HTLC, commitKeys lntypes.Dual[*CommitmentKeyRing],
|
||||||
whoseCommit lntypes.ChannelParty) ([]PaymentDescriptor,
|
whoseCommit lntypes.ChannelParty,
|
||||||
|
auxLeaves fn.Option[CommitAuxLeaves]) ([]PaymentDescriptor,
|
||||||
[]PaymentDescriptor, error) {
|
[]PaymentDescriptor, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -685,8 +689,19 @@ func (lc *LightningChannel) extractPayDescs(feeRate chainfee.SatPerKWeight,
|
||||||
|
|
||||||
htlc := htlc
|
htlc := htlc
|
||||||
|
|
||||||
|
auxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
leaves := l.OutgoingHtlcLeaves
|
||||||
|
if htlc.Incoming {
|
||||||
|
leaves = l.IncomingHtlcLeaves
|
||||||
|
}
|
||||||
|
|
||||||
|
return leaves[htlc.HtlcIndex].AuxTapLeaf
|
||||||
|
},
|
||||||
|
)(auxLeaves)
|
||||||
|
|
||||||
payDesc, err := lc.diskHtlcToPayDesc(
|
payDesc, err := lc.diskHtlcToPayDesc(
|
||||||
feeRate, &htlc, commitKeys, whoseCommit,
|
feeRate, &htlc, commitKeys, whoseCommit, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return incomingHtlcs, outgoingHtlcs, err
|
return incomingHtlcs, outgoingHtlcs, err
|
||||||
|
@ -733,12 +748,25 @@ func (lc *LightningChannel) diskCommitToMemCommit(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auxResult, err := fn.MapOptionZ(
|
||||||
|
lc.leafStore,
|
||||||
|
func(s AuxLeafStore) fn.Result[CommitDiffAuxResult] {
|
||||||
|
return s.FetchLeavesFromCommit(
|
||||||
|
NewAuxChanState(lc.channelState), *diskCommit,
|
||||||
|
*commitKeys.GetForParty(whoseCommit),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
).Unpack()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to fetch aux leaves: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// With the key rings re-created, we'll now convert all the on-disk
|
// With the key rings re-created, we'll now convert all the on-disk
|
||||||
// HTLC"s into PaymentDescriptor's so we can re-insert them into our
|
// HTLC"s into PaymentDescriptor's so we can re-insert them into our
|
||||||
// update log.
|
// update log.
|
||||||
incomingHtlcs, outgoingHtlcs, err := lc.extractPayDescs(
|
incomingHtlcs, outgoingHtlcs, err := lc.extractPayDescs(
|
||||||
chainfee.SatPerKWeight(diskCommit.FeePerKw),
|
chainfee.SatPerKWeight(diskCommit.FeePerKw),
|
||||||
diskCommit.Htlcs, commitKeys, whoseCommit,
|
diskCommit.Htlcs, commitKeys, whoseCommit, auxResult.AuxLeaves,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1091,7 +1119,8 @@ func (lc *LightningChannel) ResetState() {
|
||||||
func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
||||||
remoteUpdateLog *updateLog, commitHeight uint64,
|
remoteUpdateLog *updateLog, commitHeight uint64,
|
||||||
feeRate chainfee.SatPerKWeight, remoteCommitKeys *CommitmentKeyRing,
|
feeRate chainfee.SatPerKWeight, remoteCommitKeys *CommitmentKeyRing,
|
||||||
remoteDustLimit btcutil.Amount) (*PaymentDescriptor, error) {
|
remoteDustLimit btcutil.Amount,
|
||||||
|
auxLeaves fn.Option[CommitAuxLeaves]) (*PaymentDescriptor, error) {
|
||||||
|
|
||||||
// Depending on the type of update message we'll map that to a distinct
|
// Depending on the type of update message we'll map that to a distinct
|
||||||
// PaymentDescriptor instance.
|
// PaymentDescriptor instance.
|
||||||
|
@ -1127,10 +1156,17 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
||||||
feeRate, wireMsg.Amount.ToSatoshis(), remoteDustLimit,
|
feeRate, wireMsg.Amount.ToSatoshis(), remoteDustLimit,
|
||||||
)
|
)
|
||||||
if !isDustRemote {
|
if !isDustRemote {
|
||||||
|
auxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
leaves := l.OutgoingHtlcLeaves
|
||||||
|
return leaves[pd.HtlcIndex].AuxTapLeaf
|
||||||
|
},
|
||||||
|
)(auxLeaves)
|
||||||
|
|
||||||
scriptInfo, err := genHtlcScript(
|
scriptInfo, err := genHtlcScript(
|
||||||
lc.channelState.ChanType, false, lntypes.Remote,
|
lc.channelState.ChanType, false, lntypes.Remote,
|
||||||
wireMsg.Expiry, wireMsg.PaymentHash,
|
wireMsg.Expiry, wireMsg.PaymentHash,
|
||||||
remoteCommitKeys,
|
remoteCommitKeys, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1791,6 +1827,19 @@ func (lc *LightningChannel) restorePendingLocalUpdates(
|
||||||
pendingCommit := pendingRemoteCommitDiff.Commitment
|
pendingCommit := pendingRemoteCommitDiff.Commitment
|
||||||
pendingHeight := pendingCommit.CommitHeight
|
pendingHeight := pendingCommit.CommitHeight
|
||||||
|
|
||||||
|
auxResult, err := fn.MapOptionZ(
|
||||||
|
lc.leafStore,
|
||||||
|
func(s AuxLeafStore) fn.Result[CommitDiffAuxResult] {
|
||||||
|
return s.FetchLeavesFromCommit(
|
||||||
|
NewAuxChanState(lc.channelState), pendingCommit,
|
||||||
|
*pendingRemoteKeys,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
).Unpack()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to fetch aux leaves: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// If we did have a dangling commit, then we'll examine which updates
|
// If we did have a dangling commit, then we'll examine which updates
|
||||||
// we included in that state and re-insert them into our update log.
|
// we included in that state and re-insert them into our update log.
|
||||||
for _, logUpdate := range pendingRemoteCommitDiff.LogUpdates {
|
for _, logUpdate := range pendingRemoteCommitDiff.LogUpdates {
|
||||||
|
@ -1801,6 +1850,7 @@ func (lc *LightningChannel) restorePendingLocalUpdates(
|
||||||
chainfee.SatPerKWeight(pendingCommit.FeePerKw),
|
chainfee.SatPerKWeight(pendingCommit.FeePerKw),
|
||||||
pendingRemoteKeys,
|
pendingRemoteKeys,
|
||||||
lc.channelState.RemoteChanCfg.DustLimit,
|
lc.channelState.RemoteChanCfg.DustLimit,
|
||||||
|
auxResult.AuxLeaves,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -2007,24 +2057,40 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
||||||
leaseExpiry = chanState.ThawHeight
|
leaseExpiry = chanState.ThawHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): Actually fetch aux leaves (later commits in this PR).
|
auxResult, err := fn.MapOptionZ(
|
||||||
|
leafStore, func(s AuxLeafStore) fn.Result[CommitDiffAuxResult] {
|
||||||
|
return s.FetchLeavesFromRevocation(revokedLog)
|
||||||
|
},
|
||||||
|
).Unpack()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to fetch aux leaves: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Since it is the remote breach we are reconstructing, the output
|
// Since it is the remote breach we are reconstructing, the output
|
||||||
// going to us will be a to-remote script with our local params.
|
// going to us will be a to-remote script with our local params.
|
||||||
|
remoteAuxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return l.RemoteAuxLeaf
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
isRemoteInitiator := !chanState.IsInitiator
|
isRemoteInitiator := !chanState.IsInitiator
|
||||||
ourScript, ourDelay, err := CommitScriptToRemote(
|
ourScript, ourDelay, err := CommitScriptToRemote(
|
||||||
chanState.ChanType, isRemoteInitiator, keyRing.ToRemoteKey,
|
chanState.ChanType, isRemoteInitiator, keyRing.ToRemoteKey,
|
||||||
leaseExpiry, input.NoneTapLeaf(),
|
leaseExpiry, remoteAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
localAuxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return l.LocalAuxLeaf
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
theirDelay := uint32(chanState.RemoteChanCfg.CsvDelay)
|
theirDelay := uint32(chanState.RemoteChanCfg.CsvDelay)
|
||||||
theirScript, err := CommitScriptToSelf(
|
theirScript, err := CommitScriptToSelf(
|
||||||
chanState.ChanType, isRemoteInitiator, keyRing.ToLocalKey,
|
chanState.ChanType, isRemoteInitiator, keyRing.ToLocalKey,
|
||||||
keyRing.RevocationKey, theirDelay, leaseExpiry,
|
keyRing.RevocationKey, theirDelay, leaseExpiry, localAuxLeaf,
|
||||||
input.NoneTapLeaf(),
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2042,7 +2108,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
||||||
if revokedLog != nil {
|
if revokedLog != nil {
|
||||||
br, ourAmt, theirAmt, err = createBreachRetribution(
|
br, ourAmt, theirAmt, err = createBreachRetribution(
|
||||||
revokedLog, spendTx, chanState, keyRing,
|
revokedLog, spendTx, chanState, keyRing,
|
||||||
commitmentSecret, leaseExpiry,
|
commitmentSecret, leaseExpiry, auxResult.AuxLeaves,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2176,7 +2242,8 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
||||||
func createHtlcRetribution(chanState *channeldb.OpenChannel,
|
func createHtlcRetribution(chanState *channeldb.OpenChannel,
|
||||||
keyRing *CommitmentKeyRing, commitHash chainhash.Hash,
|
keyRing *CommitmentKeyRing, commitHash chainhash.Hash,
|
||||||
commitmentSecret *btcec.PrivateKey, leaseExpiry uint32,
|
commitmentSecret *btcec.PrivateKey, leaseExpiry uint32,
|
||||||
htlc *channeldb.HTLCEntry) (HtlcRetribution, error) {
|
htlc *channeldb.HTLCEntry,
|
||||||
|
auxLeaves fn.Option[CommitAuxLeaves]) (HtlcRetribution, error) {
|
||||||
|
|
||||||
var emptyRetribution HtlcRetribution
|
var emptyRetribution HtlcRetribution
|
||||||
|
|
||||||
|
@ -2186,10 +2253,24 @@ func createHtlcRetribution(chanState *channeldb.OpenChannel,
|
||||||
// We'll generate the original second level witness script now, as
|
// We'll generate the original second level witness script now, as
|
||||||
// we'll need it if we're revoking an HTLC output on the remote
|
// we'll need it if we're revoking an HTLC output on the remote
|
||||||
// commitment transaction, and *they* go to the second level.
|
// commitment transaction, and *they* go to the second level.
|
||||||
|
secondLevelAuxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) fn.Option[input.AuxTapLeaf] {
|
||||||
|
return fn.MapOption(func(val uint16) input.AuxTapLeaf {
|
||||||
|
idx := input.HtlcIndex(val)
|
||||||
|
|
||||||
|
if htlc.Incoming.Val {
|
||||||
|
leaves := l.IncomingHtlcLeaves[idx]
|
||||||
|
return leaves.SecondLevelLeaf
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.OutgoingHtlcLeaves[idx].SecondLevelLeaf
|
||||||
|
})(htlc.HtlcIndex.ValOpt())
|
||||||
|
},
|
||||||
|
)(auxLeaves)
|
||||||
secondLevelScript, err := SecondLevelHtlcScript(
|
secondLevelScript, err := SecondLevelHtlcScript(
|
||||||
chanState.ChanType, isRemoteInitiator,
|
chanState.ChanType, isRemoteInitiator,
|
||||||
keyRing.RevocationKey, keyRing.ToLocalKey, theirDelay,
|
keyRing.RevocationKey, keyRing.ToLocalKey, theirDelay,
|
||||||
leaseExpiry,
|
leaseExpiry, fn.FlattenOption(secondLevelAuxLeaf),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return emptyRetribution, err
|
return emptyRetribution, err
|
||||||
|
@ -2200,9 +2281,24 @@ func createHtlcRetribution(chanState *channeldb.OpenChannel,
|
||||||
// HTLC script. Otherwise, is this was an outgoing HTLC that we sent,
|
// HTLC script. Otherwise, is this was an outgoing HTLC that we sent,
|
||||||
// then from the PoV of the remote commitment state, they're the
|
// then from the PoV of the remote commitment state, they're the
|
||||||
// receiver of this HTLC.
|
// receiver of this HTLC.
|
||||||
|
htlcLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) fn.Option[input.AuxTapLeaf] {
|
||||||
|
return fn.MapOption(func(val uint16) input.AuxTapLeaf {
|
||||||
|
idx := input.HtlcIndex(val)
|
||||||
|
|
||||||
|
if htlc.Incoming.Val {
|
||||||
|
leaves := l.IncomingHtlcLeaves[idx]
|
||||||
|
return leaves.AuxTapLeaf
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.OutgoingHtlcLeaves[idx].AuxTapLeaf
|
||||||
|
})(htlc.HtlcIndex.ValOpt())
|
||||||
|
},
|
||||||
|
)(auxLeaves)
|
||||||
scriptInfo, err := genHtlcScript(
|
scriptInfo, err := genHtlcScript(
|
||||||
chanState.ChanType, htlc.Incoming.Val, lntypes.Remote,
|
chanState.ChanType, htlc.Incoming.Val, lntypes.Remote,
|
||||||
htlc.RefundTimeout.Val, htlc.RHash.Val, keyRing,
|
htlc.RefundTimeout.Val, htlc.RHash.Val, keyRing,
|
||||||
|
fn.FlattenOption(htlcLeaf),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return emptyRetribution, err
|
return emptyRetribution, err
|
||||||
|
@ -2266,7 +2362,9 @@ func createHtlcRetribution(chanState *channeldb.OpenChannel,
|
||||||
func createBreachRetribution(revokedLog *channeldb.RevocationLog,
|
func createBreachRetribution(revokedLog *channeldb.RevocationLog,
|
||||||
spendTx *wire.MsgTx, chanState *channeldb.OpenChannel,
|
spendTx *wire.MsgTx, chanState *channeldb.OpenChannel,
|
||||||
keyRing *CommitmentKeyRing, commitmentSecret *btcec.PrivateKey,
|
keyRing *CommitmentKeyRing, commitmentSecret *btcec.PrivateKey,
|
||||||
leaseExpiry uint32) (*BreachRetribution, int64, int64, error) {
|
leaseExpiry uint32,
|
||||||
|
auxLeaves fn.Option[CommitAuxLeaves]) (*BreachRetribution, int64, int64,
|
||||||
|
error) {
|
||||||
|
|
||||||
commitHash := revokedLog.CommitTxHash
|
commitHash := revokedLog.CommitTxHash
|
||||||
|
|
||||||
|
@ -2275,7 +2373,7 @@ func createBreachRetribution(revokedLog *channeldb.RevocationLog,
|
||||||
for i, htlc := range revokedLog.HTLCEntries {
|
for i, htlc := range revokedLog.HTLCEntries {
|
||||||
hr, err := createHtlcRetribution(
|
hr, err := createHtlcRetribution(
|
||||||
chanState, keyRing, commitHash.Val,
|
chanState, keyRing, commitHash.Val,
|
||||||
commitmentSecret, leaseExpiry, htlc,
|
commitmentSecret, leaseExpiry, htlc, auxLeaves,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, err
|
return nil, 0, 0, err
|
||||||
|
@ -2427,6 +2525,7 @@ func createBreachRetributionLegacy(revokedLog *channeldb.ChannelCommitment,
|
||||||
hr, err := createHtlcRetribution(
|
hr, err := createHtlcRetribution(
|
||||||
chanState, keyRing, commitHash,
|
chanState, keyRing, commitHash,
|
||||||
commitmentSecret, leaseExpiry, entry,
|
commitmentSecret, leaseExpiry, entry,
|
||||||
|
fn.None[CommitAuxLeaves](),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, err
|
return nil, 0, 0, err
|
||||||
|
@ -3041,13 +3140,27 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
||||||
// With the keys generated, we'll make a slice with enough capacity to
|
// With the keys generated, we'll make a slice with enough capacity to
|
||||||
// hold potentially all the HTLCs. The actual slice may be a bit
|
// hold potentially all the HTLCs. The actual slice may be a bit
|
||||||
// smaller (than its total capacity) and some HTLCs may be dust.
|
// smaller (than its total capacity) and some HTLCs may be dust.
|
||||||
numSigs := (len(remoteCommitView.incomingHTLCs) +
|
numSigs := len(remoteCommitView.incomingHTLCs) +
|
||||||
len(remoteCommitView.outgoingHTLCs))
|
len(remoteCommitView.outgoingHTLCs)
|
||||||
sigBatch := make([]SignJob, 0, numSigs)
|
sigBatch := make([]SignJob, 0, numSigs)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
cancelChan := make(chan struct{})
|
cancelChan := make(chan struct{})
|
||||||
|
|
||||||
|
auxResult, err := fn.MapOptionZ(
|
||||||
|
leafStore, func(s AuxLeafStore) fn.Result[CommitDiffAuxResult] {
|
||||||
|
return s.FetchLeavesFromCommit(
|
||||||
|
NewAuxChanState(chanState),
|
||||||
|
*remoteCommitView.toDiskCommit(lntypes.Remote),
|
||||||
|
*keyRing,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
).Unpack()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to fetch aux leaves: %w",
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
|
||||||
// For each outgoing and incoming HTLC, if the HTLC isn't considered a
|
// For each outgoing and incoming HTLC, if the HTLC isn't considered a
|
||||||
// dust output after taking into account second-level HTLC fees, then a
|
// dust output after taking into account second-level HTLC fees, then a
|
||||||
// sigJob will be generated and appended to the current batch.
|
// sigJob will be generated and appended to the current batch.
|
||||||
|
@ -3074,6 +3187,13 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
||||||
htlcFee := HtlcTimeoutFee(chanType, feePerKw)
|
htlcFee := HtlcTimeoutFee(chanType, feePerKw)
|
||||||
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
||||||
|
|
||||||
|
auxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
leaves := l.IncomingHtlcLeaves
|
||||||
|
return leaves[htlc.HtlcIndex].SecondLevelLeaf
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
|
|
||||||
// With the fee calculate, we can properly create the HTLC
|
// With the fee calculate, we can properly create the HTLC
|
||||||
// timeout transaction using the HTLC amount minus the fee.
|
// timeout transaction using the HTLC amount minus the fee.
|
||||||
op := wire.OutPoint{
|
op := wire.OutPoint{
|
||||||
|
@ -3084,11 +3204,15 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
||||||
chanType, isRemoteInitiator, op, outputAmt,
|
chanType, isRemoteInitiator, op, outputAmt,
|
||||||
htlc.Timeout, uint32(remoteChanCfg.CsvDelay),
|
htlc.Timeout, uint32(remoteChanCfg.CsvDelay),
|
||||||
leaseExpiry, keyRing.RevocationKey, keyRing.ToLocalKey,
|
leaseExpiry, keyRing.RevocationKey, keyRing.ToLocalKey,
|
||||||
|
auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(roasbeef): hook up signer interface here (later commit
|
||||||
|
// in this PR).
|
||||||
|
|
||||||
// Construct a full hash cache as we may be signing a segwit v1
|
// Construct a full hash cache as we may be signing a segwit v1
|
||||||
// sighash.
|
// sighash.
|
||||||
txOut := remoteCommitView.txn.TxOut[htlc.remoteOutputIndex]
|
txOut := remoteCommitView.txn.TxOut[htlc.remoteOutputIndex]
|
||||||
|
@ -3115,7 +3239,8 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
||||||
// If this is a taproot channel, then we'll need to set the
|
// If this is a taproot channel, then we'll need to set the
|
||||||
// method type to ensure we generate a valid signature.
|
// method type to ensure we generate a valid signature.
|
||||||
if chanType.IsTaproot() {
|
if chanType.IsTaproot() {
|
||||||
sigJob.SignDesc.SignMethod = input.TaprootScriptSpendSignMethod //nolint:lll
|
//nolint:lll
|
||||||
|
sigJob.SignDesc.SignMethod = input.TaprootScriptSpendSignMethod
|
||||||
}
|
}
|
||||||
|
|
||||||
sigBatch = append(sigBatch, sigJob)
|
sigBatch = append(sigBatch, sigJob)
|
||||||
|
@ -3141,6 +3266,13 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
||||||
htlcFee := HtlcSuccessFee(chanType, feePerKw)
|
htlcFee := HtlcSuccessFee(chanType, feePerKw)
|
||||||
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
||||||
|
|
||||||
|
auxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
leaves := l.OutgoingHtlcLeaves
|
||||||
|
return leaves[htlc.HtlcIndex].SecondLevelLeaf
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
|
|
||||||
// With the proper output amount calculated, we can now
|
// With the proper output amount calculated, we can now
|
||||||
// generate the success transaction using the remote party's
|
// generate the success transaction using the remote party's
|
||||||
// CSV delay.
|
// CSV delay.
|
||||||
|
@ -3152,6 +3284,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
||||||
chanType, isRemoteInitiator, op, outputAmt,
|
chanType, isRemoteInitiator, op, outputAmt,
|
||||||
uint32(remoteChanCfg.CsvDelay), leaseExpiry,
|
uint32(remoteChanCfg.CsvDelay), leaseExpiry,
|
||||||
keyRing.RevocationKey, keyRing.ToLocalKey,
|
keyRing.RevocationKey, keyRing.ToLocalKey,
|
||||||
|
auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -4491,10 +4624,24 @@ func genHtlcSigValidationJobs(chanState *channeldb.OpenChannel,
|
||||||
// enough capacity to hold verification jobs for all HTLC's in this
|
// enough capacity to hold verification jobs for all HTLC's in this
|
||||||
// view. In the case that we have some dust outputs, then the actual
|
// view. In the case that we have some dust outputs, then the actual
|
||||||
// length will be smaller than the total capacity.
|
// length will be smaller than the total capacity.
|
||||||
numHtlcs := (len(localCommitmentView.incomingHTLCs) +
|
numHtlcs := len(localCommitmentView.incomingHTLCs) +
|
||||||
len(localCommitmentView.outgoingHTLCs))
|
len(localCommitmentView.outgoingHTLCs)
|
||||||
verifyJobs := make([]VerifyJob, 0, numHtlcs)
|
verifyJobs := make([]VerifyJob, 0, numHtlcs)
|
||||||
|
|
||||||
|
auxResult, err := fn.MapOptionZ(
|
||||||
|
leafStore, func(s AuxLeafStore) fn.Result[CommitDiffAuxResult] {
|
||||||
|
return s.FetchLeavesFromCommit(
|
||||||
|
NewAuxChanState(chanState),
|
||||||
|
*localCommitmentView.toDiskCommit(
|
||||||
|
lntypes.Local,
|
||||||
|
), *keyRing,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
).Unpack()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to fetch aux leaves: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// We'll iterate through each output in the commitment transaction,
|
// We'll iterate through each output in the commitment transaction,
|
||||||
// populating the sigHash closure function if it's detected to be an
|
// populating the sigHash closure function if it's detected to be an
|
||||||
// HLTC output. Given the sighash, and the signing key, we'll be able
|
// HLTC output. Given the sighash, and the signing key, we'll be able
|
||||||
|
@ -4528,11 +4675,19 @@ func genHtlcSigValidationJobs(chanState *channeldb.OpenChannel,
|
||||||
htlcFee := HtlcSuccessFee(chanType, feePerKw)
|
htlcFee := HtlcSuccessFee(chanType, feePerKw)
|
||||||
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
||||||
|
|
||||||
|
auxLeaf := fn.ChainOption(func(
|
||||||
|
l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
|
||||||
|
leaves := l.IncomingHtlcLeaves
|
||||||
|
idx := htlc.HtlcIndex
|
||||||
|
return leaves[idx].SecondLevelLeaf
|
||||||
|
})(auxResult.AuxLeaves)
|
||||||
|
|
||||||
successTx, err := CreateHtlcSuccessTx(
|
successTx, err := CreateHtlcSuccessTx(
|
||||||
chanType, isLocalInitiator, op,
|
chanType, isLocalInitiator, op,
|
||||||
outputAmt, uint32(localChanCfg.CsvDelay),
|
outputAmt, uint32(localChanCfg.CsvDelay),
|
||||||
leaseExpiry, keyRing.RevocationKey,
|
leaseExpiry, keyRing.RevocationKey,
|
||||||
keyRing.ToLocalKey,
|
keyRing.ToLocalKey, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -4612,12 +4767,20 @@ func genHtlcSigValidationJobs(chanState *channeldb.OpenChannel,
|
||||||
htlcFee := HtlcTimeoutFee(chanType, feePerKw)
|
htlcFee := HtlcTimeoutFee(chanType, feePerKw)
|
||||||
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
outputAmt := htlc.Amount.ToSatoshis() - htlcFee
|
||||||
|
|
||||||
|
auxLeaf := fn.ChainOption(func(
|
||||||
|
l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
|
||||||
|
leaves := l.OutgoingHtlcLeaves
|
||||||
|
idx := htlc.HtlcIndex
|
||||||
|
return leaves[idx].SecondLevelLeaf
|
||||||
|
})(auxResult.AuxLeaves)
|
||||||
|
|
||||||
timeoutTx, err := CreateHtlcTimeoutTx(
|
timeoutTx, err := CreateHtlcTimeoutTx(
|
||||||
chanType, isLocalInitiator, op,
|
chanType, isLocalInitiator, op,
|
||||||
outputAmt, htlc.Timeout,
|
outputAmt, htlc.Timeout,
|
||||||
uint32(localChanCfg.CsvDelay),
|
uint32(localChanCfg.CsvDelay),
|
||||||
leaseExpiry, keyRing.RevocationKey,
|
leaseExpiry, keyRing.RevocationKey,
|
||||||
keyRing.ToLocalKey,
|
keyRing.ToLocalKey, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -6332,6 +6495,18 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel,
|
||||||
&chanState.LocalChanCfg, &chanState.RemoteChanCfg,
|
&chanState.LocalChanCfg, &chanState.RemoteChanCfg,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
auxResult, err := fn.MapOptionZ(
|
||||||
|
leafStore, func(s AuxLeafStore) fn.Result[CommitDiffAuxResult] {
|
||||||
|
return s.FetchLeavesFromCommit(
|
||||||
|
NewAuxChanState(chanState), remoteCommit,
|
||||||
|
*keyRing,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
).Unpack()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to fetch aux leaves: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Next, we'll obtain HTLC resolutions for all the outgoing HTLC's we
|
// Next, we'll obtain HTLC resolutions for all the outgoing HTLC's we
|
||||||
// had on their commitment transaction.
|
// had on their commitment transaction.
|
||||||
var leaseExpiry uint32
|
var leaseExpiry uint32
|
||||||
|
@ -6344,6 +6519,7 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel,
|
||||||
signer, remoteCommit.Htlcs, keyRing, &chanState.LocalChanCfg,
|
signer, remoteCommit.Htlcs, keyRing, &chanState.LocalChanCfg,
|
||||||
&chanState.RemoteChanCfg, commitSpend.SpendingTx,
|
&chanState.RemoteChanCfg, commitSpend.SpendingTx,
|
||||||
chanState.ChanType, isRemoteInitiator, leaseExpiry,
|
chanState.ChanType, isRemoteInitiator, leaseExpiry,
|
||||||
|
auxResult.AuxLeaves,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to create htlc "+
|
return nil, fmt.Errorf("unable to create htlc "+
|
||||||
|
@ -6352,14 +6528,17 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel,
|
||||||
|
|
||||||
commitTxBroadcast := commitSpend.SpendingTx
|
commitTxBroadcast := commitSpend.SpendingTx
|
||||||
|
|
||||||
// TODO(roasbeef): Actually fetch aux leaves (later commits in this PR).
|
|
||||||
|
|
||||||
// Before we can generate the proper sign descriptor, we'll need to
|
// Before we can generate the proper sign descriptor, we'll need to
|
||||||
// locate the output index of our non-delayed output on the commitment
|
// locate the output index of our non-delayed output on the commitment
|
||||||
// transaction.
|
// transaction.
|
||||||
|
remoteAuxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return l.RemoteAuxLeaf
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
selfScript, maturityDelay, err := CommitScriptToRemote(
|
selfScript, maturityDelay, err := CommitScriptToRemote(
|
||||||
chanState.ChanType, isRemoteInitiator, keyRing.ToRemoteKey,
|
chanState.ChanType, isRemoteInitiator, keyRing.ToRemoteKey,
|
||||||
leaseExpiry, input.NoneTapLeaf(),
|
leaseExpiry, remoteAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to create self commit "+
|
return nil, fmt.Errorf("unable to create self commit "+
|
||||||
|
@ -6599,7 +6778,8 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
||||||
htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||||
feePerKw chainfee.SatPerKWeight, csvDelay, leaseExpiry uint32,
|
feePerKw chainfee.SatPerKWeight, csvDelay, leaseExpiry uint32,
|
||||||
whoseCommit lntypes.ChannelParty, isCommitFromInitiator bool,
|
whoseCommit lntypes.ChannelParty, isCommitFromInitiator bool,
|
||||||
chanType channeldb.ChannelType) (*OutgoingHtlcResolution, error) {
|
chanType channeldb.ChannelType,
|
||||||
|
auxLeaves fn.Option[CommitAuxLeaves]) (*OutgoingHtlcResolution, error) {
|
||||||
|
|
||||||
op := wire.OutPoint{
|
op := wire.OutPoint{
|
||||||
Hash: commitTx.TxHash(),
|
Hash: commitTx.TxHash(),
|
||||||
|
@ -6608,9 +6788,12 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
||||||
|
|
||||||
// First, we'll re-generate the script used to send the HTLC to the
|
// First, we'll re-generate the script used to send the HTLC to the
|
||||||
// remote party within their commitment transaction.
|
// remote party within their commitment transaction.
|
||||||
|
auxLeaf := fn.ChainOption(func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return l.OutgoingHtlcLeaves[htlc.HtlcIndex].AuxTapLeaf
|
||||||
|
})(auxLeaves)
|
||||||
htlcScriptInfo, err := genHtlcScript(
|
htlcScriptInfo, err := genHtlcScript(
|
||||||
chanType, false, whoseCommit, htlc.RefundTimeout, htlc.RHash,
|
chanType, false, whoseCommit, htlc.RefundTimeout, htlc.RHash,
|
||||||
keyRing,
|
keyRing, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -6683,10 +6866,16 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
||||||
|
|
||||||
// With the fee calculated, re-construct the second level timeout
|
// With the fee calculated, re-construct the second level timeout
|
||||||
// transaction.
|
// transaction.
|
||||||
|
secondLevelAuxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
leaves := l.OutgoingHtlcLeaves
|
||||||
|
return leaves[htlc.HtlcIndex].SecondLevelLeaf
|
||||||
|
},
|
||||||
|
)(auxLeaves)
|
||||||
timeoutTx, err := CreateHtlcTimeoutTx(
|
timeoutTx, err := CreateHtlcTimeoutTx(
|
||||||
chanType, isCommitFromInitiator, op, secondLevelOutputAmt,
|
chanType, isCommitFromInitiator, op, secondLevelOutputAmt,
|
||||||
htlc.RefundTimeout, csvDelay, leaseExpiry, keyRing.RevocationKey,
|
htlc.RefundTimeout, csvDelay, leaseExpiry,
|
||||||
keyRing.ToLocalKey,
|
keyRing.RevocationKey, keyRing.ToLocalKey, secondLevelAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -6769,6 +6958,7 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
||||||
htlcSweepScript, err = SecondLevelHtlcScript(
|
htlcSweepScript, err = SecondLevelHtlcScript(
|
||||||
chanType, isCommitFromInitiator, keyRing.RevocationKey,
|
chanType, isCommitFromInitiator, keyRing.RevocationKey,
|
||||||
keyRing.ToLocalKey, csvDelay, leaseExpiry,
|
keyRing.ToLocalKey, csvDelay, leaseExpiry,
|
||||||
|
secondLevelAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -6777,7 +6967,7 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
||||||
//nolint:lll
|
//nolint:lll
|
||||||
secondLevelScriptTree, err := input.TaprootSecondLevelScriptTree(
|
secondLevelScriptTree, err := input.TaprootSecondLevelScriptTree(
|
||||||
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay,
|
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay,
|
||||||
fn.None[txscript.TapLeaf](),
|
secondLevelAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -6852,8 +7042,8 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||||
htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||||
feePerKw chainfee.SatPerKWeight, csvDelay, leaseExpiry uint32,
|
feePerKw chainfee.SatPerKWeight, csvDelay, leaseExpiry uint32,
|
||||||
whoseCommit lntypes.ChannelParty, isCommitFromInitiator bool,
|
whoseCommit lntypes.ChannelParty, isCommitFromInitiator bool,
|
||||||
chanType channeldb.ChannelType) (
|
chanType channeldb.ChannelType,
|
||||||
*IncomingHtlcResolution, error) {
|
auxLeaves fn.Option[CommitAuxLeaves]) (*IncomingHtlcResolution, error) {
|
||||||
|
|
||||||
op := wire.OutPoint{
|
op := wire.OutPoint{
|
||||||
Hash: commitTx.TxHash(),
|
Hash: commitTx.TxHash(),
|
||||||
|
@ -6862,9 +7052,12 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||||
|
|
||||||
// First, we'll re-generate the script the remote party used to
|
// First, we'll re-generate the script the remote party used to
|
||||||
// send the HTLC to us in their commitment transaction.
|
// send the HTLC to us in their commitment transaction.
|
||||||
|
auxLeaf := fn.ChainOption(func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return l.IncomingHtlcLeaves[htlc.HtlcIndex].AuxTapLeaf
|
||||||
|
})(auxLeaves)
|
||||||
scriptInfo, err := genHtlcScript(
|
scriptInfo, err := genHtlcScript(
|
||||||
chanType, true, whoseCommit, htlc.RefundTimeout, htlc.RHash,
|
chanType, true, whoseCommit, htlc.RefundTimeout, htlc.RHash,
|
||||||
keyRing,
|
keyRing, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -6924,6 +7117,13 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secondLevelAuxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
leaves := l.IncomingHtlcLeaves
|
||||||
|
return leaves[htlc.HtlcIndex].SecondLevelLeaf
|
||||||
|
},
|
||||||
|
)(auxLeaves)
|
||||||
|
|
||||||
// Otherwise, we'll need to go to the second level to sweep this HTLC.
|
// Otherwise, we'll need to go to the second level to sweep this HTLC.
|
||||||
//
|
//
|
||||||
// First, we'll reconstruct the original HTLC success transaction,
|
// First, we'll reconstruct the original HTLC success transaction,
|
||||||
|
@ -6933,7 +7133,7 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||||
successTx, err := CreateHtlcSuccessTx(
|
successTx, err := CreateHtlcSuccessTx(
|
||||||
chanType, isCommitFromInitiator, op, secondLevelOutputAmt,
|
chanType, isCommitFromInitiator, op, secondLevelOutputAmt,
|
||||||
csvDelay, leaseExpiry, keyRing.RevocationKey,
|
csvDelay, leaseExpiry, keyRing.RevocationKey,
|
||||||
keyRing.ToLocalKey,
|
keyRing.ToLocalKey, secondLevelAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -7016,6 +7216,7 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||||
htlcSweepScript, err = SecondLevelHtlcScript(
|
htlcSweepScript, err = SecondLevelHtlcScript(
|
||||||
chanType, isCommitFromInitiator, keyRing.RevocationKey,
|
chanType, isCommitFromInitiator, keyRing.RevocationKey,
|
||||||
keyRing.ToLocalKey, csvDelay, leaseExpiry,
|
keyRing.ToLocalKey, csvDelay, leaseExpiry,
|
||||||
|
secondLevelAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -7024,7 +7225,7 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||||
//nolint:lll
|
//nolint:lll
|
||||||
secondLevelScriptTree, err := input.TaprootSecondLevelScriptTree(
|
secondLevelScriptTree, err := input.TaprootSecondLevelScriptTree(
|
||||||
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay,
|
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay,
|
||||||
fn.None[txscript.TapLeaf](),
|
secondLevelAuxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -7117,7 +7318,8 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight,
|
||||||
htlcs []channeldb.HTLC, keyRing *CommitmentKeyRing,
|
htlcs []channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||||
localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
|
localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
|
||||||
commitTx *wire.MsgTx, chanType channeldb.ChannelType,
|
commitTx *wire.MsgTx, chanType channeldb.ChannelType,
|
||||||
isCommitFromInitiator bool, leaseExpiry uint32) (*HtlcResolutions, error) {
|
isCommitFromInitiator bool, leaseExpiry uint32,
|
||||||
|
auxLeaves fn.Option[CommitAuxLeaves]) (*HtlcResolutions, error) {
|
||||||
|
|
||||||
// TODO(roasbeef): don't need to swap csv delay?
|
// TODO(roasbeef): don't need to swap csv delay?
|
||||||
dustLimit := remoteChanCfg.DustLimit
|
dustLimit := remoteChanCfg.DustLimit
|
||||||
|
@ -7150,8 +7352,9 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight,
|
||||||
// as we can satisfy the contract.
|
// as we can satisfy the contract.
|
||||||
ihr, err := newIncomingHtlcResolution(
|
ihr, err := newIncomingHtlcResolution(
|
||||||
signer, localChanCfg, commitTx, &htlc,
|
signer, localChanCfg, commitTx, &htlc,
|
||||||
keyRing, feePerKw, uint32(csvDelay), leaseExpiry,
|
keyRing, feePerKw, uint32(csvDelay),
|
||||||
whoseCommit, isCommitFromInitiator, chanType,
|
leaseExpiry, whoseCommit, isCommitFromInitiator,
|
||||||
|
chanType, auxLeaves,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("incoming resolution "+
|
return nil, fmt.Errorf("incoming resolution "+
|
||||||
|
@ -7165,7 +7368,7 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight,
|
||||||
ohr, err := newOutgoingHtlcResolution(
|
ohr, err := newOutgoingHtlcResolution(
|
||||||
signer, localChanCfg, commitTx, &htlc, keyRing,
|
signer, localChanCfg, commitTx, &htlc, keyRing,
|
||||||
feePerKw, uint32(csvDelay), leaseExpiry, whoseCommit,
|
feePerKw, uint32(csvDelay), leaseExpiry, whoseCommit,
|
||||||
isCommitFromInitiator, chanType,
|
isCommitFromInitiator, chanType, auxLeaves,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("outgoing resolution "+
|
return nil, fmt.Errorf("outgoing resolution "+
|
||||||
|
@ -7304,16 +7507,31 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel,
|
||||||
&chanState.LocalChanCfg, &chanState.RemoteChanCfg,
|
&chanState.LocalChanCfg, &chanState.RemoteChanCfg,
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(roasbeef): Actually fetch aux leaves (later commits in this PR).
|
auxResult, err := fn.MapOptionZ(
|
||||||
|
leafStore, func(s AuxLeafStore) fn.Result[CommitDiffAuxResult] {
|
||||||
|
return s.FetchLeavesFromCommit(
|
||||||
|
NewAuxChanState(chanState),
|
||||||
|
chanState.LocalCommitment, *keyRing,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
).Unpack()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to fetch aux leaves: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
var leaseExpiry uint32
|
var leaseExpiry uint32
|
||||||
if chanState.ChanType.HasLeaseExpiration() {
|
if chanState.ChanType.HasLeaseExpiration() {
|
||||||
leaseExpiry = chanState.ThawHeight
|
leaseExpiry = chanState.ThawHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
localAuxLeaf := fn.ChainOption(
|
||||||
|
func(l CommitAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return l.LocalAuxLeaf
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
toLocalScript, err := CommitScriptToSelf(
|
toLocalScript, err := CommitScriptToSelf(
|
||||||
chanState.ChanType, chanState.IsInitiator, keyRing.ToLocalKey,
|
chanState.ChanType, chanState.IsInitiator, keyRing.ToLocalKey,
|
||||||
keyRing.RevocationKey, csvTimeout, leaseExpiry,
|
keyRing.RevocationKey, csvTimeout, leaseExpiry, localAuxLeaf,
|
||||||
input.NoneTapLeaf(),
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -7404,7 +7622,7 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel,
|
||||||
chainfee.SatPerKWeight(localCommit.FeePerKw), lntypes.Local,
|
chainfee.SatPerKWeight(localCommit.FeePerKw), lntypes.Local,
|
||||||
signer, localCommit.Htlcs, keyRing, &chanState.LocalChanCfg,
|
signer, localCommit.Htlcs, keyRing, &chanState.LocalChanCfg,
|
||||||
&chanState.RemoteChanCfg, commitTx, chanState.ChanType,
|
&chanState.RemoteChanCfg, commitTx, chanState.ChanType,
|
||||||
chanState.IsInitiator, leaseExpiry,
|
chanState.IsInitiator, leaseExpiry, auxResult.AuxLeaves,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to gen htlc resolution: %w", err)
|
return nil, fmt.Errorf("unable to gen htlc resolution: %w", err)
|
||||||
|
|
|
@ -9971,7 +9971,7 @@ func TestCreateHtlcRetribution(t *testing.T) {
|
||||||
// Create the htlc retribution.
|
// Create the htlc retribution.
|
||||||
hr, err := createHtlcRetribution(
|
hr, err := createHtlcRetribution(
|
||||||
aliceChannel.channelState, keyRing, commitHash,
|
aliceChannel.channelState, keyRing, commitHash,
|
||||||
dummyPrivate, leaseExpiry, htlc,
|
dummyPrivate, leaseExpiry, htlc, fn.None[CommitAuxLeaves](),
|
||||||
)
|
)
|
||||||
// Expect no error.
|
// Expect no error.
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -10177,6 +10177,7 @@ func TestCreateBreachRetribution(t *testing.T) {
|
||||||
tc.revocationLog, tx,
|
tc.revocationLog, tx,
|
||||||
aliceChannel.channelState, keyRing,
|
aliceChannel.channelState, keyRing,
|
||||||
dummyPrivate, leaseExpiry,
|
dummyPrivate, leaseExpiry,
|
||||||
|
fn.None[CommitAuxLeaves](),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check the error if expected.
|
// Check the error if expected.
|
||||||
|
@ -10295,7 +10296,7 @@ func testNewBreachRetribution(t *testing.T, chanType channeldb.ChannelType) {
|
||||||
// error as there are no past delta state saved as revocation logs yet.
|
// error as there are no past delta state saved as revocation logs yet.
|
||||||
_, err = NewBreachRetribution(
|
_, err = NewBreachRetribution(
|
||||||
aliceChannel.channelState, stateNum, breachHeight, breachTx,
|
aliceChannel.channelState, stateNum, breachHeight, breachTx,
|
||||||
fn.None[AuxLeafStore](),
|
fn.Some[AuxLeafStore](&MockAuxLeafStore{}),
|
||||||
)
|
)
|
||||||
require.ErrorIs(t, err, channeldb.ErrNoPastDeltas)
|
require.ErrorIs(t, err, channeldb.ErrNoPastDeltas)
|
||||||
|
|
||||||
|
@ -10303,7 +10304,7 @@ func testNewBreachRetribution(t *testing.T, chanType channeldb.ChannelType) {
|
||||||
// provided.
|
// provided.
|
||||||
_, err = NewBreachRetribution(
|
_, err = NewBreachRetribution(
|
||||||
aliceChannel.channelState, stateNum, breachHeight, nil,
|
aliceChannel.channelState, stateNum, breachHeight, nil,
|
||||||
fn.None[AuxLeafStore](),
|
fn.Some[AuxLeafStore](&MockAuxLeafStore{}),
|
||||||
)
|
)
|
||||||
require.ErrorIs(t, err, channeldb.ErrNoPastDeltas)
|
require.ErrorIs(t, err, channeldb.ErrNoPastDeltas)
|
||||||
|
|
||||||
|
@ -10417,6 +10418,7 @@ func TestExtractPayDescs(t *testing.T) {
|
||||||
// scripts(`genHtlcScript`) as it should be tested independently.
|
// scripts(`genHtlcScript`) as it should be tested independently.
|
||||||
incomingPDs, outgoingPDs, err := lnChan.extractPayDescs(
|
incomingPDs, outgoingPDs, err := lnChan.extractPayDescs(
|
||||||
0, htlcs, lntypes.Dual[*CommitmentKeyRing]{}, lntypes.Local,
|
0, htlcs, lntypes.Dual[*CommitmentKeyRing]{}, lntypes.Local,
|
||||||
|
fn.None[CommitAuxLeaves](),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
@ -420,14 +420,14 @@ func sweepSigHash(chanType channeldb.ChannelType) txscript.SigHashType {
|
||||||
// argument should correspond to the owner of the commitment transaction which
|
// argument should correspond to the owner of the commitment transaction which
|
||||||
// we are generating the to_local script for.
|
// we are generating the to_local script for.
|
||||||
func SecondLevelHtlcScript(chanType channeldb.ChannelType, initiator bool,
|
func SecondLevelHtlcScript(chanType channeldb.ChannelType, initiator bool,
|
||||||
revocationKey, delayKey *btcec.PublicKey,
|
revocationKey, delayKey *btcec.PublicKey, csvDelay, leaseExpiry uint32,
|
||||||
csvDelay, leaseExpiry uint32) (input.ScriptDescriptor, error) {
|
auxLeaf input.AuxTapLeaf) (input.ScriptDescriptor, error) {
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
// For taproot channels, the pkScript is a segwit v1 p2tr output.
|
// For taproot channels, the pkScript is a segwit v1 p2tr output.
|
||||||
case chanType.IsTaproot():
|
case chanType.IsTaproot():
|
||||||
return input.TaprootSecondLevelScriptTree(
|
return input.TaprootSecondLevelScriptTree(
|
||||||
revocationKey, delayKey, csvDelay, input.NoneTapLeaf(),
|
revocationKey, delayKey, csvDelay, auxLeaf,
|
||||||
)
|
)
|
||||||
|
|
||||||
// If we are the initiator of a leased channel, then we have an
|
// If we are the initiator of a leased channel, then we have an
|
||||||
|
@ -755,10 +755,7 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
||||||
theirBalance -= commitFeeMSat
|
theirBalance -= commitFeeMSat
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var commitTx *wire.MsgTx
|
||||||
commitTx *wire.MsgTx
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
// Before we create the commitment transaction below, we'll try to see
|
// Before we create the commitment transaction below, we'll try to see
|
||||||
// if there're any aux leaves that need to be a part of the tapscript
|
// if there're any aux leaves that need to be a part of the tapscript
|
||||||
|
@ -806,6 +803,19 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Similarly, we'll now attempt to extract the set of aux leaves for
|
||||||
|
// the set of incoming and outgoing HTLCs.
|
||||||
|
incomingAuxLeaves := fn.MapOption(
|
||||||
|
func(leaves CommitAuxLeaves) input.HtlcAuxLeaves {
|
||||||
|
return leaves.IncomingHtlcLeaves
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
|
outgoingAuxLeaves := fn.MapOption(
|
||||||
|
func(leaves CommitAuxLeaves) input.HtlcAuxLeaves {
|
||||||
|
return leaves.OutgoingHtlcLeaves
|
||||||
|
},
|
||||||
|
)(auxResult.AuxLeaves)
|
||||||
|
|
||||||
// We'll now add all the HTLC outputs to the commitment transaction.
|
// We'll now add all the HTLC outputs to the commitment transaction.
|
||||||
// Each output includes an off-chain 2-of-2 covenant clause, so we'll
|
// Each output includes an off-chain 2-of-2 covenant clause, so we'll
|
||||||
// need the objective local/remote keys for this particular commitment
|
// need the objective local/remote keys for this particular commitment
|
||||||
|
@ -826,9 +836,15 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auxLeaf := fn.ChainOption(
|
||||||
|
func(leaves input.HtlcAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return leaves[htlc.HtlcIndex].AuxTapLeaf
|
||||||
|
},
|
||||||
|
)(outgoingAuxLeaves)
|
||||||
|
|
||||||
err := addHTLC(
|
err := addHTLC(
|
||||||
commitTx, whoseCommit, false, htlc, keyRing,
|
commitTx, whoseCommit, false, htlc, keyRing,
|
||||||
cb.chanState.ChanType,
|
cb.chanState.ChanType, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -848,9 +864,15 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance,
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auxLeaf := fn.ChainOption(
|
||||||
|
func(leaves input.HtlcAuxLeaves) input.AuxTapLeaf {
|
||||||
|
return leaves[htlc.HtlcIndex].AuxTapLeaf
|
||||||
|
},
|
||||||
|
)(incomingAuxLeaves)
|
||||||
|
|
||||||
err := addHTLC(
|
err := addHTLC(
|
||||||
commitTx, whoseCommit, true, htlc, keyRing,
|
commitTx, whoseCommit, true, htlc, keyRing,
|
||||||
cb.chanState.ChanType,
|
cb.chanState.ChanType, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1128,7 +1150,7 @@ func genSegwitV0HtlcScript(chanType channeldb.ChannelType,
|
||||||
// channel.
|
// channel.
|
||||||
func GenTaprootHtlcScript(isIncoming bool, whoseCommit lntypes.ChannelParty,
|
func GenTaprootHtlcScript(isIncoming bool, whoseCommit lntypes.ChannelParty,
|
||||||
timeout uint32, rHash [32]byte, keyRing *CommitmentKeyRing,
|
timeout uint32, rHash [32]byte, keyRing *CommitmentKeyRing,
|
||||||
) (*input.HtlcScriptTree, error) {
|
auxLeaf input.AuxTapLeaf) (*input.HtlcScriptTree, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
htlcScriptTree *input.HtlcScriptTree
|
htlcScriptTree *input.HtlcScriptTree
|
||||||
|
@ -1145,8 +1167,7 @@ func GenTaprootHtlcScript(isIncoming bool, whoseCommit lntypes.ChannelParty,
|
||||||
case isIncoming && whoseCommit.IsLocal():
|
case isIncoming && whoseCommit.IsLocal():
|
||||||
htlcScriptTree, err = input.ReceiverHTLCScriptTaproot(
|
htlcScriptTree, err = input.ReceiverHTLCScriptTaproot(
|
||||||
timeout, keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
timeout, keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
||||||
keyRing.RevocationKey, rHash[:], whoseCommit,
|
keyRing.RevocationKey, rHash[:], whoseCommit, auxLeaf,
|
||||||
input.NoneTapLeaf(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// We're being paid via an HTLC by the remote party, and the HTLC is
|
// We're being paid via an HTLC by the remote party, and the HTLC is
|
||||||
|
@ -1155,8 +1176,7 @@ func GenTaprootHtlcScript(isIncoming bool, whoseCommit lntypes.ChannelParty,
|
||||||
case isIncoming && whoseCommit.IsRemote():
|
case isIncoming && whoseCommit.IsRemote():
|
||||||
htlcScriptTree, err = input.SenderHTLCScriptTaproot(
|
htlcScriptTree, err = input.SenderHTLCScriptTaproot(
|
||||||
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
||||||
keyRing.RevocationKey, rHash[:], whoseCommit,
|
keyRing.RevocationKey, rHash[:], whoseCommit, auxLeaf,
|
||||||
input.NoneTapLeaf(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// We're sending an HTLC which is being added to our commitment
|
// We're sending an HTLC which is being added to our commitment
|
||||||
|
@ -1165,8 +1185,7 @@ func GenTaprootHtlcScript(isIncoming bool, whoseCommit lntypes.ChannelParty,
|
||||||
case !isIncoming && whoseCommit.IsLocal():
|
case !isIncoming && whoseCommit.IsLocal():
|
||||||
htlcScriptTree, err = input.SenderHTLCScriptTaproot(
|
htlcScriptTree, err = input.SenderHTLCScriptTaproot(
|
||||||
keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
|
keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
|
||||||
keyRing.RevocationKey, rHash[:], whoseCommit,
|
keyRing.RevocationKey, rHash[:], whoseCommit, auxLeaf,
|
||||||
input.NoneTapLeaf(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Finally, we're paying the remote party via an HTLC, which is being
|
// Finally, we're paying the remote party via an HTLC, which is being
|
||||||
|
@ -1175,8 +1194,7 @@ func GenTaprootHtlcScript(isIncoming bool, whoseCommit lntypes.ChannelParty,
|
||||||
case !isIncoming && whoseCommit.IsRemote():
|
case !isIncoming && whoseCommit.IsRemote():
|
||||||
htlcScriptTree, err = input.ReceiverHTLCScriptTaproot(
|
htlcScriptTree, err = input.ReceiverHTLCScriptTaproot(
|
||||||
timeout, keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
|
timeout, keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
|
||||||
keyRing.RevocationKey, rHash[:], whoseCommit,
|
keyRing.RevocationKey, rHash[:], whoseCommit, auxLeaf,
|
||||||
input.NoneTapLeaf(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1191,7 +1209,8 @@ func GenTaprootHtlcScript(isIncoming bool, whoseCommit lntypes.ChannelParty,
|
||||||
// along side the multiplexer.
|
// along side the multiplexer.
|
||||||
func genHtlcScript(chanType channeldb.ChannelType, isIncoming bool,
|
func genHtlcScript(chanType channeldb.ChannelType, isIncoming bool,
|
||||||
whoseCommit lntypes.ChannelParty, timeout uint32, rHash [32]byte,
|
whoseCommit lntypes.ChannelParty, timeout uint32, rHash [32]byte,
|
||||||
keyRing *CommitmentKeyRing) (input.ScriptDescriptor, error) {
|
keyRing *CommitmentKeyRing,
|
||||||
|
auxLeaf input.AuxTapLeaf) (input.ScriptDescriptor, error) {
|
||||||
|
|
||||||
if !chanType.IsTaproot() {
|
if !chanType.IsTaproot() {
|
||||||
return genSegwitV0HtlcScript(
|
return genSegwitV0HtlcScript(
|
||||||
|
@ -1201,7 +1220,7 @@ func genHtlcScript(chanType channeldb.ChannelType, isIncoming bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenTaprootHtlcScript(
|
return GenTaprootHtlcScript(
|
||||||
isIncoming, whoseCommit, timeout, rHash, keyRing,
|
isIncoming, whoseCommit, timeout, rHash, keyRing, auxLeaf,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1214,13 +1233,15 @@ func genHtlcScript(chanType channeldb.ChannelType, isIncoming bool,
|
||||||
// the descriptor itself.
|
// the descriptor itself.
|
||||||
func addHTLC(commitTx *wire.MsgTx, whoseCommit lntypes.ChannelParty,
|
func addHTLC(commitTx *wire.MsgTx, whoseCommit lntypes.ChannelParty,
|
||||||
isIncoming bool, paymentDesc *PaymentDescriptor,
|
isIncoming bool, paymentDesc *PaymentDescriptor,
|
||||||
keyRing *CommitmentKeyRing, chanType channeldb.ChannelType) error {
|
keyRing *CommitmentKeyRing, chanType channeldb.ChannelType,
|
||||||
|
auxLeaf input.AuxTapLeaf) error {
|
||||||
|
|
||||||
timeout := paymentDesc.Timeout
|
timeout := paymentDesc.Timeout
|
||||||
rHash := paymentDesc.RHash
|
rHash := paymentDesc.RHash
|
||||||
|
|
||||||
scriptInfo, err := genHtlcScript(
|
scriptInfo, err := genHtlcScript(
|
||||||
chanType, isIncoming, whoseCommit, timeout, rHash, keyRing,
|
chanType, isIncoming, whoseCommit, timeout, rHash, keyRing,
|
||||||
|
auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -50,8 +51,8 @@ var (
|
||||||
// - <sender sig> <receiver sig> <preimage> <success_script> <control_block>
|
// - <sender sig> <receiver sig> <preimage> <success_script> <control_block>
|
||||||
func CreateHtlcSuccessTx(chanType channeldb.ChannelType, initiator bool,
|
func CreateHtlcSuccessTx(chanType channeldb.ChannelType, initiator bool,
|
||||||
htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, csvDelay,
|
htlcOutput wire.OutPoint, htlcAmt btcutil.Amount, csvDelay,
|
||||||
leaseExpiry uint32, revocationKey, delayKey *btcec.PublicKey) (
|
leaseExpiry uint32, revocationKey, delayKey *btcec.PublicKey,
|
||||||
*wire.MsgTx, error) {
|
auxLeaf input.AuxTapLeaf) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
// Create a version two transaction (as the success version of this
|
// Create a version two transaction (as the success version of this
|
||||||
// spends an output with a CSV timeout).
|
// spends an output with a CSV timeout).
|
||||||
|
@ -71,7 +72,7 @@ func CreateHtlcSuccessTx(chanType channeldb.ChannelType, initiator bool,
|
||||||
// HTLC outputs.
|
// HTLC outputs.
|
||||||
scriptInfo, err := SecondLevelHtlcScript(
|
scriptInfo, err := SecondLevelHtlcScript(
|
||||||
chanType, initiator, revocationKey, delayKey, csvDelay,
|
chanType, initiator, revocationKey, delayKey, csvDelay,
|
||||||
leaseExpiry,
|
leaseExpiry, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -110,7 +111,8 @@ func CreateHtlcSuccessTx(chanType channeldb.ChannelType, initiator bool,
|
||||||
func CreateHtlcTimeoutTx(chanType channeldb.ChannelType, initiator bool,
|
func CreateHtlcTimeoutTx(chanType channeldb.ChannelType, initiator bool,
|
||||||
htlcOutput wire.OutPoint, htlcAmt btcutil.Amount,
|
htlcOutput wire.OutPoint, htlcAmt btcutil.Amount,
|
||||||
cltvExpiry, csvDelay, leaseExpiry uint32,
|
cltvExpiry, csvDelay, leaseExpiry uint32,
|
||||||
revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) {
|
revocationKey, delayKey *btcec.PublicKey,
|
||||||
|
auxLeaf input.AuxTapLeaf) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
// Create a version two transaction (as the success version of this
|
// Create a version two transaction (as the success version of this
|
||||||
// spends an output with a CSV timeout), and set the lock-time to the
|
// spends an output with a CSV timeout), and set the lock-time to the
|
||||||
|
@ -134,7 +136,7 @@ func CreateHtlcTimeoutTx(chanType channeldb.ChannelType, initiator bool,
|
||||||
// HTLC outputs.
|
// HTLC outputs.
|
||||||
scriptInfo, err := SecondLevelHtlcScript(
|
scriptInfo, err := SecondLevelHtlcScript(
|
||||||
chanType, initiator, revocationKey, delayKey, csvDelay,
|
chanType, initiator, revocationKey, delayKey, csvDelay,
|
||||||
leaseExpiry,
|
leaseExpiry, auxLeaf,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
Loading…
Add table
Reference in a new issue