mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-22 14:22:37 +01:00
lntest/harness: harden ConnectEnsure
Alters the behavior of ConnectEnsure to initiate a connection attempt in both directions. Additionally, the wait predicate only returns true after cross checking both peer lists.
This commit is contained in:
parent
2490b9b6e3
commit
0d8f4f4be4
1 changed files with 60 additions and 26 deletions
|
@ -1,6 +1,7 @@
|
||||||
package lntest
|
package lntest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -271,53 +272,86 @@ func (n *NetworkHarness) NewNode(extraArgs []string) (*HarnessNode, error) {
|
||||||
// been made, the method will block until the two nodes appear in each other's
|
// been made, the method will block until the two nodes appear in each other's
|
||||||
// peers list, or until the 15s timeout expires.
|
// peers list, or until the 15s timeout expires.
|
||||||
func (n *NetworkHarness) EnsureConnected(ctx context.Context, a, b *HarnessNode) error {
|
func (n *NetworkHarness) EnsureConnected(ctx context.Context, a, b *HarnessNode) error {
|
||||||
bobInfo, err := b.GetInfo(ctx, &lnrpc.GetInfoRequest{})
|
// errConnectionRequested is used to signal that a connection was
|
||||||
if err != nil {
|
// requested successfully, which is distinct from already being
|
||||||
return err
|
// connected to the peer.
|
||||||
|
errConnectionRequested := errors.New("connection request in progress")
|
||||||
|
|
||||||
|
tryConnect := func(a, b *HarnessNode) error {
|
||||||
|
ctxt, _ := context.WithTimeout(ctx, 15*time.Second)
|
||||||
|
bInfo, err := b.GetInfo(ctxt, &lnrpc.GetInfoRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &lnrpc.ConnectPeerRequest{
|
||||||
|
Addr: &lnrpc.LightningAddress{
|
||||||
|
Pubkey: bInfo.IdentityPubkey,
|
||||||
|
Host: b.cfg.P2PAddr(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt, _ = context.WithTimeout(ctx, 15*time.Second)
|
||||||
|
_, err = a.ConnectPeer(ctxt, req)
|
||||||
|
switch {
|
||||||
|
|
||||||
|
// Request was successful, wait for both to display the
|
||||||
|
// connection.
|
||||||
|
case err == nil:
|
||||||
|
return errConnectionRequested
|
||||||
|
|
||||||
|
// If the two are already connected, we return early with no
|
||||||
|
// error.
|
||||||
|
case strings.Contains(err.Error(), "already connected to peer"):
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req := &lnrpc.ConnectPeerRequest{
|
aErr := tryConnect(a, b)
|
||||||
Addr: &lnrpc.LightningAddress{
|
bErr := tryConnect(b, a)
|
||||||
Pubkey: bobInfo.IdentityPubkey,
|
|
||||||
Host: b.cfg.P2PAddr(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = a.ConnectPeer(ctx, req)
|
|
||||||
switch {
|
switch {
|
||||||
|
case aErr == nil && bErr == nil:
|
||||||
// Request was successful, wait for both to display the connection.
|
// If both reported already being connected to each other, we
|
||||||
case err == nil:
|
// can exit early.
|
||||||
|
|
||||||
// If we already have pending connection, we will wait until bob appears
|
|
||||||
// in alice's peer list.
|
|
||||||
case strings.Contains(err.Error(), "connection attempt to ") &&
|
|
||||||
strings.Contains(err.Error(), " is pending"):
|
|
||||||
|
|
||||||
// If the two are already connected, we return early with no error.
|
|
||||||
case strings.Contains(err.Error(), "already connected to peer"):
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
case aErr != errConnectionRequested:
|
||||||
|
// Return any critical errors returned by either alice.
|
||||||
|
return aErr
|
||||||
|
|
||||||
|
case bErr != errConnectionRequested:
|
||||||
|
// Return any critical errors returned by either bob.
|
||||||
|
return bErr
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return err
|
// Otherwise one or both requested a connection, so we wait for
|
||||||
|
// the peers lists to reflect the connection.
|
||||||
}
|
}
|
||||||
|
|
||||||
err = WaitPredicate(func() bool {
|
findSelfInPeerList := func(a, b *HarnessNode) bool {
|
||||||
// If node B is seen in the ListPeers response from node A,
|
// If node B is seen in the ListPeers response from node A,
|
||||||
// then we can exit early as the connection has been fully
|
// then we can exit early as the connection has been fully
|
||||||
// established.
|
// established.
|
||||||
resp, err := a.ListPeers(ctx, &lnrpc.ListPeersRequest{})
|
ctxt, _ := context.WithTimeout(ctx, 15*time.Second)
|
||||||
|
resp, err := b.ListPeers(ctxt, &lnrpc.ListPeersRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, peer := range resp.Peers {
|
for _, peer := range resp.Peers {
|
||||||
if peer.PubKey == b.PubKeyStr {
|
if peer.PubKey == a.PubKeyStr {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
err := WaitPredicate(func() bool {
|
||||||
|
return findSelfInPeerList(a, b) && findSelfInPeerList(b, a)
|
||||||
}, time.Second*15)
|
}, time.Second*15)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("peers not connected within 15 seconds")
|
return fmt.Errorf("peers not connected within 15 seconds")
|
||||||
|
|
Loading…
Add table
Reference in a new issue