Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multi: fix loopvar and enhance logging around channel reestablishment #8220

Merged
merged 4 commits into from
Nov 28, 2023
Merged
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
36 changes: 36 additions & 0 deletions channeldb/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,30 @@ type OpenChannel struct {
sync.RWMutex
}

// String returns a string representation of the channel.
func (c *OpenChannel) String() string {
indexStr := "height=%v, local_htlc_index=%v, local_log_index=%v, " +
"remote_htlc_index=%v, remote_log_index=%v"

commit := c.LocalCommitment
local := fmt.Sprintf(indexStr, commit.CommitHeight,
commit.LocalHtlcIndex, commit.LocalLogIndex,
commit.RemoteHtlcIndex, commit.RemoteLogIndex,
)

commit = c.RemoteCommitment
remote := fmt.Sprintf(indexStr, commit.CommitHeight,
commit.LocalHtlcIndex, commit.LocalLogIndex,
commit.RemoteHtlcIndex, commit.RemoteLogIndex,
)

return fmt.Sprintf("SCID=%v, status=%v, initiator=%v, pending=%v, "+
"local commitment has %s, remote commitment has %s",
c.ShortChannelID, c.chanStatus, c.IsInitiator, c.IsPending,
local, remote,
)
}

// ShortChanID returns the current ShortChannelID of this channel.
func (c *OpenChannel) ShortChanID() lnwire.ShortChannelID {
c.RLock()
Expand Down Expand Up @@ -2100,6 +2124,10 @@ func (c *OpenChannel) ActiveHtlcs() []HTLC {
// which ones are present on their commitment.
remoteHtlcs := make(map[[32]byte]struct{})
for _, htlc := range c.RemoteCommitment.Htlcs {
log.Tracef("RemoteCommitment has htlc: id=%v, update=%v "+
"incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
htlc.Incoming)

onionHash := sha256.Sum256(htlc.OnionBlob[:])
remoteHtlcs[onionHash] = struct{}{}
}
Expand All @@ -2108,8 +2136,16 @@ func (c *OpenChannel) ActiveHtlcs() []HTLC {
// as active if *we* know them as well.
activeHtlcs := make([]HTLC, 0, len(remoteHtlcs))
for _, htlc := range c.LocalCommitment.Htlcs {
log.Tracef("LocalCommitment has htlc: id=%v, update=%v "+
"incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
htlc.Incoming)

onionHash := sha256.Sum256(htlc.OnionBlob[:])
if _, ok := remoteHtlcs[onionHash]; !ok {
log.Tracef("Skipped htlc due to onion mismatched: "+
"id=%v, update=%v incoming=%v",
htlc.HtlcIndex, htlc.LogIndex, htlc.Incoming)

continue
}

Expand Down
3 changes: 3 additions & 0 deletions docs/release-notes/release-notes-0.17.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
`musig2Sessions` with a `SyncMap` used in `input` package to avoid concurrent
write to this map.

* [Fixed](https://github.com/lightningnetwork/lnd/pull/8220) a loop variable
issue which may affect programs built using go `v1.20` and below.

# New Features
## Functional Enhancements
## RPC Additions
Expand Down
5 changes: 3 additions & 2 deletions htlcswitch/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -649,12 +649,13 @@ func (l *channelLink) createFailureWithUpdate(incoming bool,
// flow. We'll compare out commitment chains with the remote party, and re-send
// either a danging commit signature, a revocation, or both.
func (l *channelLink) syncChanStates() error {
l.log.Info("attempting to re-synchronize")
chanState := l.channel.State()

l.log.Infof("Attempting to re-synchronize channel: %v", chanState)

// First, we'll generate our ChanSync message to send to the other
// side. Based on this message, the remote party will decide if they
// need to retransmit any data or not.
chanState := l.channel.State()
localChanSyncMsg, err := chanState.ChanSyncMsg()
if err != nil {
return fmt.Errorf("unable to generate chan sync message for "+
Expand Down
2 changes: 2 additions & 0 deletions lnwallet/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,8 @@ func (lc *LightningChannel) extractPayDescs(commitHeight uint64,
// persist state w.r.t to if forwarded or not, or can
// inadvertently trigger replays

htlc := htlc

payDesc, err := lc.diskHtlcToPayDesc(
feeRate, commitHeight, &htlc,
localCommitKeys, remoteCommitKeys,
Expand Down
98 changes: 98 additions & 0 deletions lnwallet/channel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10111,3 +10111,101 @@ func testNewBreachRetribution(t *testing.T, chanType channeldb.ChannelType) {
)
require.ErrorIs(t, err, channeldb.ErrLogEntryNotFound)
}

// TestExtractPayDescs asserts that `extractPayDescs` can correctly turn a
// slice of htlcs into two slices of PaymentDescriptors.
func TestExtractPayDescs(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Important test 👍

t.Parallel()

// Create a testing LightningChannel.
lnChan, _, err := CreateTestChannels(
t, channeldb.SingleFunderTweaklessBit,
)
require.NoError(t, err)

// Create two incoming HTLCs.
incomings := []channeldb.HTLC{
createRandomHTLC(t, true),
createRandomHTLC(t, true),
}

// Create two outgoing HTLCs.
outgoings := []channeldb.HTLC{
createRandomHTLC(t, false),
createRandomHTLC(t, false),
}

// Concatenate incomings and outgoings into a single slice.
htlcs := []channeldb.HTLC{}
htlcs = append(htlcs, incomings...)
htlcs = append(htlcs, outgoings...)

// Run the method under test.
//
// NOTE: we use nil commitment key rings to avoid checking the htlc
// scripts(`genHtlcScript`) as it should be tested independently.
incomingPDs, outgoingPDs, err := lnChan.extractPayDescs(
0, 0, htlcs, nil, nil, true,
)
require.NoError(t, err)

// Assert the incoming PaymentDescriptors are matched.
for i, pd := range incomingPDs {
htlc := incomings[i]
assertPayDescMatchHTLC(t, pd, htlc)
}

// Assert the outgoing PaymentDescriptors are matched.
for i, pd := range outgoingPDs {
htlc := outgoings[i]
assertPayDescMatchHTLC(t, pd, htlc)
}
}

// assertPayDescMatchHTLC compares a PaymentDescriptor to a channeldb.HTLC and
// asserts that the fields are matched.
func assertPayDescMatchHTLC(t *testing.T, pd PaymentDescriptor,
htlc channeldb.HTLC) {

require := require.New(t)

require.EqualValues(htlc.RHash, pd.RHash, "RHash")
require.Equal(htlc.RefundTimeout, pd.Timeout, "Timeout")
require.Equal(htlc.Amt, pd.Amount, "Amount")
require.Equal(htlc.HtlcIndex, pd.HtlcIndex, "HtlcIndex")
require.Equal(htlc.LogIndex, pd.LogIndex, "LogIndex")
require.EqualValues(htlc.OnionBlob[:], pd.OnionBlob, "OnionBlob")
}

// createRandomHTLC creates an HTLC that has random value in every field except
// the `Incoming`.
func createRandomHTLC(t *testing.T, incoming bool) channeldb.HTLC {
var onionBlob [lnwire.OnionPacketSize]byte
_, err := rand.Read(onionBlob[:])
require.NoError(t, err)

var rHash [lntypes.HashSize]byte
_, err = rand.Read(rHash[:])
require.NoError(t, err)

sig := make([]byte, 64)
_, err = rand.Read(sig)
require.NoError(t, err)

extra := make([]byte, 1000)
_, err = rand.Read(extra)
require.NoError(t, err)

return channeldb.HTLC{
Signature: sig,
RHash: rHash,
Amt: lnwire.MilliSatoshi(rand.Uint64()),
RefundTimeout: rand.Uint32(),
OutputIndex: rand.Int31n(1000),
Incoming: incoming,
OnionBlob: onionBlob,
HtlcIndex: rand.Uint64(),
LogIndex: rand.Uint64(),
ExtraData: extra,
}
}
3 changes: 2 additions & 1 deletion peer/brontide.go
Original file line number Diff line number Diff line change
Expand Up @@ -2009,7 +2009,8 @@ func messageSummary(msg lnwire.Message) string {
msg.ChanID, int64(msg.FeePerKw))

case *lnwire.ChannelReestablish:
return fmt.Sprintf("next_local_height=%v, remote_tail_height=%v",
return fmt.Sprintf("chan_id=%v, next_local_height=%v, "+
"remote_tail_height=%v", msg.ChanID,
msg.NextLocalCommitHeight, msg.RemoteCommitTailHeight)

case *lnwire.ReplyShortChanIDsEnd:
Expand Down
Loading