diff --git a/itest/lnd_open_channel_test.go b/itest/lnd_open_channel_test.go index 744d211f1..0b26b2171 100644 --- a/itest/lnd_open_channel_test.go +++ b/itest/lnd_open_channel_test.go @@ -2,6 +2,7 @@ package itest import ( "fmt" + "strings" "testing" "github.com/btcsuite/btcd/btcjson" @@ -373,16 +374,32 @@ func runBasicChannelCreationAndUpdates(ht *lntest.HarnessTest, aliceChanSub := alice.RPC.SubscribeChannelEvents() // Open the channels between Alice and Bob, asserting that the channels - // have been properly opened on-chain. + // have been properly opened on-chain. We also attach the optional Memo + // argument to one of the channels so we can test that it can be + // retrieved correctly when querying the created channel. chanPoints := make([]*lnrpc.ChannelPoint, numChannels) + openChannelParams := []lntest.OpenChannelParams{ + {Amt: amount, Memo: "bob is a good peer"}, + {Amt: amount}, + } for i := 0; i < numChannels; i++ { chanPoints[i] = ht.OpenChannel( - alice, bob, lntest.OpenChannelParams{ - Amt: amount, - }, + alice, bob, openChannelParams[i], ) } + // Alice should see the memo when retrieving the first channel. + channel := ht.QueryChannelByChanPoint(alice, chanPoints[0]) + require.Equal(ht, "bob is a good peer", channel.Memo) + + // Bob shouldn't see the memo since it's for Alice only. + channel = ht.QueryChannelByChanPoint(bob, chanPoints[0]) + require.Empty(ht, channel.Memo, "Memo is not empty") + + // The second channel doesn't have a memo. + channel = ht.QueryChannelByChanPoint(alice, chanPoints[1]) + require.Empty(ht, channel.Memo, "Memo is not empty") + // Since each of the channels just became open, Bob and Alice should // each receive an open and an active notification for each channel. const numExpectedOpenUpdates = 3 * numChannels @@ -445,6 +462,16 @@ func runBasicChannelCreationAndUpdates(ht *lntest.HarnessTest, } } + // If Bob now tries to open a channel with an invalid memo, reject it. + invalidMemo := strings.Repeat("a", 501) + params := lntest.OpenChannelParams{ + Amt: funding.MaxBtcFundingAmount, + Memo: invalidMemo, + } + expErr := fmt.Errorf("provided memo (%s) is of length 501, exceeds 500", + invalidMemo) + ht.OpenChannelAssertErr(bob, alice, params, expErr) + // verifyCloseUpdatesReceived is used to verify that Alice and Bob // receive the correct channel updates in order. const numExpectedCloseUpdates = 3 * numChannels diff --git a/lntest/harness.go b/lntest/harness.go index 19a6f7f24..9cbca8fba 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -890,6 +890,12 @@ type OpenChannelParams struct { // FundMax is a boolean indicating whether the channel should be funded // with the maximum possible amount from the wallet. FundMax bool + + // An optional note-to-self containing some useful information about the + // channel. This is stored locally only, and is purely for reference. It + // has no bearing on the channel's operation. Max allowed length is 500 + // characters. + Memo string } // prepareOpenChannel waits for both nodes to be synced to chain and returns an @@ -931,6 +937,7 @@ func (h *HarnessTest) prepareOpenChannel(srcNode, destNode *node.HarnessNode, UseBaseFee: p.UseBaseFee, UseFeeRate: p.UseFeeRate, FundMax: p.FundMax, + Memo: p.Memo, } }