mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-22 06:21:40 +01:00
contractcourt: update UTXO nursery to support taproot chans
This commit is contained in:
parent
cdcde6e0a5
commit
7e2d04a310
2 changed files with 94 additions and 13 deletions
|
@ -10,6 +10,7 @@ import (
|
|||
"sync/atomic"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
|
@ -368,10 +369,23 @@ func (u *UtxoNursery) IncubateOutputs(chanPoint wire.OutPoint,
|
|||
// second-layer HTLC output. We effectively skip the baby stage (as the
|
||||
// timelock is zero), and enter the kid stage.
|
||||
for _, htlcRes := range incomingHtlcs {
|
||||
// Based on the input pk script of the sign descriptor, we can
|
||||
// determine if this is a taproot output or not. This'll
|
||||
// determine the witness type we try to set below.
|
||||
isTaproot := txscript.IsPayToTaproot(
|
||||
htlcRes.SweepSignDesc.Output.PkScript,
|
||||
)
|
||||
|
||||
var witType input.StandardWitnessType
|
||||
if isTaproot {
|
||||
witType = input.TaprootHtlcAcceptedSuccessSecondLevel
|
||||
} else {
|
||||
witType = input.HtlcAcceptedSuccessSecondLevel
|
||||
}
|
||||
|
||||
htlcOutput := makeKidOutput(
|
||||
&htlcRes.ClaimOutpoint, &chanPoint, htlcRes.CsvDelay,
|
||||
input.HtlcAcceptedSuccessSecondLevel,
|
||||
&htlcRes.SweepSignDesc, 0,
|
||||
witType, &htlcRes.SweepSignDesc, 0,
|
||||
)
|
||||
|
||||
if htlcOutput.Amount() > 0 {
|
||||
|
@ -396,6 +410,20 @@ func (u *UtxoNursery) IncubateOutputs(chanPoint wire.OutPoint,
|
|||
continue
|
||||
}
|
||||
|
||||
// Based on the input pk script of the sign descriptor, we can
|
||||
// determine if this is a taproot output or not. This'll
|
||||
// determine the witness type we try to set below.
|
||||
isTaproot := txscript.IsPayToTaproot(
|
||||
htlcRes.SweepSignDesc.Output.PkScript,
|
||||
)
|
||||
|
||||
var witType input.StandardWitnessType
|
||||
if isTaproot {
|
||||
witType = input.TaprootHtlcOfferedRemoteTimeout
|
||||
} else {
|
||||
witType = input.HtlcOfferedRemoteTimeout
|
||||
}
|
||||
|
||||
// Otherwise, this is actually a kid output as we can sweep it
|
||||
// once the commitment transaction confirms, and the absolute
|
||||
// CLTV lock has expired. We set the CSV delay what the
|
||||
|
@ -403,8 +431,7 @@ func (u *UtxoNursery) IncubateOutputs(chanPoint wire.OutPoint,
|
|||
// accordingly.
|
||||
htlcOutput := makeKidOutput(
|
||||
&htlcRes.ClaimOutpoint, &chanPoint, htlcRes.CsvDelay,
|
||||
input.HtlcOfferedRemoteTimeout,
|
||||
&htlcRes.SweepSignDesc, htlcRes.Expiry,
|
||||
witType, &htlcRes.SweepSignDesc, htlcRes.Expiry,
|
||||
)
|
||||
kidOutputs = append(kidOutputs, htlcOutput)
|
||||
}
|
||||
|
@ -516,13 +543,15 @@ func (u *UtxoNursery) NurseryReport(
|
|||
// confirmation of the commitment transaction.
|
||||
switch kid.WitnessType() {
|
||||
|
||||
case input.HtlcAcceptedSuccessSecondLevel:
|
||||
case input.HtlcAcceptedSuccessSecondLevel,
|
||||
input.TaprootHtlcAcceptedSuccessSecondLevel:
|
||||
// An HTLC output on our commitment transaction
|
||||
// where the second-layer transaction hasn't
|
||||
// yet confirmed.
|
||||
report.AddLimboStage1SuccessHtlc(&kid)
|
||||
|
||||
case input.HtlcOfferedRemoteTimeout:
|
||||
case input.HtlcOfferedRemoteTimeout,
|
||||
input.TaprootHtlcOfferedRemoteTimeout:
|
||||
// This is an HTLC output on the
|
||||
// commitment transaction of the remote
|
||||
// party. We are waiting for the CLTV
|
||||
|
@ -537,7 +566,8 @@ func (u *UtxoNursery) NurseryReport(
|
|||
// types.
|
||||
switch kid.WitnessType() {
|
||||
|
||||
case input.HtlcOfferedRemoteTimeout:
|
||||
case input.HtlcOfferedRemoteTimeout,
|
||||
input.TaprootHtlcOfferedRemoteTimeout:
|
||||
// This is an HTLC output on the
|
||||
// commitment transaction of the remote
|
||||
// party. The CLTV timelock has
|
||||
|
@ -545,6 +575,10 @@ func (u *UtxoNursery) NurseryReport(
|
|||
// it.
|
||||
report.AddLimboDirectHtlc(&kid)
|
||||
|
||||
case input.TaprootHtlcAcceptedSuccessSecondLevel:
|
||||
fallthrough
|
||||
case input.TaprootHtlcOfferedTimeoutSecondLevel:
|
||||
fallthrough
|
||||
case input.HtlcAcceptedSuccessSecondLevel:
|
||||
fallthrough
|
||||
case input.HtlcOfferedTimeoutSecondLevel:
|
||||
|
@ -561,10 +595,16 @@ func (u *UtxoNursery) NurseryReport(
|
|||
// balance.
|
||||
switch kid.WitnessType() {
|
||||
|
||||
case input.TaprootHtlcAcceptedSuccessSecondLevel:
|
||||
fallthrough
|
||||
case input.TaprootHtlcOfferedTimeoutSecondLevel:
|
||||
fallthrough
|
||||
case input.HtlcAcceptedSuccessSecondLevel:
|
||||
fallthrough
|
||||
case input.HtlcOfferedTimeoutSecondLevel:
|
||||
fallthrough
|
||||
case input.TaprootHtlcOfferedRemoteTimeout:
|
||||
fallthrough
|
||||
case input.HtlcOfferedRemoteTimeout:
|
||||
// This htlc output successfully
|
||||
// resides in a p2wkh output belonging
|
||||
|
@ -731,7 +771,8 @@ func (u *UtxoNursery) graduateClass(classHeight uint32) error {
|
|||
// Fetch all information about the crib and kindergarten outputs at
|
||||
// this height.
|
||||
kgtnOutputs, cribOutputs, err := u.cfg.Store.FetchClass(
|
||||
classHeight)
|
||||
classHeight,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1225,7 +1266,17 @@ func makeBabyOutput(chanPoint *wire.OutPoint,
|
|||
|
||||
htlcOutpoint := htlcResolution.ClaimOutpoint
|
||||
blocksToMaturity := htlcResolution.CsvDelay
|
||||
witnessType := input.HtlcOfferedTimeoutSecondLevel
|
||||
|
||||
isTaproot := txscript.IsPayToTaproot(
|
||||
htlcResolution.SweepSignDesc.Output.PkScript,
|
||||
)
|
||||
|
||||
var witnessType input.StandardWitnessType
|
||||
if isTaproot {
|
||||
witnessType = input.TaprootHtlcOfferedTimeoutSecondLevel
|
||||
} else {
|
||||
witnessType = input.HtlcOfferedTimeoutSecondLevel
|
||||
}
|
||||
|
||||
kid := makeKidOutput(
|
||||
&htlcOutpoint, chanPoint, blocksToMaturity, witnessType,
|
||||
|
@ -1313,6 +1364,8 @@ func makeKidOutput(outpoint, originChanPoint *wire.OutPoint,
|
|||
// transaction, or is an outgoing HTLC on the commitment transaction of
|
||||
// the remote peer.
|
||||
isHtlc := (witnessType == input.HtlcAcceptedSuccessSecondLevel ||
|
||||
witnessType == input.TaprootHtlcAcceptedSuccessSecondLevel ||
|
||||
witnessType == input.TaprootHtlcOfferedRemoteTimeout ||
|
||||
witnessType == input.HtlcOfferedRemoteTimeout)
|
||||
|
||||
// heightHint can be safely set to zero here, because after this
|
||||
|
@ -1389,7 +1442,17 @@ func (k *kidOutput) Encode(w io.Writer) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return input.WriteSignDescriptor(w, k.SignDesc())
|
||||
if err := input.WriteSignDescriptor(w, k.SignDesc()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if k.SignDesc().ControlBlock == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If this is a taproot output, then it'll also have a control block,
|
||||
// so we'll go ahead and write that now.
|
||||
return wire.WriteVarBytes(w, 1000, k.SignDesc().ControlBlock)
|
||||
}
|
||||
|
||||
// Decode takes a byte array representation of a kidOutput and converts it to an
|
||||
|
@ -1436,7 +1499,27 @@ func (k *kidOutput) Decode(r io.Reader) error {
|
|||
}
|
||||
k.witnessType = input.StandardWitnessType(byteOrder.Uint16(scratch[:2]))
|
||||
|
||||
return input.ReadSignDescriptor(r, &k.signDesc)
|
||||
if err := input.ReadSignDescriptor(r, &k.signDesc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If there's anything left in the reader, then this is a taproot
|
||||
// output that also wrote a control block.
|
||||
ctrlBlock, err := wire.ReadVarBytes(r, 0, 1000, "control block")
|
||||
switch {
|
||||
// If there're no bytes remaining, then we'll return early.
|
||||
case errors.Is(err, io.EOF):
|
||||
fallthrough
|
||||
case errors.Is(err, io.ErrUnexpectedEOF):
|
||||
return nil
|
||||
|
||||
case err != nil:
|
||||
return err
|
||||
}
|
||||
|
||||
k.signDesc.ControlBlock = ctrlBlock
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(bvu): copied from channeldb, remove repetition
|
||||
|
|
|
@ -225,8 +225,6 @@ func WriteSignDescriptor(w io.Writer, sd *SignDescriptor) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// TODO(roasbeef): also write ctrl block?
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue