From 34329c684e7047c77799b88a4fcbb317c0bf6d18 Mon Sep 17 00:00:00 2001 From: elnosh Date: Wed, 12 Nov 2025 17:11:20 -0500 Subject: [PATCH 1/2] multi: rename experimental endorsement signal to accountable Renames the endorsement signal to accountable to match the latest proposal https://github.com/lightning/blips/pull/67 --- feature/default_sets.go | 2 +- feature/manager.go | 12 ++--- htlcswitch/link.go | 48 +++++++++--------- htlcswitch/link_test.go | 46 ++++++++--------- htlcswitch/test_utils.go | 42 ++++++++-------- itest/list_on_test.go | 4 +- ....go => lnd_experimental_accountability.go} | 50 +++++++++---------- itest/lnd_forward_interceptor_test.go | 14 +++--- itest/lnd_invoice_acceptor_test.go | 6 +-- lncfg/protocol.go | 12 ++--- lncfg/protocol_integration.go | 12 ++--- lnrpc/routerrpc/router_backend.go | 14 +++--- lnrpc/routerrpc/router_backend_test.go | 30 +++++------ lntest/utils.go | 19 +++---- lnwire/features.go | 18 ++++--- lnwire/update_add_htlc.go | 25 +++++----- peer/brontide.go | 44 ++++++++-------- routing/route/route.go | 2 +- rpcserver.go | 8 ++- sample-lnd.conf | 4 +- server.go | 44 ++++++++-------- 21 files changed, 229 insertions(+), 227 deletions(-) rename itest/{lnd_experimental_endorsement.go => lnd_experimental_accountability.go} (64%) diff --git a/feature/default_sets.go b/feature/default_sets.go index fcb53b666..5be5706f6 100644 --- a/feature/default_sets.go +++ b/feature/default_sets.go @@ -100,7 +100,7 @@ var defaultSetDesc = setDesc{ SetInit: {}, // I SetNodeAnn: {}, // N }, - lnwire.ExperimentalEndorsementOptional: { + lnwire.ExperimentalAccountabilityOptional: { SetNodeAnn: {}, // N }, lnwire.RbfCoopCloseOptionalStaging: { diff --git a/feature/manager.go b/feature/manager.go index 862880f3b..baef44019 100644 --- a/feature/manager.go +++ b/feature/manager.go @@ -69,9 +69,9 @@ type Config struct { // NoTaprootOverlay unsets the taproot overlay channel feature bits. NoTaprootOverlay bool - // NoExperimentalEndorsement unsets any bits that signal support for - // forwarding experimental endorsement. - NoExperimentalEndorsement bool + // NoExperimentalAccountability unsets any bits that signal support for + // forwarding experimental accountability. + NoExperimentalAccountability bool // NoRbfCoopClose unsets any bits that signal support for using RBF for // coop close. @@ -213,9 +213,9 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) { raw.Unset(lnwire.SimpleTaprootOverlayChansOptional) raw.Unset(lnwire.SimpleTaprootOverlayChansRequired) } - if cfg.NoExperimentalEndorsement { - raw.Unset(lnwire.ExperimentalEndorsementOptional) - raw.Unset(lnwire.ExperimentalEndorsementRequired) + if cfg.NoExperimentalAccountability { + raw.Unset(lnwire.ExperimentalAccountabilityOptional) + raw.Unset(lnwire.ExperimentalAccountabilityRequired) } if cfg.NoRbfCoopClose { raw.Unset(lnwire.RbfCoopCloseOptionalStaging) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 4c81964cc..93bbabb78 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -290,9 +290,9 @@ type ChannelLinkConfig struct { // restrict the flow of HTLCs and fee updates. MaxFeeExposure lnwire.MilliSatoshi - // ShouldFwdExpEndorsement is a closure that indicates whether the link - // should forward experimental endorsement signals. - ShouldFwdExpEndorsement func() bool + // ShouldFwdExpAccountability is a closure that indicates whether the + // link should forward experimental accountability signals. + ShouldFwdExpAccountability func() bool // AuxTrafficShaper is an optional auxiliary traffic shaper that can be // used to manage the bandwidth of the link. @@ -3163,11 +3163,11 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) { continue } - endorseValue := l.experimentalEndorsement( + accountableValue := l.experimentalAccountability( record.CustomSet(add.CustomRecords), ) - endorseType := uint64( - lnwire.ExperimentalEndorsementType, + accountableType := uint64( + lnwire.ExperimentalAccountableType, ) switch fwdPkg.State { @@ -3191,9 +3191,9 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) { BlindingPoint: fwdInfo.NextBlinding, } - endorseValue.WhenSome(func(e byte) { + accountableValue.WhenSome(func(e byte) { custRecords := map[uint64][]byte{ - endorseType: {e}, + accountableType: {e}, } outgoingAdd.CustomRecords = custRecords @@ -3249,9 +3249,9 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) { BlindingPoint: fwdInfo.NextBlinding, } - endorseValue.WhenSome(func(e byte) { + accountableValue.WhenSome(func(e byte) { addMsg.CustomRecords = map[uint64][]byte{ - endorseType: {e}, + accountableType: {e}, } }) @@ -3340,44 +3340,44 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) { l.forwardBatch(reforward, switchPackets...) } -// experimentalEndorsement returns the value to set for our outgoing -// experimental endorsement field, and a boolean indicating whether it should -// be populated on the outgoing htlc. -func (l *channelLink) experimentalEndorsement( +// experimentalAccountability returns the value to set for our outgoing +// experimental accountable field. It only considers the accountability bit, +// other custom records present are not considered for forwarding. +func (l *channelLink) experimentalAccountability( customUpdateAdd record.CustomSet) fn.Option[byte] { // Only relay experimental signal if we are within the experiment // period. - if !l.cfg.ShouldFwdExpEndorsement() { + if !l.cfg.ShouldFwdExpAccountability() { return fn.None[byte]() } // If we don't have any custom records or the experimental field is // not set, just forward a zero value. if len(customUpdateAdd) == 0 { - return fn.Some[byte](lnwire.ExperimentalUnendorsed) + return fn.Some[byte](lnwire.ExperimentalUnaccountable) } - t := uint64(lnwire.ExperimentalEndorsementType) + t := uint64(lnwire.ExperimentalAccountableType) value, set := customUpdateAdd[t] if !set { - return fn.Some[byte](lnwire.ExperimentalUnendorsed) + return fn.Some[byte](lnwire.ExperimentalUnaccountable) } // We expect at least one byte for this field, consider it invalid if // it has no data and just forward a zero value. if len(value) == 0 { - return fn.Some[byte](lnwire.ExperimentalUnendorsed) + return fn.Some[byte](lnwire.ExperimentalUnaccountable) } - // Only forward endorsed if the incoming link is endorsed. - if value[0] == lnwire.ExperimentalEndorsed { - return fn.Some[byte](lnwire.ExperimentalEndorsed) + // Only forward accountable if the incoming link is accountable. + if value[0] == lnwire.ExperimentalAccountable { + return fn.Some[byte](lnwire.ExperimentalAccountable) } - // Forward as unendorsed otherwise, including cases where we've + // Forward as unaccountable otherwise, including cases where we've // received an invalid value that uses more than 3 bits of information. - return fn.Some[byte](lnwire.ExperimentalUnendorsed) + return fn.Some[byte](lnwire.ExperimentalUnaccountable) } // processExitHop handles an htlc for which this link is the exit hop. It diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 101a47b98..e4e63d982 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -2234,18 +2234,18 @@ func newSingleLinkTestHarness(t *testing.T, chanAmt, PendingCommitTicker: ticker.New(time.Minute), // Make the BatchSize and Min/MaxUpdateTimeout large enough // to not trigger commit updates automatically during tests. - BatchSize: 10000, - MinUpdateTimeout: 30 * time.Minute, - MaxUpdateTimeout: 40 * time.Minute, - MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, - MaxFeeAllocation: DefaultMaxLinkFeeAllocation, - NotifyActiveLink: func(wire.OutPoint) {}, - NotifyActiveChannel: func(wire.OutPoint) {}, - NotifyInactiveChannel: func(wire.OutPoint) {}, - NotifyInactiveLinkEvent: func(wire.OutPoint) {}, - HtlcNotifier: aliceSwitch.cfg.HtlcNotifier, - GetAliases: getAliases, - ShouldFwdExpEndorsement: func() bool { return true }, + BatchSize: 10000, + MinUpdateTimeout: 30 * time.Minute, + MaxUpdateTimeout: 40 * time.Minute, + MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, + MaxFeeAllocation: DefaultMaxLinkFeeAllocation, + NotifyActiveLink: func(wire.OutPoint) {}, + NotifyActiveChannel: func(wire.OutPoint) {}, + NotifyInactiveChannel: func(wire.OutPoint) {}, + NotifyInactiveLinkEvent: func(wire.OutPoint) {}, + HtlcNotifier: aliceSwitch.cfg.HtlcNotifier, + GetAliases: getAliases, + ShouldFwdExpAccountability: func() bool { return true }, } aliceLink := NewChannelLink(aliceCfg, aliceLc.channel) @@ -4924,17 +4924,17 @@ func (h *persistentLinkHarness) restartLink( MinUpdateTimeout: 30 * time.Minute, MaxUpdateTimeout: 40 * time.Minute, // Set any hodl flags requested for the new link. - HodlMask: hodl.MaskFromFlags(hodlFlags...), - MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, - MaxFeeAllocation: DefaultMaxLinkFeeAllocation, - NotifyActiveLink: func(wire.OutPoint) {}, - NotifyActiveChannel: func(wire.OutPoint) {}, - NotifyInactiveChannel: func(wire.OutPoint) {}, - NotifyInactiveLinkEvent: func(wire.OutPoint) {}, - HtlcNotifier: h.hSwitch.cfg.HtlcNotifier, - SyncStates: syncStates, - GetAliases: getAliases, - ShouldFwdExpEndorsement: func() bool { return true }, + HodlMask: hodl.MaskFromFlags(hodlFlags...), + MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, + MaxFeeAllocation: DefaultMaxLinkFeeAllocation, + NotifyActiveLink: func(wire.OutPoint) {}, + NotifyActiveChannel: func(wire.OutPoint) {}, + NotifyInactiveChannel: func(wire.OutPoint) {}, + NotifyInactiveLinkEvent: func(wire.OutPoint) {}, + HtlcNotifier: h.hSwitch.cfg.HtlcNotifier, + SyncStates: syncStates, + GetAliases: getAliases, + ShouldFwdExpAccountability: func() bool { return true }, } aliceLink := NewChannelLink(aliceCfg, aliceChannel) diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index bdb365d3c..b74dbd0bb 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -1157,27 +1157,27 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer, UpdateContractSignals: func(*contractcourt.ContractSignals) error { return nil }, - NotifyContractUpdate: notifyContractUpdate, - ChainEvents: &contractcourt.ChainEventSubscription{}, - SyncStates: true, - BatchSize: 10, - BatchTicker: ticker.NewForce(testBatchTimeout), - FwdPkgGCTicker: ticker.NewForce(fwdPkgTimeout), - PendingCommitTicker: ticker.New(2 * time.Minute), - MinUpdateTimeout: minFeeUpdateTimeout, - MaxUpdateTimeout: maxFeeUpdateTimeout, - OnChannelFailure: func(lnwire.ChannelID, lnwire.ShortChannelID, LinkFailureError) {}, - OutgoingCltvRejectDelta: 3, - MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, - MaxFeeAllocation: DefaultMaxLinkFeeAllocation, - MaxAnchorsCommitFeeRate: chainfee.SatPerKVByte(10 * 1000).FeePerKWeight(), - NotifyActiveLink: func(wire.OutPoint) {}, - NotifyActiveChannel: func(wire.OutPoint) {}, - NotifyInactiveChannel: func(wire.OutPoint) {}, - NotifyInactiveLinkEvent: func(wire.OutPoint) {}, - HtlcNotifier: server.htlcSwitch.cfg.HtlcNotifier, - GetAliases: getAliases, - ShouldFwdExpEndorsement: func() bool { return true }, + NotifyContractUpdate: notifyContractUpdate, + ChainEvents: &contractcourt.ChainEventSubscription{}, + SyncStates: true, + BatchSize: 10, + BatchTicker: ticker.NewForce(testBatchTimeout), + FwdPkgGCTicker: ticker.NewForce(fwdPkgTimeout), + PendingCommitTicker: ticker.New(2 * time.Minute), + MinUpdateTimeout: minFeeUpdateTimeout, + MaxUpdateTimeout: maxFeeUpdateTimeout, + OnChannelFailure: func(lnwire.ChannelID, lnwire.ShortChannelID, LinkFailureError) {}, + OutgoingCltvRejectDelta: 3, + MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, + MaxFeeAllocation: DefaultMaxLinkFeeAllocation, + MaxAnchorsCommitFeeRate: chainfee.SatPerKVByte(10 * 1000).FeePerKWeight(), + NotifyActiveLink: func(wire.OutPoint) {}, + NotifyActiveChannel: func(wire.OutPoint) {}, + NotifyInactiveChannel: func(wire.OutPoint) {}, + NotifyInactiveLinkEvent: func(wire.OutPoint) {}, + HtlcNotifier: server.htlcSwitch.cfg.HtlcNotifier, + GetAliases: getAliases, + ShouldFwdExpAccountability: func() bool { return true }, }, channel, ) diff --git a/itest/list_on_test.go b/itest/list_on_test.go index f5961147d..02457d7d1 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -700,8 +700,8 @@ var allTestCases = []*lntest.TestCase{ TestFunc: testDebuglevelShow, }, { - Name: "experimental endorsement", - TestFunc: testExperimentalEndorsement, + Name: "experimental accountability", + TestFunc: testExperimentalAccountability, }, { Name: "quiescence", diff --git a/itest/lnd_experimental_endorsement.go b/itest/lnd_experimental_accountability.go similarity index 64% rename from itest/lnd_experimental_endorsement.go rename to itest/lnd_experimental_accountability.go index 67f5e30c0..a636769ae 100644 --- a/itest/lnd_experimental_endorsement.go +++ b/itest/lnd_experimental_accountability.go @@ -15,19 +15,19 @@ import ( "github.com/stretchr/testify/require" ) -// testExperimentalEndorsement tests setting of positive and negative -// experimental endorsement signals. -func testExperimentalEndorsement(ht *lntest.HarnessTest) { - testEndorsement(ht, true) - testEndorsement(ht, false) +// testExperimentalAccountability tests setting of positive and negative +// experimental accountable signals. +func testExperimentalAccountability(ht *lntest.HarnessTest) { + testAccountability(ht, true) + testAccountability(ht, false) } -// testEndorsement sets up a 5 hop network and tests propagation of -// experimental endorsement signals. -func testEndorsement(ht *lntest.HarnessTest, aliceEndorse bool) { +// testAccountability sets up a 5 hop network and tests propagation of +// experimental accountable signals. +func testAccountability(ht *lntest.HarnessTest, aliceAccountable bool) { cfg := node.CfgAnchor carolCfg := append( - []string{"--protocol.no-experimental-endorsement"}, cfg..., + []string{"--protocol.no-experimental-accountability"}, cfg..., ) cfgs := [][]string{cfg, cfg, carolCfg, cfg, cfg} @@ -58,17 +58,17 @@ func testEndorsement(ht *lntest.HarnessTest, aliceEndorse bool) { } var expectedValue []byte - hasEndorsement := lntest.ExperimentalEndorsementActive() + hasAccountability := lntest.ExperimentalAccountabilityActive() - if hasEndorsement { - if aliceEndorse { - expectedValue = []byte{lnwire.ExperimentalEndorsed} - t := uint64(lnwire.ExperimentalEndorsementType) + if hasAccountability { + if aliceAccountable { + expectedValue = []byte{lnwire.ExperimentalAccountable} + t := uint64(lnwire.ExperimentalAccountableType) sendReq.FirstHopCustomRecords = map[uint64][]byte{ t: expectedValue, } } else { - expectedValue = []byte{lnwire.ExperimentalUnendorsed} + expectedValue = []byte{lnwire.ExperimentalUnaccountable} } } @@ -76,29 +76,29 @@ func testEndorsement(ht *lntest.HarnessTest, aliceEndorse bool) { // Validate that our signal (positive or zero) propagates until carol // and then is dropped because she has disabled the feature. - // When the endorsement experiment is not active, no signal is sent. - validateEndorsedAndResume( - ht, bobIntercept, hasEndorsement, expectedValue, + // When the accountability experiment is not active, no signal is sent. + validateAccountableAndResume( + ht, bobIntercept, hasAccountability, expectedValue, ) - validateEndorsedAndResume( - ht, carolIntercept, hasEndorsement, expectedValue, + validateAccountableAndResume( + ht, carolIntercept, hasAccountability, expectedValue, ) - validateEndorsedAndResume(ht, daveIntercept, false, nil) + validateAccountableAndResume(ht, daveIntercept, false, nil) var preimage lntypes.Preimage copy(preimage[:], invoice.RPreimage) ht.AssertPaymentStatus(alice, preimage.Hash(), lnrpc.Payment_SUCCEEDED) } -func validateEndorsedAndResume(ht *lntest.HarnessTest, - interceptor rpc.InterceptorClient, hasEndorsement bool, +func validateAccountableAndResume(ht *lntest.HarnessTest, + interceptor rpc.InterceptorClient, hasAccountable bool, expectedValue []byte) { packet := ht.ReceiveHtlcInterceptor(interceptor) var expectedRecords map[uint64][]byte - if hasEndorsement { - u64Type := uint64(lnwire.ExperimentalEndorsementType) + if hasAccountable { + u64Type := uint64(lnwire.ExperimentalAccountableType) expectedRecords = map[uint64][]byte{ u64Type: expectedValue, } diff --git a/itest/lnd_forward_interceptor_test.go b/itest/lnd_forward_interceptor_test.go index 615f9f48b..d45d65025 100644 --- a/itest/lnd_forward_interceptor_test.go +++ b/itest/lnd_forward_interceptor_test.go @@ -387,7 +387,7 @@ func testForwardInterceptorRestart(ht *lntest.HarnessTest) { // all intercepted packets. These packets are held to simulate a // pending payment. packet := ht.ReceiveHtlcInterceptor(bobInterceptor) - require.Equal(ht, lntest.CustomRecordsWithUnendorsed( + require.Equal(ht, lntest.CustomRecordsWithUnaccountable( customRecords, ), packet.InWireCustomRecords) @@ -433,21 +433,21 @@ func testForwardInterceptorRestart(ht *lntest.HarnessTest) { packet = ht.ReceiveHtlcInterceptor(bobInterceptor) // Check the expected number of custom records based on whether the - // endorsement experiment is still active. + // accountability experiment is still active. expectedLen := 1 - if lntest.ExperimentalEndorsementActive() { + if lntest.ExperimentalAccountabilityActive() { expectedLen = 2 } require.Len(ht, packet.InWireCustomRecords, expectedLen) - require.Equal(ht, lntest.CustomRecordsWithUnendorsed(customRecords), + require.Equal(ht, lntest.CustomRecordsWithUnaccountable(customRecords), packet.InWireCustomRecords) // And now we forward the payment at Carol, expecting only an - // endorsement signal in our incoming custom records (if the experiment + // accountability signal in our incoming custom records (if the experiment // is still active). packet = ht.ReceiveHtlcInterceptor(carolInterceptor) expectedCarolLen := 0 - if lntest.ExperimentalEndorsementActive() { + if lntest.ExperimentalAccountabilityActive() { expectedCarolLen = 1 } require.Len(ht, packet.InWireCustomRecords, expectedCarolLen) @@ -462,7 +462,7 @@ func testForwardInterceptorRestart(ht *lntest.HarnessTest) { alice, preimage.Hash(), lnrpc.Payment_SUCCEEDED, func(p *lnrpc.Payment) error { recordsEqual := reflect.DeepEqual( - lntest.CustomRecordsWithUnendorsed( + lntest.CustomRecordsWithUnaccountable( sendReq.FirstHopCustomRecords, ), p.FirstHopCustomRecords, ) diff --git a/itest/lnd_invoice_acceptor_test.go b/itest/lnd_invoice_acceptor_test.go index f7c617b25..4d5e30cc1 100644 --- a/itest/lnd_invoice_acceptor_test.go +++ b/itest/lnd_invoice_acceptor_test.go @@ -102,9 +102,9 @@ func testInvoiceHtlcModifierBasic(ht *lntest.HarnessTest) { ht, tc.sendAmountMsat, modifierRequest.ExitHtlcAmt, ) - // Expect custom records plus endorsement signal. + // Expect custom records plus accountable signal. require.Equal( - ht, lntest.CustomRecordsWithUnendorsed( + ht, lntest.CustomRecordsWithUnaccountable( tc.lastHopCustomRecords, ), modifierRequest.ExitHtlcWireCustomRecords, ) @@ -152,7 +152,7 @@ func testInvoiceHtlcModifierBasic(ht *lntest.HarnessTest) { require.Len(ht, updatedInvoice.Htlcs, 1) require.Equal( - ht, lntest.CustomRecordsWithUnendorsed( + ht, lntest.CustomRecordsWithUnaccountable( tc.lastHopCustomRecords, ), updatedInvoice.Htlcs[0].CustomRecords, ) diff --git a/lncfg/protocol.go b/lncfg/protocol.go index 4d348b215..fbfe26411 100644 --- a/lncfg/protocol.go +++ b/lncfg/protocol.go @@ -71,8 +71,8 @@ type ProtocolOptions struct { // NoRouteBlindingOption disables forwarding of payments in blinded routes. NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"` - // NoExperimentalEndorsementOption disables experimental endorsement. - NoExperimentalEndorsementOption bool `long:"no-experimental-endorsement" description:"do not forward experimental endorsement signals"` + // NoExperimentalAccountabilityOption disables experimental accountability. + NoExperimentalAccountabilityOption bool `long:"no-experimental-accountability" description:"do not forward experimental accountability signals"` // CustomMessage allows the custom message APIs to handle messages with // the provided protocol numbers, which fall outside the custom message @@ -139,10 +139,10 @@ func (l *ProtocolOptions) NoRouteBlinding() bool { return l.NoRouteBlindingOption } -// NoExperimentalEndorsement returns true if experimental endorsement should -// be disabled. -func (l *ProtocolOptions) NoExperimentalEndorsement() bool { - return l.NoExperimentalEndorsementOption +// NoExpAccountability returns true if experimental accountability should be +// disabled. +func (l *ProtocolOptions) NoExpAccountability() bool { + return l.NoExperimentalAccountabilityOption } // NoQuiescence returns true if quiescence is disabled. diff --git a/lncfg/protocol_integration.go b/lncfg/protocol_integration.go index c68d6ffe6..72a26ae8b 100644 --- a/lncfg/protocol_integration.go +++ b/lncfg/protocol_integration.go @@ -74,8 +74,8 @@ type ProtocolOptions struct { // NoRouteBlindingOption disables forwarding of payments in blinded routes. NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"` - // NoExperimentalEndorsementOption disables experimental endorsement. - NoExperimentalEndorsementOption bool `long:"no-experimental-endorsement" description:"do not forward experimental endorsement signals"` + // NoExperimentalAccountabilityOption disables experimental accountability. + NoExperimentalAccountabilityOption bool `long:"no-experimental-accountability" description:"do not forward experimental accountability signals"` // NoQuiescenceOption disables quiescence for all channels. NoQuiescenceOption bool `long:"no-quiescence" description:"do not allow or advertise quiescence for any channel"` @@ -137,10 +137,10 @@ func (l *ProtocolOptions) NoRouteBlinding() bool { return l.NoRouteBlindingOption } -// NoExperimentalEndorsement returns true if experimental endorsement should -// be disabled. -func (l *ProtocolOptions) NoExperimentalEndorsement() bool { - return l.NoExperimentalEndorsementOption +// NoExpAccountability returns true if experimental accountability should be +// disabled. +func (l *ProtocolOptions) NoExpAccountability() bool { + return l.NoExperimentalAccountabilityOption } // NoQuiescence returns true if quiescence is disabled. diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index f8a3c568e..d8c8a17c4 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -122,9 +122,9 @@ type RouterBackend struct { // channel data from the first hop of a route. ParseCustomChannelData func(message proto.Message) error - // ShouldSetExpEndorsement returns a boolean indicating whether the - // experimental endorsement bit should be set. - ShouldSetExpEndorsement func() bool + // ShouldSetExpAccountability returns a boolean indicating whether the + // experimental accountability bit should be set. + ShouldSetExpAccountability func() bool // Clock is the clock used to validate payment requests expiry. // It is useful for testing. @@ -947,19 +947,19 @@ func (r *RouterBackend) extractIntentFromSendRequest( } payIntent.FirstHopCustomRecords = firstHopRecords - // If the experimental endorsement signal is not already set, propagate + // If the experimental accountable signal is not already set, propagate // a zero value field if configured to set this signal. - if r.ShouldSetExpEndorsement() { + if r.ShouldSetExpAccountability() { if payIntent.FirstHopCustomRecords == nil { payIntent.FirstHopCustomRecords = make( map[uint64][]byte, ) } - t := uint64(lnwire.ExperimentalEndorsementType) + t := uint64(lnwire.ExperimentalAccountableType) if _, set := payIntent.FirstHopCustomRecords[t]; !set { payIntent.FirstHopCustomRecords[t] = []byte{ - lnwire.ExperimentalUnendorsed, + lnwire.ExperimentalUnaccountable, } } } diff --git a/lnrpc/routerrpc/router_backend_test.go b/lnrpc/routerrpc/router_backend_test.go index a1095a36c..373b92983 100644 --- a/lnrpc/routerrpc/router_backend_test.go +++ b/lnrpc/routerrpc/router_backend_test.go @@ -677,7 +677,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Amount conflict, both sat and msat specified", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return true }, }, @@ -692,7 +692,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Both dest and payment_request provided", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, @@ -708,7 +708,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Both payment_hash and payment_request provided", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, @@ -725,7 +725,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { name: "Both final_cltv_delta and payment_request " + "provided", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, @@ -741,7 +741,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Invalid payment request length", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, ActiveNetParams: &chaincfg.RegressionNetParams, @@ -756,7 +756,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Expired invoice payment request", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, ActiveNetParams: &chaincfg.RegressionNetParams, @@ -772,7 +772,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Invoice missing payment address", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, ActiveNetParams: &chaincfg.RegressionNetParams, @@ -789,7 +789,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Invalid dest vertex length", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, @@ -803,7 +803,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Payment request with missing amount", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, @@ -817,7 +817,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Destination lacks AMP support", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, @@ -834,7 +834,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Invalid payment hash length", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, @@ -849,7 +849,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { { name: "Payment amount exceeds maximum possible amount", backend: &RouterBackend{ - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, @@ -868,7 +868,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { name: "Reject self-payments if not permitted", backend: &RouterBackend{ MaxTotalTimelock: 1000, - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, SelfNode: target, @@ -885,7 +885,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { name: "Required and optional feature bits set", backend: &RouterBackend{ MaxTotalTimelock: 1000, - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, @@ -906,7 +906,7 @@ func TestExtractIntentFromSendRequest(t *testing.T) { name: "Valid send req parameters, payment settled", backend: &RouterBackend{ MaxTotalTimelock: 1000, - ShouldSetExpEndorsement: func() bool { + ShouldSetExpAccountability: func() bool { return false }, }, diff --git a/lntest/utils.go b/lntest/utils.go index ab998ecf8..a2c3ea839 100644 --- a/lntest/utils.go +++ b/lntest/utils.go @@ -285,12 +285,13 @@ func CalcStaticFeeBuffer(c lnrpc.CommitmentType, numHTLCs int) btcutil.Amount { return feeBuffer.ToSatoshis() } -// CustomRecordsWithUnendorsed copies the map of custom records and adds an -// endorsed signal (replacing in the case of conflict) for assertion in tests. -func CustomRecordsWithUnendorsed( +// CustomRecordsWithUnaccountable copies the map of custom records and adds an +// accountable signal (replacing in the case of conflict) for assertion in +// tests. +func CustomRecordsWithUnaccountable( originalRecords lnwire.CustomRecords) map[uint64][]byte { - if !ExperimentalEndorsementActive() { + if !ExperimentalAccountabilityActive() { // Return nil if there are no records, to match wire encoding. if len(originalRecords) == 0 { return nil @@ -300,16 +301,16 @@ func CustomRecordsWithUnendorsed( } return originalRecords.MergedCopy(map[uint64][]byte{ - uint64(lnwire.ExperimentalEndorsementType): { - lnwire.ExperimentalUnendorsed, + uint64(lnwire.ExperimentalAccountableType): { + lnwire.ExperimentalUnaccountable, }}, ) } -// ExperimentalEndorsementActive returns true if the experimental endorsement +// ExperimentalAccountabilityActive returns true if the experimental accountability // window is still open. -func ExperimentalEndorsementActive() bool { - return time.Now().Before(lnd.EndorsementExperimentEnd) +func ExperimentalAccountabilityActive() bool { + return time.Now().Before(lnd.AccountabilityExperimentEnd) } // LnrpcOutpointToStr returns a string representation of an lnrpc.OutPoint. diff --git a/lnwire/features.go b/lnwire/features.go index 107828ee2..4e927e170 100644 --- a/lnwire/features.go +++ b/lnwire/features.go @@ -289,13 +289,15 @@ const ( // being finalized. SimpleTaprootChannelsOptionalStaging = 181 - // ExperimentalEndorsementRequired is a required feature bit that - // indicates that the node will relay experimental endorsement signals. - ExperimentalEndorsementRequired FeatureBit = 260 + // ExperimentalAccountabilityRequired is a required feature bit that + // indicates that the node will relay experimental accountability + // signals. + ExperimentalAccountabilityRequired FeatureBit = 260 - // ExperimentalEndorsementOptional is an optional feature bit that - // indicates that the node will relay experimental endorsement signals. - ExperimentalEndorsementOptional FeatureBit = 261 + // ExperimentalAccountabilityOptional is an optional feature bit that + // indicates that the node will relay experimental accountability + // signals. + ExperimentalAccountabilityOptional FeatureBit = 261 // Bolt11BlindedPathsRequired is a required feature bit that indicates // that the node is able to understand the blinded path tagged field in @@ -385,8 +387,8 @@ var Features = map[FeatureBit]string{ SimpleTaprootChannelsOptionalStaging: "simple-taproot-chans-x", SimpleTaprootOverlayChansOptional: "taproot-overlay-chans", SimpleTaprootOverlayChansRequired: "taproot-overlay-chans", - ExperimentalEndorsementRequired: "endorsement-x", - ExperimentalEndorsementOptional: "endorsement-x", + ExperimentalAccountabilityRequired: "accountable-x", + ExperimentalAccountabilityOptional: "accountable-x", Bolt11BlindedPathsOptional: "bolt-11-blinded-paths", Bolt11BlindedPathsRequired: "bolt-11-blinded-paths", RbfCoopCloseOptional: "rbf-coop-close", diff --git a/lnwire/update_add_htlc.go b/lnwire/update_add_htlc.go index e627dbf4e..38ceeec21 100644 --- a/lnwire/update_add_htlc.go +++ b/lnwire/update_add_htlc.go @@ -16,20 +16,21 @@ const ( // entire packet. OnionPacketSize = 1366 - // ExperimentalEndorsementType is the TLV type used for a custom - // record that sets an experimental endorsement value. - ExperimentalEndorsementType tlv.Type = 106823 + // ExperimentalAccountableType is the TLV type used for a custom + // record that sets an experimental accountable value. + ExperimentalAccountableType tlv.Type = 106823 - // ExperimentalUnendorsed is the value that the experimental endorsement - // field contains when a htlc is not endorsed. - ExperimentalUnendorsed = 0 + // ExperimentalUnaccountable is the value that the experimental + // accountable field contains when a htlc is not accountable. + ExperimentalUnaccountable = 0 - // ExperimentalEndorsed is the value that the experimental endorsement - // field contains when a htlc is endorsed. We're using a single byte - // to represent our endorsement value, but limit the value to using - // the first three bits (max value = 00000111). Interpreted as a uint8 - // (an alias for byte in go), we can just define this constant as 7. - ExperimentalEndorsed = 7 + // ExperimentalAccountable is the value that the experimental + // accountable field contains when a htlc is accountable. We're using a + // single byte to represent our accountable value, but limit the value + // to using the first three bits (max value = 00000111). Interpreted as + // a uint8 (an alias for byte in go), we can just define this constant + // as 7. + ExperimentalAccountable = 7 ) type ( diff --git a/peer/brontide.go b/peer/brontide.go index 8d02ca6e5..73c5acda4 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -468,9 +468,9 @@ type Config struct { // onion messages to subscribers. OnionMessageServer *subscribe.Server - // ShouldFwdExpEndorsement is a closure that indicates whether - // experimental endorsement signals should be set. - ShouldFwdExpEndorsement func() bool + // ShouldFwdExpAccountability is a closure that indicates whether + // experimental accountability signals should be set. + ShouldFwdExpAccountability func() bool // NoDisconnectOnPongFailure indicates whether the peer should *not* be // disconnected if a pong is not received in time or is mismatched. @@ -1460,25 +1460,25 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint, PendingCommitTicker: ticker.New( p.cfg.PendingCommitInterval, ), - BatchSize: p.cfg.ChannelCommitBatchSize, - UnsafeReplay: p.cfg.UnsafeReplay, - MinUpdateTimeout: htlcswitch.DefaultMinLinkFeeUpdateTimeout, - MaxUpdateTimeout: htlcswitch.DefaultMaxLinkFeeUpdateTimeout, - OutgoingCltvRejectDelta: p.cfg.OutgoingCltvRejectDelta, - TowerClient: p.cfg.TowerClient, - MaxOutgoingCltvExpiry: p.cfg.MaxOutgoingCltvExpiry, - MaxFeeAllocation: p.cfg.MaxChannelFeeAllocation, - MaxAnchorsCommitFeeRate: p.cfg.MaxAnchorsCommitFeeRate, - NotifyActiveLink: p.cfg.ChannelNotifier.NotifyActiveLinkEvent, - NotifyActiveChannel: p.cfg.ChannelNotifier.NotifyActiveChannelEvent, - NotifyInactiveChannel: p.cfg.ChannelNotifier.NotifyInactiveChannelEvent, - NotifyInactiveLinkEvent: p.cfg.ChannelNotifier.NotifyInactiveLinkEvent, - HtlcNotifier: p.cfg.HtlcNotifier, - GetAliases: p.cfg.GetAliases, - PreviouslySentShutdown: shutdownMsg, - DisallowRouteBlinding: p.cfg.DisallowRouteBlinding, - MaxFeeExposure: p.cfg.MaxFeeExposure, - ShouldFwdExpEndorsement: p.cfg.ShouldFwdExpEndorsement, + BatchSize: p.cfg.ChannelCommitBatchSize, + UnsafeReplay: p.cfg.UnsafeReplay, + MinUpdateTimeout: htlcswitch.DefaultMinLinkFeeUpdateTimeout, + MaxUpdateTimeout: htlcswitch.DefaultMaxLinkFeeUpdateTimeout, + OutgoingCltvRejectDelta: p.cfg.OutgoingCltvRejectDelta, + TowerClient: p.cfg.TowerClient, + MaxOutgoingCltvExpiry: p.cfg.MaxOutgoingCltvExpiry, + MaxFeeAllocation: p.cfg.MaxChannelFeeAllocation, + MaxAnchorsCommitFeeRate: p.cfg.MaxAnchorsCommitFeeRate, + NotifyActiveLink: p.cfg.ChannelNotifier.NotifyActiveLinkEvent, + NotifyActiveChannel: p.cfg.ChannelNotifier.NotifyActiveChannelEvent, + NotifyInactiveChannel: p.cfg.ChannelNotifier.NotifyInactiveChannelEvent, + NotifyInactiveLinkEvent: p.cfg.ChannelNotifier.NotifyInactiveLinkEvent, + HtlcNotifier: p.cfg.HtlcNotifier, + GetAliases: p.cfg.GetAliases, + PreviouslySentShutdown: shutdownMsg, + DisallowRouteBlinding: p.cfg.DisallowRouteBlinding, + MaxFeeExposure: p.cfg.MaxFeeExposure, + ShouldFwdExpAccountability: p.cfg.ShouldFwdExpAccountability, DisallowQuiescence: p.cfg.DisallowQuiescence || !p.remoteFeatures.HasFeature(lnwire.QuiescenceOptional), AuxTrafficShaper: p.cfg.AuxTrafficShaper, diff --git a/routing/route/route.go b/routing/route/route.go index 3b35ad62b..1bb52badb 100644 --- a/routing/route/route.go +++ b/routing/route/route.go @@ -526,7 +526,7 @@ type Route struct { // FirstHopWireCustomRecords is a set of custom records that should be // included in the wire message sent to the first hop. This is for // example used in custom channels. Besides custom channels we use it - // also for the endorsement bit. This data will be sent to the first + // also for the accountable bit. This data will be sent to the first // hop in the UpdateAddHTLC message. // // NOTE: Since these records already represent TLV records, and we diff --git a/rpcserver.go b/rpcserver.go index 5d2c4d266..026b224fd 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -695,8 +695,6 @@ func newRPCServer(cfg *Config, interceptorChain *rpcperms.InterceptorChain, // addDeps populates all dependencies needed by the RPC server, and any // of the sub-servers that it maintains. When this is done, the RPC server can // be started, and start accepting RPC calls. -// -//nolint:funlen func (r *rpcServer) addDeps(ctx context.Context, s *server, macService *macaroons.Service, subServerCgs *subRPCServerConfigs, atpl *autopilot.Manager, @@ -781,13 +779,13 @@ func (r *rpcServer) addDeps(ctx context.Context, s *server, return nil }, - ShouldSetExpEndorsement: func() bool { - if s.cfg.ProtocolOptions.NoExperimentalEndorsement() { + ShouldSetExpAccountability: func() bool { + if s.cfg.ProtocolOptions.NoExpAccountability() { return false } return clock.NewDefaultClock().Now().Before( - EndorsementExperimentEnd, + AccountabilityExperimentEnd, ) }, } diff --git a/sample-lnd.conf b/sample-lnd.conf index c9a2865b8..830d42ea1 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -1440,8 +1440,8 @@ ; Set to disable blinded route forwarding. ; protocol.no-route-blinding=false -; Set to disable experimental endorsement signaling. -; protocol.no-experimental-endorsement=false +; Set to disable experimental accountability signaling. +; protocol.no-experimental-accountability=false ; Set to enable support for RBF based coop close. ; protocol.rbf-coop-close=false diff --git a/server.go b/server.go index c3b724ed3..ef8abbf81 100644 --- a/server.go +++ b/server.go @@ -139,11 +139,11 @@ var ( // TODO(roasbeef): add command line param to modify. MaxFundingAmount = funding.MaxBtcFundingAmount - // EndorsementExperimentEnd is the time after which nodes should stop - // propagating experimental endorsement signals. + // AccountabilityExperimentEnd is the time after which nodes should stop + // propagating experimental accountable signals. // // Per blip04: January 1, 2026 12:00:00 AM UTC in unix seconds. - EndorsementExperimentEnd = time.Unix(1767225600, 0) + AccountabilityExperimentEnd = time.Unix(1767225600, 0) // ErrGossiperBan is one of the errors that can be returned when we // attempt to finalize a connection to a remote peer. @@ -641,22 +641,22 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr, //nolint:ll featureMgr, err := feature.NewManager(feature.Config{ - NoTLVOnion: cfg.ProtocolOptions.LegacyOnion(), - NoStaticRemoteKey: cfg.ProtocolOptions.NoStaticRemoteKey(), - NoAnchors: cfg.ProtocolOptions.NoAnchorCommitments(), - NoWumbo: !cfg.ProtocolOptions.Wumbo(), - NoScriptEnforcementLease: cfg.ProtocolOptions.NoScriptEnforcementLease(), - NoKeysend: !cfg.AcceptKeySend, - NoOptionScidAlias: !cfg.ProtocolOptions.ScidAlias(), - NoZeroConf: !cfg.ProtocolOptions.ZeroConf(), - NoAnySegwit: cfg.ProtocolOptions.NoAnySegwit(), - CustomFeatures: cfg.ProtocolOptions.CustomFeatures(), - NoTaprootChans: !cfg.ProtocolOptions.TaprootChans, - NoTaprootOverlay: !cfg.ProtocolOptions.TaprootOverlayChans, - NoRouteBlinding: cfg.ProtocolOptions.NoRouteBlinding(), - NoExperimentalEndorsement: cfg.ProtocolOptions.NoExperimentalEndorsement(), - NoQuiescence: cfg.ProtocolOptions.NoQuiescence(), - NoRbfCoopClose: !cfg.ProtocolOptions.RbfCoopClose, + NoTLVOnion: cfg.ProtocolOptions.LegacyOnion(), + NoStaticRemoteKey: cfg.ProtocolOptions.NoStaticRemoteKey(), + NoAnchors: cfg.ProtocolOptions.NoAnchorCommitments(), + NoWumbo: !cfg.ProtocolOptions.Wumbo(), + NoScriptEnforcementLease: cfg.ProtocolOptions.NoScriptEnforcementLease(), + NoKeysend: !cfg.AcceptKeySend, + NoOptionScidAlias: !cfg.ProtocolOptions.ScidAlias(), + NoZeroConf: !cfg.ProtocolOptions.ZeroConf(), + NoAnySegwit: cfg.ProtocolOptions.NoAnySegwit(), + CustomFeatures: cfg.ProtocolOptions.CustomFeatures(), + NoTaprootChans: !cfg.ProtocolOptions.TaprootChans, + NoTaprootOverlay: !cfg.ProtocolOptions.TaprootOverlayChans, + NoRouteBlinding: cfg.ProtocolOptions.NoRouteBlinding(), + NoExperimentalAccountability: cfg.ProtocolOptions.NoExpAccountability(), + NoQuiescence: cfg.ProtocolOptions.NoQuiescence(), + NoRbfCoopClose: !cfg.ProtocolOptions.RbfCoopClose, }) if err != nil { return nil, err @@ -4443,13 +4443,13 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, AuxResolver: s.implCfg.AuxContractResolver, AuxTrafficShaper: s.implCfg.TrafficShaper, AuxChannelNegotiator: s.implCfg.AuxChannelNegotiator, - ShouldFwdExpEndorsement: func() bool { - if s.cfg.ProtocolOptions.NoExperimentalEndorsement() { + ShouldFwdExpAccountability: func() bool { + if s.cfg.ProtocolOptions.NoExpAccountability() { return false } return clock.NewDefaultClock().Now().Before( - EndorsementExperimentEnd, + AccountabilityExperimentEnd, ) }, NoDisconnectOnPongFailure: s.cfg.NoDisconnectOnPongFailure, From 6f49bea52b8ff6e4d2362582ce7c6462a7af6df0 Mon Sep 17 00:00:00 2001 From: elnosh Date: Thu, 13 Nov 2025 10:33:02 -0500 Subject: [PATCH 2/2] server: remove accountability signal experiment period In the previous iteration with endorsement signaling, the recommendation was for the sender to set it to 1 and that could have had privacy concerns when first deploying given that the default was to downgrade the signal to 0. In the latest proposal the recommended default for both sending and forwarding nodes is to set `accountable` to 0. As a result, the dates have been removed given that there are no privacy risks associated with relaying the signal with zero values. --- docs/release-notes/release-notes-0.21.0.md | 4 ++++ htlcswitch/link.go | 2 -- itest/lnd_experimental_accountability.go | 23 ++++++++-------------- itest/lnd_forward_interceptor_test.go | 17 +++------------- lntest/utils.go | 18 ----------------- rpcserver.go | 8 +------- server.go | 14 +------------ 7 files changed, 17 insertions(+), 69 deletions(-) diff --git a/docs/release-notes/release-notes-0.21.0.md b/docs/release-notes/release-notes-0.21.0.md index 4e032a340..71965798d 100644 --- a/docs/release-notes/release-notes-0.21.0.md +++ b/docs/release-notes/release-notes-0.21.0.md @@ -75,6 +75,10 @@ This applies to both funders and fundees, with the ability to override the value during channel opening or acceptance. +* Rename [experimental endorsement signal](https://github.com/lightning/blips/blob/a833e7b49f224e1240b5d669e78fa950160f5a06/blip-0004.md) + to [accountable](https://github.com/lightningnetwork/lnd/pull/10367) to match + the latest [proposal](https://github.com/lightning/blips/pull/67). + ## RPC Updates ## lncli Updates diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 93bbabb78..4dbfa5223 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -3346,8 +3346,6 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) { func (l *channelLink) experimentalAccountability( customUpdateAdd record.CustomSet) fn.Option[byte] { - // Only relay experimental signal if we are within the experiment - // period. if !l.cfg.ShouldFwdExpAccountability() { return fn.None[byte]() } diff --git a/itest/lnd_experimental_accountability.go b/itest/lnd_experimental_accountability.go index a636769ae..30296e7cb 100644 --- a/itest/lnd_experimental_accountability.go +++ b/itest/lnd_experimental_accountability.go @@ -57,18 +57,12 @@ func testAccountability(ht *lntest.HarnessTest, aliceAccountable bool) { FeeLimitMsat: math.MaxInt64, } - var expectedValue []byte - hasAccountability := lntest.ExperimentalAccountabilityActive() - - if hasAccountability { - if aliceAccountable { - expectedValue = []byte{lnwire.ExperimentalAccountable} - t := uint64(lnwire.ExperimentalAccountableType) - sendReq.FirstHopCustomRecords = map[uint64][]byte{ - t: expectedValue, - } - } else { - expectedValue = []byte{lnwire.ExperimentalUnaccountable} + expectedValue := []byte{lnwire.ExperimentalUnaccountable} + if aliceAccountable { + expectedValue = []byte{lnwire.ExperimentalAccountable} + t := uint64(lnwire.ExperimentalAccountableType) + sendReq.FirstHopCustomRecords = map[uint64][]byte{ + t: expectedValue, } } @@ -76,12 +70,11 @@ func testAccountability(ht *lntest.HarnessTest, aliceAccountable bool) { // Validate that our signal (positive or zero) propagates until carol // and then is dropped because she has disabled the feature. - // When the accountability experiment is not active, no signal is sent. validateAccountableAndResume( - ht, bobIntercept, hasAccountability, expectedValue, + ht, bobIntercept, true, expectedValue, ) validateAccountableAndResume( - ht, carolIntercept, hasAccountability, expectedValue, + ht, carolIntercept, true, expectedValue, ) validateAccountableAndResume(ht, daveIntercept, false, nil) diff --git a/itest/lnd_forward_interceptor_test.go b/itest/lnd_forward_interceptor_test.go index d45d65025..f68042db5 100644 --- a/itest/lnd_forward_interceptor_test.go +++ b/itest/lnd_forward_interceptor_test.go @@ -432,25 +432,14 @@ func testForwardInterceptorRestart(ht *lntest.HarnessTest) { // We should get another notification about the held HTLC. packet = ht.ReceiveHtlcInterceptor(bobInterceptor) - // Check the expected number of custom records based on whether the - // accountability experiment is still active. - expectedLen := 1 - if lntest.ExperimentalAccountabilityActive() { - expectedLen = 2 - } - require.Len(ht, packet.InWireCustomRecords, expectedLen) + require.Len(ht, packet.InWireCustomRecords, 2) require.Equal(ht, lntest.CustomRecordsWithUnaccountable(customRecords), packet.InWireCustomRecords) // And now we forward the payment at Carol, expecting only an - // accountability signal in our incoming custom records (if the experiment - // is still active). + // accountability signal in our incoming custom records. packet = ht.ReceiveHtlcInterceptor(carolInterceptor) - expectedCarolLen := 0 - if lntest.ExperimentalAccountabilityActive() { - expectedCarolLen = 1 - } - require.Len(ht, packet.InWireCustomRecords, expectedCarolLen) + require.Len(ht, packet.InWireCustomRecords, 1) err = carolInterceptor.Send(&routerrpc.ForwardHtlcInterceptResponse{ IncomingCircuitKey: packet.IncomingCircuitKey, Action: actionResume, diff --git a/lntest/utils.go b/lntest/utils.go index a2c3ea839..999439855 100644 --- a/lntest/utils.go +++ b/lntest/utils.go @@ -7,11 +7,9 @@ import ( "os" "strconv" "strings" - "time" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" - "github.com/lightningnetwork/lnd" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntest/wait" @@ -290,16 +288,6 @@ func CalcStaticFeeBuffer(c lnrpc.CommitmentType, numHTLCs int) btcutil.Amount { // tests. func CustomRecordsWithUnaccountable( originalRecords lnwire.CustomRecords) map[uint64][]byte { - - if !ExperimentalAccountabilityActive() { - // Return nil if there are no records, to match wire encoding. - if len(originalRecords) == 0 { - return nil - } - - return originalRecords.Copy() - } - return originalRecords.MergedCopy(map[uint64][]byte{ uint64(lnwire.ExperimentalAccountableType): { lnwire.ExperimentalUnaccountable, @@ -307,12 +295,6 @@ func CustomRecordsWithUnaccountable( ) } -// ExperimentalAccountabilityActive returns true if the experimental accountability -// window is still open. -func ExperimentalAccountabilityActive() bool { - return time.Now().Before(lnd.AccountabilityExperimentEnd) -} - // LnrpcOutpointToStr returns a string representation of an lnrpc.OutPoint. func LnrpcOutpointToStr(outpoint *lnrpc.OutPoint) string { return fmt.Sprintf("%s:%d", outpoint.TxidStr, outpoint.OutputIndex) diff --git a/rpcserver.go b/rpcserver.go index 026b224fd..29efd150e 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -780,13 +780,7 @@ func (r *rpcServer) addDeps(ctx context.Context, s *server, return nil }, ShouldSetExpAccountability: func() bool { - if s.cfg.ProtocolOptions.NoExpAccountability() { - return false - } - - return clock.NewDefaultClock().Now().Before( - AccountabilityExperimentEnd, - ) + return !s.cfg.ProtocolOptions.NoExpAccountability() }, } diff --git a/server.go b/server.go index ef8abbf81..3f7b3e826 100644 --- a/server.go +++ b/server.go @@ -139,12 +139,6 @@ var ( // TODO(roasbeef): add command line param to modify. MaxFundingAmount = funding.MaxBtcFundingAmount - // AccountabilityExperimentEnd is the time after which nodes should stop - // propagating experimental accountable signals. - // - // Per blip04: January 1, 2026 12:00:00 AM UTC in unix seconds. - AccountabilityExperimentEnd = time.Unix(1767225600, 0) - // ErrGossiperBan is one of the errors that can be returned when we // attempt to finalize a connection to a remote peer. ErrGossiperBan = errors.New("gossiper has banned remote's key") @@ -4444,13 +4438,7 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, AuxTrafficShaper: s.implCfg.TrafficShaper, AuxChannelNegotiator: s.implCfg.AuxChannelNegotiator, ShouldFwdExpAccountability: func() bool { - if s.cfg.ProtocolOptions.NoExpAccountability() { - return false - } - - return clock.NewDefaultClock().Now().Before( - AccountabilityExperimentEnd, - ) + return !s.cfg.ProtocolOptions.NoExpAccountability() }, NoDisconnectOnPongFailure: s.cfg.NoDisconnectOnPongFailure, }