What changed, and why it matters
This commit only updates integration tests to account for an experimental feature's activation window expiring. It does not change production code behavior or fix any security vulnerability. The new helper checks whether the endorsement experiment is still active and adjusts test expectations accordingly.
No security action required. This is a test-maintenance commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies three test-related files. It introduces lntest.ExperimentalEndorsementActive(), which compares time.Now() against lnd.EndorsementExperimentEnd. Test helpers and two integration tests (testEndorsement, testForwardInterceptorRestart) now conditionally expect endorsement custom records only while the experiment window is open. No consensus, networking, or wallet code is changed.
Changed components
itest/lnd_experimental_endorsement.goitest/lnd_forward_interceptor_test.golntest/utils.goInspect captured patch +50 / −11
diff --git a/itest/lnd_experimental_endorsement.go b/itest/lnd_experimental_endorsement.go
index 7b0fc21..67f5e30 100644
--- a/itest/lnd_experimental_endorsement.go
+++ b/itest/lnd_experimental_endorsement.go
@@ -57,12 +57,18 @@ func testEndorsement(ht *lntest.HarnessTest, aliceEndorse bool) {
FeeLimitMsat: math.MaxInt64,
}
- expectedValue := []byte{lnwire.ExperimentalUnendorsed}
- if aliceEndorse {
- expectedValue = []byte{lnwire.ExperimentalEndorsed}
- t := uint64(lnwire.ExperimentalEndorsementType)
- sendReq.FirstHopCustomRecords = map[uint64][]byte{
- t: expectedValue,
+ var expectedValue []byte
+ hasEndorsement := lntest.ExperimentalEndorsementActive()
+
+ if hasEndorsement {
+ if aliceEndorse {
+ expectedValue = []byte{lnwire.ExperimentalEndorsed}
+ t := uint64(lnwire.ExperimentalEndorsementType)
+ sendReq.FirstHopCustomRecords = map[uint64][]byte{
+ t: expectedValue,
+ }
+ } else {
+ expectedValue = []byte{lnwire.ExperimentalUnendorsed}
}
}
@@ -70,8 +76,13 @@ 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)
+ // When the endorsement experiment is not active, no signal is sent.
+ validateEndorsedAndResume(
+ ht, bobIntercept, hasEndorsement, expectedValue,
+ )
+ validateEndorsedAndResume(
+ ht, carolIntercept, hasEndorsement, expectedValue,
+ )
validateEndorsedAndResume(ht, daveIntercept, false, nil)
var preimage lntypes.Preimage
diff --git a/itest/lnd_forward_interceptor_test.go b/itest/lnd_forward_interceptor_test.go
index 8eec171..615f9f4 100644
--- a/itest/lnd_forward_interceptor_test.go
+++ b/itest/lnd_forward_interceptor_test.go
@@ -432,14 +432,25 @@ func testForwardInterceptorRestart(ht *lntest.HarnessTest) {
// We should get another notification about the held HTLC.
packet = ht.ReceiveHtlcInterceptor(bobInterceptor)
- require.Len(ht, packet.InWireCustomRecords, 2)
+ // Check the expected number of custom records based on whether the
+ // endorsement experiment is still active.
+ expectedLen := 1
+ if lntest.ExperimentalEndorsementActive() {
+ expectedLen = 2
+ }
+ require.Len(ht, packet.InWireCustomRecords, expectedLen)
require.Equal(ht, lntest.CustomRecordsWithUnendorsed(customRecords),
packet.InWireCustomRecords)
// And now we forward the payment at Carol, expecting only an
- // endorsement signal in our incoming custom records.
+ // endorsement signal in our incoming custom records (if the experiment
+ // is still active).
packet = ht.ReceiveHtlcInterceptor(carolInterceptor)
- require.Len(ht, packet.InWireCustomRecords, 1)
+ expectedCarolLen := 0
+ if lntest.ExperimentalEndorsementActive() {
+ expectedCarolLen = 1
+ }
+ require.Len(ht, packet.InWireCustomRecords, expectedCarolLen)
err = carolInterceptor.Send(&routerrpc.ForwardHtlcInterceptResponse{
IncomingCircuitKey: packet.IncomingCircuitKey,
Action: actionResume,
diff --git a/lntest/utils.go b/lntest/utils.go
index a07b064..ab998ec 100644
--- a/lntest/utils.go
+++ b/lntest/utils.go
@@ -7,9 +7,11 @@ 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"
@@ -288,6 +290,15 @@ func CalcStaticFeeBuffer(c lnrpc.CommitmentType, numHTLCs int) btcutil.Amount {
func CustomRecordsWithUnendorsed(
originalRecords lnwire.CustomRecords) map[uint64][]byte {
+ if !ExperimentalEndorsementActive() {
+ // 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.ExperimentalEndorsementType): {
lnwire.ExperimentalUnendorsed,
@@ -295,6 +306,12 @@ func CustomRecordsWithUnendorsed(
)
}
+// ExperimentalEndorsementActive returns true if the experimental endorsement
+// window is still open.
+func ExperimentalEndorsementActive() bool {
+ return time.Now().Before(lnd.EndorsementExperimentEnd)
+}
+
// LnrpcOutpointToStr returns a string representation of an lnrpc.OutPoint.
func LnrpcOutpointToStr(outpoint *lnrpc.OutPoint) string {
return fmt.Sprintf("%s:%d", outpoint.TxidStr, outpoint.OutputIndex)
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.