mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-23 14:40:30 +01:00
Merge pull request #5157 from orbitalturtle/addPeer-flag
lnd: Adds addpeer flag
This commit is contained in:
commit
b6c5603e00
7 changed files with 133 additions and 29 deletions
|
@ -293,6 +293,7 @@ type Config struct {
|
||||||
WSPingInterval time.Duration `long:"ws-ping-interval" description:"The ping interval for REST based WebSocket connections, set to 0 to disable sending ping messages from the server side"`
|
WSPingInterval time.Duration `long:"ws-ping-interval" description:"The ping interval for REST based WebSocket connections, set to 0 to disable sending ping messages from the server side"`
|
||||||
WSPongWait time.Duration `long:"ws-pong-wait" description:"The time we wait for a pong response message on REST based WebSocket connections before the connection is closed as inactive"`
|
WSPongWait time.Duration `long:"ws-pong-wait" description:"The time we wait for a pong response message on REST based WebSocket connections before the connection is closed as inactive"`
|
||||||
NAT bool `long:"nat" description:"Toggle NAT traversal support (using either UPnP or NAT-PMP) to automatically advertise your external IP address to the network -- NOTE this does not support devices behind multiple NATs"`
|
NAT bool `long:"nat" description:"Toggle NAT traversal support (using either UPnP or NAT-PMP) to automatically advertise your external IP address to the network -- NOTE this does not support devices behind multiple NATs"`
|
||||||
|
AddPeers []string `long:"addpeer" description:"Specify peers to connect to first"`
|
||||||
MinBackoff time.Duration `long:"minbackoff" description:"Shortest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
|
MinBackoff time.Duration `long:"minbackoff" description:"Shortest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
|
||||||
MaxBackoff time.Duration `long:"maxbackoff" description:"Longest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
|
MaxBackoff time.Duration `long:"maxbackoff" description:"Longest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
|
||||||
ConnectionTimeout time.Duration `long:"connectiontimeout" description:"The timeout value for network connections. Valid time units are {ms, s, m, h}."`
|
ConnectionTimeout time.Duration `long:"connectiontimeout" description:"The timeout value for network connections. Valid time units are {ms, s, m, h}."`
|
||||||
|
|
|
@ -181,6 +181,7 @@ then watch it on chain. Taproot script spends are also supported through the
|
||||||
* [Fix a flaky unit test in the `chainview`
|
* [Fix a flaky unit test in the `chainview`
|
||||||
package](https://github.com/lightningnetwork/lnd/pull/6354).
|
package](https://github.com/lightningnetwork/lnd/pull/6354).
|
||||||
|
|
||||||
|
* [Adds a new config option for adding a specific peer at startup](https://github.com/lightningnetwork/lnd/pull/5157).
|
||||||
|
|
||||||
* [Add a new method in `tlv` to encode an uint64/uint32 field using `BigSize`
|
* [Add a new method in `tlv` to encode an uint64/uint32 field using `BigSize`
|
||||||
format.](https://github.com/lightningnetwork/lnd/pull/6421)
|
format.](https://github.com/lightningnetwork/lnd/pull/6421)
|
||||||
|
@ -276,6 +277,7 @@ gRPC performance metrics (latency to process `GetInfo`, etc)](https://github.com
|
||||||
# Contributors (Alphabetical Order)
|
# Contributors (Alphabetical Order)
|
||||||
|
|
||||||
* 3nprob
|
* 3nprob
|
||||||
|
* Alyssa Hertig
|
||||||
* Andras Banki-Horvath
|
* Andras Banki-Horvath
|
||||||
* Andreas Schjønhaug
|
* Andreas Schjønhaug
|
||||||
* asvdf
|
* asvdf
|
||||||
|
|
|
@ -278,36 +278,9 @@ func ParseAddressString(strAddress string, defaultPort string,
|
||||||
func ParseLNAddressString(strAddress string, defaultPort string,
|
func ParseLNAddressString(strAddress string, defaultPort string,
|
||||||
tcpResolver TCPResolver) (*lnwire.NetAddress, error) {
|
tcpResolver TCPResolver) (*lnwire.NetAddress, error) {
|
||||||
|
|
||||||
// Split the address string around the @ sign.
|
pubKey, parsedAddr, err := ParseLNAddressPubkey(strAddress)
|
||||||
parts := strings.Split(strAddress, "@")
|
|
||||||
|
|
||||||
// The string is malformed if there are not exactly two parts.
|
|
||||||
if len(parts) != 2 {
|
|
||||||
return nil, fmt.Errorf("invalid lightning address %s: "+
|
|
||||||
"must be of the form <pubkey-hex>@<addr>", strAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, take the first portion as the hex pubkey, and the latter as the
|
|
||||||
// address string.
|
|
||||||
parsedPubKey, parsedAddr := parts[0], parts[1]
|
|
||||||
|
|
||||||
// Decode the hex pubkey to get the raw compressed pubkey bytes.
|
|
||||||
pubKeyBytes, err := hex.DecodeString(parsedPubKey)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid lightning address pubkey: %v", err)
|
return nil, err
|
||||||
}
|
|
||||||
|
|
||||||
// The compressed pubkey should have a length of exactly 33 bytes.
|
|
||||||
if len(pubKeyBytes) != 33 {
|
|
||||||
return nil, fmt.Errorf("invalid lightning address pubkey: "+
|
|
||||||
"length must be 33 bytes, found %d", len(pubKeyBytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the pubkey bytes to verify that it corresponds to valid public
|
|
||||||
// key on the secp256k1 curve.
|
|
||||||
pubKey, err := btcec.ParsePubKey(pubKeyBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid lightning address pubkey: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, parse the address string using our generic address parser.
|
// Finally, parse the address string using our generic address parser.
|
||||||
|
@ -322,6 +295,45 @@ func ParseLNAddressString(strAddress string, defaultPort string,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseLNAddressPubkey converts a string of the form <pubkey>@<addr> into two
|
||||||
|
// pieces: the pubkey bytes and an addr string. It validates that the pubkey
|
||||||
|
// is of a valid form.
|
||||||
|
func ParseLNAddressPubkey(strAddress string) (*btcec.PublicKey, string, error) {
|
||||||
|
// Split the address string around the @ sign.
|
||||||
|
parts := strings.Split(strAddress, "@")
|
||||||
|
|
||||||
|
// The string is malformed if there are not exactly two parts.
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return nil, "", fmt.Errorf("invalid lightning address %s: "+
|
||||||
|
"must be of the form <pubkey-hex>@<addr>", strAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, take the first portion as the hex pubkey, and the latter as the
|
||||||
|
// address string.
|
||||||
|
parsedPubKey, parsedAddr := parts[0], parts[1]
|
||||||
|
|
||||||
|
// Decode the hex pubkey to get the raw compressed pubkey bytes.
|
||||||
|
pubKeyBytes, err := hex.DecodeString(parsedPubKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", fmt.Errorf("invalid lightning address pubkey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The compressed pubkey should have a length of exactly 33 bytes.
|
||||||
|
if len(pubKeyBytes) != 33 {
|
||||||
|
return nil, "", fmt.Errorf("invalid lightning address pubkey: "+
|
||||||
|
"length must be 33 bytes, found %d", len(pubKeyBytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the pubkey bytes to verify that it corresponds to valid public
|
||||||
|
// key on the secp256k1 curve.
|
||||||
|
pubKey, err := btcec.ParsePubKey(pubKeyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", fmt.Errorf("invalid lightning address pubkey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pubKey, parsedAddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
// verifyPort makes sure that an address string has both a host and a port. If
|
// verifyPort makes sure that an address string has both a host and a port. If
|
||||||
// there is no port found, the default port is appended. If the address is just
|
// there is no port found, the default port is appended. If the address is just
|
||||||
// a port, then we'll assume that the user is using the short cut to specify a
|
// a port, then we'll assume that the user is using the short cut to specify a
|
||||||
|
|
|
@ -3,10 +3,12 @@ package itest
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
network "net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd"
|
"github.com/lightningnetwork/lnd"
|
||||||
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -278,3 +280,46 @@ func connect(ctxt context.Context, node *lntest.HarnessNode,
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testAddPeerConfig tests that the "--addpeer" config flag successfully adds
|
||||||
|
// a new peer.
|
||||||
|
func testAddPeerConfig(net *lntest.NetworkHarness, t *harnessTest) {
|
||||||
|
ctxb := context.Background()
|
||||||
|
|
||||||
|
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
|
||||||
|
defer cancel()
|
||||||
|
alice := net.Alice
|
||||||
|
info, err := alice.GetInfo(ctxt, &lnrpc.GetInfoRequest{})
|
||||||
|
require.NoError(t.t, err)
|
||||||
|
|
||||||
|
alicePeerAddress := info.Uris[0]
|
||||||
|
|
||||||
|
// Create a new node (Carol) with Alice as a peer.
|
||||||
|
args := []string{
|
||||||
|
fmt.Sprintf("--addpeer=%v", alicePeerAddress),
|
||||||
|
}
|
||||||
|
carol := net.NewNode(t.t, "Carol", args)
|
||||||
|
defer shutdownAndAssert(net, t, carol)
|
||||||
|
|
||||||
|
assertConnected(t, alice, carol)
|
||||||
|
|
||||||
|
// If we list Carol's peers, Alice should already be
|
||||||
|
// listed as one, since we specified her using the
|
||||||
|
// addpeer flag.
|
||||||
|
ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
|
defer cancel()
|
||||||
|
listPeersRequest := &lnrpc.ListPeersRequest{}
|
||||||
|
listPeersResp, err := carol.ListPeers(ctxt, listPeersRequest)
|
||||||
|
require.NoError(t.t, err)
|
||||||
|
|
||||||
|
parsedPeerAddr, err := lncfg.ParseLNAddressString(
|
||||||
|
alicePeerAddress, "9735", network.ResolveTCPAddr,
|
||||||
|
)
|
||||||
|
require.NoError(t.t, err)
|
||||||
|
|
||||||
|
parsedKeyStr := fmt.Sprintf(
|
||||||
|
"%x", parsedPeerAddr.IdentityKey.SerializeCompressed(),
|
||||||
|
)
|
||||||
|
|
||||||
|
require.Equal(t.t, parsedKeyStr, listPeersResp.Peers[0].PubKey)
|
||||||
|
}
|
||||||
|
|
|
@ -395,4 +395,8 @@ var allTestCases = []*testCase{
|
||||||
name: "taproot",
|
name: "taproot",
|
||||||
test: testTaproot,
|
test: testTaproot,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "addpeer config",
|
||||||
|
test: testAddPeerConfig,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,6 +183,9 @@
|
||||||
; Disable TLS for the REST API.
|
; Disable TLS for the REST API.
|
||||||
; no-rest-tls=true
|
; no-rest-tls=true
|
||||||
|
|
||||||
|
; Specify peer(s) to connect to first.
|
||||||
|
; addpeer=
|
||||||
|
|
||||||
; The ping interval for REST based WebSocket connections, set to 0 to disable
|
; The ping interval for REST based WebSocket connections, set to 0 to disable
|
||||||
; sending ping messages from the server side. Valid time units are {s, m, h}.
|
; sending ping messages from the server side. Valid time units are {s, m, h}.
|
||||||
; ws-ping-interval=30s
|
; ws-ping-interval=30s
|
||||||
|
|
37
server.go
37
server.go
|
@ -1905,6 +1905,43 @@ func (s *server) Start() error {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// If peers are specified as a config option, we'll add those
|
||||||
|
// peers first.
|
||||||
|
for _, peerAddrCfg := range s.cfg.AddPeers {
|
||||||
|
parsedPubkey, parsedHost, err := lncfg.ParseLNAddressPubkey(
|
||||||
|
peerAddrCfg,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
startErr = fmt.Errorf("unable to parse peer "+
|
||||||
|
"pubkey from config: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addr, err := parseAddr(parsedHost, s.cfg.net)
|
||||||
|
if err != nil {
|
||||||
|
startErr = fmt.Errorf("unable to parse peer "+
|
||||||
|
"address provided as a config option: "+
|
||||||
|
"%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
peerAddr := &lnwire.NetAddress{
|
||||||
|
IdentityKey: parsedPubkey,
|
||||||
|
Address: addr,
|
||||||
|
ChainNet: s.cfg.ActiveNetParams.Net,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.ConnectToPeer(
|
||||||
|
peerAddr, true,
|
||||||
|
s.cfg.ConnectionTimeout,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
startErr = fmt.Errorf("unable to connect to "+
|
||||||
|
"peer address provided as a config "+
|
||||||
|
"option: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Subscribe to NodeAnnouncements that advertise new addresses
|
// Subscribe to NodeAnnouncements that advertise new addresses
|
||||||
// our persistent peers.
|
// our persistent peers.
|
||||||
if err := s.updatePersistentPeerAddrs(); err != nil {
|
if err := s.updatePersistentPeerAddrs(); err != nil {
|
||||||
|
|
Loading…
Add table
Reference in a new issue