Skip to content

Commit

Permalink
Merge pull request #9335 from lightningnetwork/0-18-4-branch-rc2
Browse files Browse the repository at this point in the history
release: create branch for v0.18.4-beta.rc2
  • Loading branch information
guggero authored Dec 11, 2024
2 parents c1129bb + 3447484 commit 3c08109
Show file tree
Hide file tree
Showing 27 changed files with 931 additions and 283 deletions.
2 changes: 1 addition & 1 deletion build/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const (

// AppPreRelease MUST only contain characters from semanticAlphabet per
// the semantic versioning spec.
AppPreRelease = "beta.rc1"
AppPreRelease = "beta.rc2"
)

func init() {
Expand Down
4 changes: 2 additions & 2 deletions config_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/htlcswitch"
"github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/kvdb"
Expand All @@ -46,7 +47,6 @@ import (
"github.com/lightningnetwork/lnd/lnwallet/rpcwallet"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/msgmux"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/rpcperms"
"github.com/lightningnetwork/lnd/signal"
"github.com/lightningnetwork/lnd/sqldb"
Expand Down Expand Up @@ -165,7 +165,7 @@ type AuxComponents struct {

// TrafficShaper is an optional traffic shaper that can be used to
// control the outgoing channel of a payment.
TrafficShaper fn.Option[routing.TlvTrafficShaper]
TrafficShaper fn.Option[htlcswitch.AuxTrafficShaper]

// MsgRouter is an optional message router that if set will be used in
// place of a new blank default message router.
Expand Down
37 changes: 32 additions & 5 deletions contractcourt/channel_arbitrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,20 @@ func (c *ChannelArbitrator) Start(state *chanArbStartState) error {
return err
}

c.wg.Add(1)
go c.channelAttendant(bestHeight, state.commitSet)

return nil
}

// progressStateMachineAfterRestart attempts to progress the state machine
// after a restart. This makes sure that if the state transition failed, we
// will try to progress the state machine again. Moreover it will relaunch
// resolvers if the channel is still in the pending close state and has not
// been fully resolved yet.
func (c *ChannelArbitrator) progressStateMachineAfterRestart(bestHeight int32,
commitSet *CommitSet) error {

// If the channel has been marked pending close in the database, and we
// haven't transitioned the state machine to StateContractClosed (or a
// succeeding state), then a state transition most likely failed. We'll
Expand Down Expand Up @@ -527,7 +541,7 @@ func (c *ChannelArbitrator) Start(state *chanArbStartState) error {
// on-chain state, and our set of active contracts.
startingState := c.state
nextState, _, err := c.advanceState(
triggerHeight, trigger, state.commitSet,
triggerHeight, trigger, commitSet,
)
if err != nil {
switch err {
Expand Down Expand Up @@ -564,14 +578,12 @@ func (c *ChannelArbitrator) Start(state *chanArbStartState) error {
// receive a chain event from the chain watcher that the
// commitment has been confirmed on chain, and before we
// advance our state step, we call InsertConfirmedCommitSet.
err := c.relaunchResolvers(state.commitSet, triggerHeight)
err := c.relaunchResolvers(commitSet, triggerHeight)
if err != nil {
return err
}
}

c.wg.Add(1)
go c.channelAttendant(bestHeight)
return nil
}

Expand Down Expand Up @@ -2775,13 +2787,28 @@ func (c *ChannelArbitrator) updateActiveHTLCs() {
// Nursery for incubation, and ultimate sweeping.
//
// NOTE: This MUST be run as a goroutine.
func (c *ChannelArbitrator) channelAttendant(bestHeight int32) {
//
//nolint:funlen
func (c *ChannelArbitrator) channelAttendant(bestHeight int32,
commitSet *CommitSet) {

// TODO(roasbeef): tell top chain arb we're done
defer func() {
c.wg.Done()
}()

err := c.progressStateMachineAfterRestart(bestHeight, commitSet)
if err != nil {
// In case of an error, we return early but we do not shutdown
// LND, because there might be other channels that still can be
// resolved and we don't want to interfere with that.
// We continue to run the channel attendant in case the channel
// closes via other means for example the remote pary force
// closes the channel. So we log the error and continue.
log.Errorf("Unable to progress state machine after "+
"restart: %v", err)
}

for {
select {

Expand Down
27 changes: 20 additions & 7 deletions contractcourt/channel_arbitrator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lntest/mock"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
Expand Down Expand Up @@ -1043,10 +1044,19 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) {

// Post restart, it should be the case that our resolver was properly
// supplemented, and we only have a single resolver in the final set.
if len(chanArb.activeResolvers) != 1 {
t.Fatalf("expected single resolver, instead got: %v",
len(chanArb.activeResolvers))
}
// The resolvers are added concurrently so we need to wait here.
err = wait.NoError(func() error {
chanArb.activeResolversLock.Lock()
defer chanArb.activeResolversLock.Unlock()

if len(chanArb.activeResolvers) != 1 {
return fmt.Errorf("expected single resolver, instead "+
"got: %v", len(chanArb.activeResolvers))
}

return nil
}, defaultTimeout)
require.NoError(t, err)

// We'll now examine the in-memory state of the active resolvers to
// ensure t hey were populated properly.
Expand Down Expand Up @@ -2884,9 +2894,12 @@ func TestChannelArbitratorStartForceCloseFail(t *testing.T) {
{
name: "Commitment is rejected with an " +
"unmatched error",
broadcastErr: fmt.Errorf("Reject Commitment Tx"),
expectedState: StateBroadcastCommit,
expectedStartup: false,
broadcastErr: fmt.Errorf("Reject Commitment Tx"),
expectedState: StateBroadcastCommit,
// We should still be able to start up since we other
// channels might be closing as well and we should
// resolve the contracts.
expectedStartup: true,
},

// We started after the DLP was triggered, and try to force
Expand Down
8 changes: 8 additions & 0 deletions docs/release-notes/release-notes-0.18.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@
* [Make the contract resolutions for the channel arbitrator optional](
https://github.com/lightningnetwork/lnd/pull/9253).

* [Fixed a bug](https://github.com/lightningnetwork/lnd/pull/9324) to prevent
potential deadlocks when LND depends on external components (e.g. aux
components, hooks).

* [Make sure blinded payment failures are handled correctly in the mission
controller](https://github.com/lightningnetwork/lnd/pull/9316).

# New Features

The main channel state machine and database now allow for processing and storing
Expand Down Expand Up @@ -121,4 +128,5 @@ types in a series of changes:
* George Tsagkarelis
* Olaoluwa Osuntokun
* Oliver Gugger
* Ziggie

68 changes: 58 additions & 10 deletions htlcswitch/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ const (
Outgoing LinkDirection = true
)

// OptionalBandwidth is a type alias for the result of a bandwidth query that
// may return a bandwidth value or fn.None if the bandwidth is not available or
// not applicable.
type OptionalBandwidth = fn.Option[lnwire.MilliSatoshi]

// ChannelLink is an interface which represents the subsystem for managing the
// incoming htlc requests, applying the changes to the channel, and also
// propagating/forwarding it to htlc switch.
Expand Down Expand Up @@ -255,25 +260,26 @@ type ChannelLink interface {
// in order to signal to the source of the HTLC, the policy consistency
// issue.
CheckHtlcForward(payHash [32]byte, incomingAmt lnwire.MilliSatoshi,
amtToForward lnwire.MilliSatoshi,
incomingTimeout, outgoingTimeout uint32,
inboundFee models.InboundFee,
heightNow uint32, scid lnwire.ShortChannelID) *LinkError
amtToForward lnwire.MilliSatoshi, incomingTimeout,
outgoingTimeout uint32, inboundFee models.InboundFee,
heightNow uint32, scid lnwire.ShortChannelID,
customRecords lnwire.CustomRecords) *LinkError

// CheckHtlcTransit should return a nil error if the passed HTLC details
// satisfy the current channel policy. Otherwise, a LinkError with a
// valid protocol failure message should be returned in order to signal
// the violation. This call is intended to be used for locally initiated
// payments for which there is no corresponding incoming htlc.
CheckHtlcTransit(payHash [32]byte, amt lnwire.MilliSatoshi,
timeout uint32, heightNow uint32) *LinkError
timeout uint32, heightNow uint32,
customRecords lnwire.CustomRecords) *LinkError

// Stats return the statistics of channel link. Number of updates,
// total sent/received milli-satoshis.
Stats() (uint64, lnwire.MilliSatoshi, lnwire.MilliSatoshi)

// Peer returns the serialized public key of remote peer with which we
// have the channel link opened.
// PeerPubKey returns the serialized public key of remote peer with
// which we have the channel link opened.
PeerPubKey() [33]byte

// AttachMailBox delivers an active MailBox to the link. The MailBox may
Expand All @@ -290,9 +296,18 @@ type ChannelLink interface {
// commitment of the channel that this link is associated with.
CommitmentCustomBlob() fn.Option[tlv.Blob]

// Start/Stop are used to initiate the start/stop of the channel link
// functioning.
// AuxBandwidth returns the bandwidth that can be used for a channel,
// expressed in milli-satoshi. This might be different from the regular
// BTC bandwidth for custom channels. This will always return fn.None()
// for a regular (non-custom) channel.
AuxBandwidth(amount lnwire.MilliSatoshi, cid lnwire.ShortChannelID,
htlcBlob fn.Option[tlv.Blob],
ts AuxTrafficShaper) fn.Result[OptionalBandwidth]

// Start starts the channel link.
Start() error

// Stop requests the channel link to be shut down.
Stop()
}

Expand Down Expand Up @@ -428,7 +443,7 @@ type htlcNotifier interface {
NotifyForwardingEvent(key HtlcKey, info HtlcInfo,
eventType HtlcEventType)

// NotifyIncomingLinkFailEvent notifies that a htlc has failed on our
// NotifyLinkFailEvent notifies that a htlc has failed on our
// incoming link. It takes an isReceive bool to differentiate between
// our node's receives and forwards.
NotifyLinkFailEvent(key HtlcKey, info HtlcInfo,
Expand All @@ -449,3 +464,36 @@ type htlcNotifier interface {
NotifyFinalHtlcEvent(key models.CircuitKey,
info channeldb.FinalHtlcInfo)
}

// AuxHtlcModifier is an interface that allows the sender to modify the outgoing
// HTLC of a payment by changing the amount or the wire message tlv records.
type AuxHtlcModifier interface {
// ProduceHtlcExtraData is a function that, based on the previous extra
// data blob of an HTLC, may produce a different blob or modify the
// amount of bitcoin this htlc should carry.
ProduceHtlcExtraData(totalAmount lnwire.MilliSatoshi,
htlcCustomRecords lnwire.CustomRecords) (lnwire.MilliSatoshi,
lnwire.CustomRecords, error)
}

// AuxTrafficShaper is an interface that allows the sender to determine if a
// payment should be carried by a channel based on the TLV records that may be
// present in the `update_add_htlc` message or the channel commitment itself.
type AuxTrafficShaper interface {
AuxHtlcModifier

// ShouldHandleTraffic is called in order to check if the channel
// identified by the provided channel ID may have external mechanisms
// that would allow it to carry out the payment.
ShouldHandleTraffic(cid lnwire.ShortChannelID,
fundingBlob fn.Option[tlv.Blob]) (bool, error)

// PaymentBandwidth returns the available bandwidth for a custom channel
// decided by the given channel aux blob and HTLC blob. A return value
// of 0 means there is no bandwidth available. To find out if a channel
// is a custom channel that should be handled by the traffic shaper, the
// ShouldHandleTraffic method should be called first.
PaymentBandwidth(htlcBlob, commitmentBlob fn.Option[tlv.Blob],
linkBandwidth,
htlcAmt lnwire.MilliSatoshi) (lnwire.MilliSatoshi, error)
}
Loading

0 comments on commit 3c08109

Please sign in to comment.