discovery: send policy updates for private channels directly to the remote peer
In this commit, we modify the main loop in `processChanPolicyUpdate` to send updates for private channels directly to the remote peer via the reliable message sender. This fixes a prior issue where the remote peer wouldn't receive new updates as this method doesn't go through the traditional path for channel updates.
This commit is contained in:
parent
a9d6273828
commit
53beed7aaf
@ -1293,8 +1293,22 @@ func (d *AuthenticatedGossiper) processChanPolicyUpdate(
|
||||
}
|
||||
|
||||
// We'll avoid broadcasting any updates for private channels to
|
||||
// avoid directly giving away their existence.
|
||||
// avoid directly giving away their existence. Instead, we'll
|
||||
// send the update directly to the remote party.
|
||||
if edgeInfo.info.AuthProof == nil {
|
||||
remotePubKey := remotePubFromChanInfo(
|
||||
edgeInfo.info, chanUpdate.ChannelFlags,
|
||||
)
|
||||
err := d.reliableSender.sendMessage(
|
||||
chanUpdate, remotePubKey,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to reliably send %v for "+
|
||||
"channel=%v to peer=%x: %v",
|
||||
chanUpdate.MsgType(),
|
||||
chanUpdate.ShortChannelID,
|
||||
remotePubKey, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@ -1928,13 +1942,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(
|
||||
// so we'll try sending the update directly to the remote peer.
|
||||
if !nMsg.isRemote && chanInfo.AuthProof == nil {
|
||||
// Get our peer's public key.
|
||||
var remotePubKey [33]byte
|
||||
switch {
|
||||
case msg.ChannelFlags&lnwire.ChanUpdateDirection == 0:
|
||||
remotePubKey = chanInfo.NodeKey2Bytes
|
||||
case msg.ChannelFlags&lnwire.ChanUpdateDirection == 1:
|
||||
remotePubKey = chanInfo.NodeKey1Bytes
|
||||
}
|
||||
remotePubKey := remotePubFromChanInfo(
|
||||
chanInfo, msg.ChannelFlags,
|
||||
)
|
||||
|
||||
// Now, we'll attempt to send the channel update message
|
||||
// reliably to the remote peer in the background, so
|
||||
|
@ -3351,6 +3351,24 @@ func TestPropagateChanPolicyUpdate(t *testing.T) {
|
||||
sentMsgs := make(chan lnwire.Message, 10)
|
||||
remotePeer := &mockPeer{remoteKey, sentMsgs, ctx.gossiper.quit}
|
||||
|
||||
// The forced code path for sending the private ChannelUpdate to the
|
||||
// remote peer will be hit, forcing it to request a notification that
|
||||
// the remote peer is active. We'll ensure that it targets the proper
|
||||
// pubkey, and hand it our mock peer above.
|
||||
notifyErr := make(chan error, 1)
|
||||
ctx.gossiper.reliableSender.cfg.NotifyWhenOnline = func(
|
||||
targetPub *btcec.PublicKey, peerChan chan<- lnpeer.Peer) {
|
||||
|
||||
if !targetPub.IsEqual(remoteKey) {
|
||||
notifyErr <- fmt.Errorf("reliableSender attempted to send the "+
|
||||
"message to the wrong peer: expected %x got %x",
|
||||
remoteKey.SerializeCompressed(),
|
||||
targetPub.SerializeCompressed())
|
||||
}
|
||||
|
||||
peerChan <- remotePeer
|
||||
}
|
||||
|
||||
// With our channel announcements created, we'll now send them all to
|
||||
// the gossiper in order for it to process. However, we'll hold back
|
||||
// the channel ann proof from the first channel in order to have it be
|
||||
@ -3374,12 +3392,16 @@ func TestPropagateChanPolicyUpdate(t *testing.T) {
|
||||
sendRemoteMsg(t, ctx, batch.remoteProofAnn, remotePeer)
|
||||
}
|
||||
|
||||
// Drain out any broadcast messages we might not have read up to this
|
||||
// point.
|
||||
// Drain out any broadcast or direct messages we might not have read up
|
||||
// to this point. We'll also check out notifyErr to detect if the
|
||||
// reliable sender had an issue sending to the remote peer.
|
||||
out:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.broadcastedMessage:
|
||||
case <-sentMsgs:
|
||||
case err := <-notifyErr:
|
||||
t.Fatal(err)
|
||||
default:
|
||||
break out
|
||||
}
|
||||
@ -3419,6 +3441,45 @@ out:
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Finally the ChannelUpdate should have been sent directly to the
|
||||
// remote peer via the reliable sender.
|
||||
select {
|
||||
case msg := <-sentMsgs:
|
||||
upd, ok := msg.(*lnwire.ChannelUpdate)
|
||||
if !ok {
|
||||
t.Fatalf("channel update not "+
|
||||
"broadcast, instead %T was", msg)
|
||||
}
|
||||
if upd.TimeLockDelta != newTimeLockDelta {
|
||||
t.Fatalf("wrong delta: expected %v, "+
|
||||
"got %v", newTimeLockDelta,
|
||||
upd.TimeLockDelta)
|
||||
}
|
||||
if upd.ShortChannelID != firstChanID {
|
||||
t.Fatalf("private channel upd " +
|
||||
"broadcast")
|
||||
}
|
||||
case <-time.After(time.Second * 5):
|
||||
t.Fatalf("message not sent directly to peer")
|
||||
}
|
||||
|
||||
// At this point, no other ChannelUpdate messages should be broadcast
|
||||
// as we sent the two public ones to the network, and the private one
|
||||
// was sent directly to the peer.
|
||||
for {
|
||||
select {
|
||||
case msg := <-ctx.broadcastedMessage:
|
||||
if upd, ok := msg.msg.(*lnwire.ChannelUpdate); ok {
|
||||
if upd.ShortChannelID == firstChanID {
|
||||
t.Fatalf("chan update msg received: %v",
|
||||
spew.Sdump(msg))
|
||||
}
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func assertMessage(t *testing.T, expected, got lnwire.Message) {
|
||||
|
@ -146,3 +146,19 @@ func SignAnnouncement(signer lnwallet.MessageSigner, pubKey *btcec.PublicKey,
|
||||
|
||||
return signer.SignMessage(pubKey, data)
|
||||
}
|
||||
|
||||
// remotePubFromChanInfo returns the public key of the remote peer given a
|
||||
// ChannelEdgeInfo that describe a channel we have with them.
|
||||
func remotePubFromChanInfo(chanInfo *channeldb.ChannelEdgeInfo,
|
||||
chanFlags lnwire.ChanUpdateChanFlags) [33]byte {
|
||||
|
||||
var remotePubKey [33]byte
|
||||
switch {
|
||||
case chanFlags&lnwire.ChanUpdateDirection == 0:
|
||||
remotePubKey = chanInfo.NodeKey2Bytes
|
||||
case chanFlags&lnwire.ChanUpdateDirection == 1:
|
||||
remotePubKey = chanInfo.NodeKey1Bytes
|
||||
}
|
||||
|
||||
return remotePubKey
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user