Skip to content
Open
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
4 changes: 4 additions & 0 deletions docs/release-notes/release-notes-0.21.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,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
Expand Down
2 changes: 1 addition & 1 deletion feature/default_sets.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ var defaultSetDesc = setDesc{
SetInit: {}, // I
SetNodeAnn: {}, // N
},
lnwire.ExperimentalEndorsementOptional: {
lnwire.ExperimentalAccountabilityOptional: {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: one mention of endorsement left in comment.

SetNodeAnn: {}, // N
},
lnwire.RbfCoopCloseOptionalStaging: {
Expand Down
12 changes: 6 additions & 6 deletions feature/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
48 changes: 23 additions & 25 deletions htlcswitch/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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},
}
})

Expand Down Expand Up @@ -3340,44 +3340,42 @@ 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
// experimentalAccountability returns the value to set for our outgoing
// experimental accountable field, and a boolean indicating whether it should
// be populated on the outgoing htlc.
func (l *channelLink) experimentalEndorsement(
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
Expand Down
46 changes: 23 additions & 23 deletions htlcswitch/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
42 changes: 21 additions & 21 deletions htlcswitch/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down
4 changes: 2 additions & 2 deletions itest/list_on_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -700,8 +700,8 @@ var allTestCases = []*lntest.TestCase{
TestFunc: testDebuglevelShow,
},
{
Name: "experimental endorsement",
TestFunc: testExperimentalEndorsement,
Name: "experimental accountability",
TestFunc: testExperimentalAccountability,
},
{
Name: "quiescence",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down Expand Up @@ -57,10 +57,10 @@ func testEndorsement(ht *lntest.HarnessTest, aliceEndorse bool) {
FeeLimitMsat: math.MaxInt64,
}

expectedValue := []byte{lnwire.ExperimentalUnendorsed}
if aliceEndorse {
expectedValue = []byte{lnwire.ExperimentalEndorsed}
t := uint64(lnwire.ExperimentalEndorsementType)
expectedValue := []byte{lnwire.ExperimentalUnaccountable}
if aliceAccountable {
expectedValue = []byte{lnwire.ExperimentalAccountable}
t := uint64(lnwire.ExperimentalAccountableType)
sendReq.FirstHopCustomRecords = map[uint64][]byte{
t: expectedValue,
}
Expand All @@ -70,24 +70,24 @@ 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.
validateEndorsedAndResume(ht, bobIntercept, true, expectedValue)
validateEndorsedAndResume(ht, carolIntercept, true, expectedValue)
validateEndorsedAndResume(ht, daveIntercept, false, nil)
validateAccountableAndResume(ht, bobIntercept, true, expectedValue)
validateAccountableAndResume(ht, carolIntercept, true, expectedValue)
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,
}
Expand Down
8 changes: 4 additions & 4 deletions itest/lnd_forward_interceptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -433,11 +433,11 @@ func testForwardInterceptorRestart(ht *lntest.HarnessTest) {
packet = ht.ReceiveHtlcInterceptor(bobInterceptor)

require.Len(ht, packet.InWireCustomRecords, 2)
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.
// accountable signal in our incoming custom records.
packet = ht.ReceiveHtlcInterceptor(carolInterceptor)
require.Len(ht, packet.InWireCustomRecords, 1)
err = carolInterceptor.Send(&routerrpc.ForwardHtlcInterceptResponse{
Expand All @@ -451,7 +451,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,
)
Expand Down
Loading