Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 67 additions & 16 deletions contractcourt/chain_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@ type chainWatcher struct {
// the current state number on the commitment transactions.
stateHintObfuscator [lnwallet.StateHintSize]byte

// fundingPkScript is the pkScript of the funding output.
fundingPkScript []byte

// heightHint is the height hint used to checkpoint scans on chain for
// conf/spend events.
heightHint uint32

// All the fields below are protected by this mutex.
sync.Mutex

Expand Down Expand Up @@ -267,9 +274,9 @@ func (c *chainWatcher) Start() error {
// As a height hint, we'll try to use the opening height, but if the
// channel isn't yet open, then we'll use the height it was broadcast
// at. This may be an unconfirmed zero-conf channel.
heightHint := c.cfg.chanState.ShortChanID().BlockHeight
if heightHint == 0 {
heightHint = chanState.BroadcastHeight()
c.heightHint = c.cfg.chanState.ShortChanID().BlockHeight
if c.heightHint == 0 {
c.heightHint = chanState.BroadcastHeight()
}

// Since no zero-conf state is stored in a channel backup, the below
Expand All @@ -279,29 +286,43 @@ func (c *chainWatcher) Start() error {
if chanState.ZeroConfConfirmed() {
// If the zero-conf channel is confirmed, we'll use the
// confirmed SCID's block height.
heightHint = chanState.ZeroConfRealScid().BlockHeight
c.heightHint = chanState.ZeroConfRealScid().BlockHeight
} else {
// The zero-conf channel is unconfirmed. We'll need to
// use the FundingBroadcastHeight.
heightHint = chanState.BroadcastHeight()
c.heightHint = chanState.BroadcastHeight()
}
}

localKey := chanState.LocalChanCfg.MultiSigKey.PubKey.SerializeCompressed()
remoteKey := chanState.RemoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
multiSigScript, err := input.GenMultiSigScript(
localKey, remoteKey,
localKey := chanState.LocalChanCfg.MultiSigKey.PubKey
remoteKey := chanState.RemoteChanCfg.MultiSigKey.PubKey

var (
err error
)
if err != nil {
return err
}
pkScript, err := input.WitnessScriptHash(multiSigScript)
if err != nil {
return err
if chanState.ChanType.IsTaproot() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another place that would benefit from an input func that hides this switch

c.fundingPkScript, _, err = input.GenTaprootFundingScript(
localKey, remoteKey, 0,
)
if err != nil {
return err
}
} else {
multiSigScript, err := input.GenMultiSigScript(
localKey.SerializeCompressed(),
remoteKey.SerializeCompressed(),
)
if err != nil {
return err
}
c.fundingPkScript, err = input.WitnessScriptHash(multiSigScript)
if err != nil {
return err
}
}

spendNtfn, err := c.cfg.notifier.RegisterSpendNtfn(
fundingOut, pkScript, heightHint,
fundingOut, c.fundingPkScript, c.heightHint,
)
if err != nil {
return err
Expand Down Expand Up @@ -567,6 +588,33 @@ func (c *chainWatcher) closeObserver(spendNtfn *chainntnfs.SpendEvent) {
log.Infof("Close observer for ChannelPoint(%v) active",
c.cfg.chanState.FundingOutpoint)

// If this is a taproot channel, before we proceed, we want to ensure
// that the expected funding output has confirmed on chain.
if c.cfg.chanState.ChanType.IsTaproot() {
fundingPoint := c.cfg.chanState.FundingOutpoint

confNtfn, err := c.cfg.notifier.RegisterConfirmationsNtfn(
&fundingPoint.Hash, c.fundingPkScript, 1, c.heightHint,
)
if err != nil {
log.Warnf("unable to register for conf: %v", err)
}

log.Infof("Waiting for taproot ChannelPoint(%v) to confirm...",
c.cfg.chanState.FundingOutpoint)

select {
case _, ok := <-confNtfn.Confirmed:
// If the channel was closed, then this means that the
// notifier exited, so we will as well.
if !ok {
return
}
case <-c.quit:
return
}
}

select {
// We've detected a spend of the channel onchain! Depending on the type
// of spend, we'll act accordingly, so we'll examine the spending
Expand Down Expand Up @@ -833,6 +881,9 @@ func (c *chainWatcher) handlePossibleBreach(commitSpend *chainntnfs.SpendDetail,
}

// Create an AnchorResolution for the breached state.
//
// TODO(roasbeef): make keyring for taproot chans to pass in instead of
// nil
anchorRes, err := lnwallet.NewAnchorResolution(
c.cfg.chanState, commitSpend.SpendingTx, nil,
)
Expand Down
5 changes: 3 additions & 2 deletions discovery/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnpeer"
"github.com/lightningnetwork/lnd/lnwire"
)
Expand Down Expand Up @@ -42,7 +41,9 @@ func (p *mockPeer) SendMessageLazy(sync bool, msgs ...lnwire.Message) error {
return p.SendMessage(sync, msgs...)
}

func (p *mockPeer) AddNewChannel(_ *channeldb.OpenChannel, _ <-chan struct{}) error {
func (p *mockPeer) AddNewChannel(_ *lnpeer.NewChannel,
_ <-chan struct{}) error {

return nil
}
func (p *mockPeer) WipeChannel(_ *wire.OutPoint) {}
Expand Down
4 changes: 4 additions & 0 deletions feature/default_sets.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,8 @@ var defaultSetDesc = setDesc{
SetInit: {}, // I
SetNodeAnn: {}, // N
},
lnwire.SimpleTaprootChannelsOptional: {
SetInit: {}, // I
SetNodeAnn: {}, // N
},
}
4 changes: 4 additions & 0 deletions feature/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ var deps = depDesc{
lnwire.ZeroConfOptional: {
lnwire.ScidAliasOptional: {},
},
lnwire.SimpleTaprootChannelsOptional: {
lnwire.AnchorsZeroFeeHtlcTxOptional: {},
lnwire.ExplicitChannelTypeOptional: {},
},
}

// ValidateDeps asserts that a feature vector sets all features and their
Expand Down
46 changes: 46 additions & 0 deletions funding/commitment_type_negotiation.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,52 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType, local,
}
return lnwallet.CommitmentTypeTweakless, nil

// Simple taproot channels only.
case channelFeatures.OnlyContains(lnwire.SimpleTaprootChannelsRequired):

if !hasFeatures(
local, remote, lnwire.SimpleTaprootChannelsOptional,
) {

return 0, errUnsupportedChannelType
}

return lnwallet.CommitmentTypeSimpleTaproot, nil

// Simple taproot channels with scid only.
case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequired,
lnwire.ScidAliasRequired,
):

if !hasFeatures(
local, remote,
lnwire.SimpleTaprootChannelsOptional,
lnwire.ScidAliasOptional,
) {

return 0, errUnsupportedChannelType
}

return lnwallet.CommitmentTypeSimpleTaproot, nil

// Simple taproot channels with zero conf only.
case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequired,
lnwire.ZeroConfRequired,
):

if !hasFeatures(
local, remote,
lnwire.SimpleTaprootChannelsOptional,
lnwire.ZeroConfOptional,
) {

return 0, errUnsupportedChannelType
}

return lnwallet.CommitmentTypeSimpleTaproot, nil

// No features, use legacy commitment type.
case channelFeatures.IsEmpty():
return lnwallet.CommitmentTypeLegacy, nil
Expand Down
Loading