diff --git a/cmd/juno/juno.go b/cmd/juno/juno.go index 65ffa90c51..1669143ab8 100644 --- a/cmd/juno/juno.go +++ b/cmd/juno/juno.go @@ -54,6 +54,7 @@ const ( pendingPollIntervalF = "pending-poll-interval" p2pF = "p2p" p2pAddrF = "p2p-addr" + p2pPublicAddrF = "p2p-public-addr" p2pPeersF = "p2p-peers" p2pFeederNodeF = "p2p-feeder-node" p2pPrivateKey = "p2p-private-key" @@ -95,6 +96,7 @@ const ( defaultPendingPollInterval = 5 * time.Second defaultP2p = false defaultP2pAddr = "" + defaultP2pPublicAddr = "" defaultP2pPeers = "" defaultP2pFeederNode = false defaultP2pPrivateKey = "" @@ -143,7 +145,8 @@ const ( "Juno must connect to an Ethereum node and parse events in the Starknet contract." pendingPollIntervalUsage = "Sets how frequently pending block will be updated (0s will disable fetching of pending block)." p2pUsage = "EXPERIMENTAL: Enables p2p server." - p2pAddrUsage = "EXPERIMENTAL: Specify p2p source address as multiaddr." + p2pAddrUsage = "EXPERIMENTAL: Specify p2p listening source address as multiaddr. Example: /ip4/0.0.0.0/tcp/7777" + p2pPublicAddrUsage = "EXPERIMENTAL: Specify p2p public address as multiaddr. Example: /ip4/35.243.XXX.XXX/tcp/7777" p2pPeersUsage = "EXPERIMENTAL: Specify list of p2p peers split by a comma. " + "These peers can be either Feeder or regular nodes." p2pFeederNodeUsage = "EXPERIMENTAL: Run juno as a feeder node which will only sync from feeder gateway and gossip the new" + @@ -328,6 +331,7 @@ func NewCmd(config *node.Config, run func(*cobra.Command, []string) error) *cobr junoCmd.Flags().Duration(pendingPollIntervalF, defaultPendingPollInterval, pendingPollIntervalUsage) junoCmd.Flags().Bool(p2pF, defaultP2p, p2pUsage) junoCmd.Flags().String(p2pAddrF, defaultP2pAddr, p2pAddrUsage) + junoCmd.Flags().String(p2pPublicAddrF, defaultP2pPublicAddr, p2pPublicAddrUsage) junoCmd.Flags().String(p2pPeersF, defaultP2pPeers, p2pPeersUsage) junoCmd.Flags().Bool(p2pFeederNodeF, defaultP2pFeederNode, p2pFeederNodeUsage) junoCmd.Flags().String(p2pPrivateKey, defaultP2pPrivateKey, p2pPrivateKeyUsage) diff --git a/node/node.go b/node/node.go index 6a20829e89..1d61267b35 100644 --- a/node/node.go +++ b/node/node.go @@ -72,6 +72,7 @@ type Config struct { P2P bool `mapstructure:"p2p"` P2PAddr string `mapstructure:"p2p-addr"` + P2PPublicAddr string `mapstructure:"p2p-public-addr"` P2PPeers string `mapstructure:"p2p-peers"` P2PFeederNode bool `mapstructure:"p2p-feeder-node"` P2PPrivateKey string `mapstructure:"p2p-private-key"` @@ -165,7 +166,7 @@ func New(cfg *Config, version string) (*Node, error) { //nolint:gocyclo,funlen // Do not start the feeder synchronisation synchronizer = nil } - p2pService, err = p2p.New(cfg.P2PAddr, version, cfg.P2PPeers, cfg.P2PPrivateKey, cfg.P2PFeederNode, + p2pService, err = p2p.New(cfg.P2PAddr, cfg.P2PPublicAddr, version, cfg.P2PPeers, cfg.P2PPrivateKey, cfg.P2PFeederNode, chain, &cfg.Network, log, database) if err != nil { return nil, fmt.Errorf("set up p2p service: %w", err) diff --git a/p2p/p2p.go b/p2p/p2p.go index 74fb5ab855..8b909f002c 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -54,7 +54,7 @@ type Service struct { database db.DB } -func New(addr, version, peers, privKeyStr string, feederNode bool, bc *blockchain.Blockchain, snNetwork *utils.Network, +func New(addr, publicAddr, version, peers, privKeyStr string, feederNode bool, bc *blockchain.Blockchain, snNetwork *utils.Network, log utils.SimpleLogger, database db.DB, ) (*Service, error) { if addr == "" { @@ -66,12 +66,46 @@ func New(addr, version, peers, privKeyStr string, feederNode bool, bc *blockchai return nil, err } + var publicMultiAddr multiaddr.Multiaddr + if publicAddr != "" { + publicMultiAddr, err = multiaddr.NewMultiaddr(publicAddr) + if err != nil { + return nil, err + } + } + prvKey, err := privateKey(privKeyStr) if err != nil { return nil, err } - p2pHost, err := libp2p.New(libp2p.ListenAddrs(sourceMultiAddr), libp2p.Identity(prvKey), libp2p.UserAgent(makeAgentName(version))) + // The address Factory is used when the public ip is passed to the node. + // In this case the node will NOT try to listen to the public IP because + // it is not possible to listen to a public IP. Instead, the node will + // listen to the private one (or 0.0.0.0) and will add the public IP to + // the list of addresses that it will advertise to the network. + addressFactory := func(addrs []multiaddr.Multiaddr) []multiaddr.Multiaddr { + if publicMultiAddr != nil { + addrs = append(addrs, publicMultiAddr) + } + return addrs + } + + p2pHost, err := libp2p.New( + libp2p.ListenAddrs(sourceMultiAddr), + libp2p.Identity(prvKey), + libp2p.UserAgent(makeAgentName(version)), + // Use address factory to add the public address to the list of + // addresses that the node will advertise. + libp2p.AddrsFactory(addressFactory), + // If we know the public ip, enable the relay service. + libp2p.EnableRelayService(), + // When listening behind NAT, enable peers to try to poke thought the + // NAT in order to reach the node. + libp2p.EnableHolePunching(), + // Try to open a port in the NAT router to accept incoming connections. + libp2p.NATPortMap(), + ) if err != nil { return nil, err } diff --git a/p2p/p2p_test.go b/p2p/p2p_test.go index e91281c48b..070a9eedb8 100644 --- a/p2p/p2p_test.go +++ b/p2p/p2p_test.go @@ -139,6 +139,7 @@ func TestService(t *testing.T) { func TestInvalidKey(t *testing.T) { _, err := p2p.New( "/ip4/127.0.0.1/tcp/30301", + "", "peerA", "", "something", @@ -156,6 +157,7 @@ func TestValidKey(t *testing.T) { t.Skip("TestValidKey") _, err := p2p.New( "/ip4/127.0.0.1/tcp/30301", + "", "peerA", "", "08011240333b4a433f16d7ca225c0e99d0d8c437b835cb74a98d9279c561977690c80f681b25ccf3fa45e2f2de260149c112fa516b69057dd3b0151a879416c0cb12d9b3", @@ -192,6 +194,7 @@ func TestLoadAndPersistPeers(t *testing.T) { _, err = p2p.New( "/ip4/127.0.0.1/tcp/30301", + "", "peerA", "", "5f6cdc3aebcc74af494df054876100368ef6126e3a33fa65b90c765b381ffc37a0a63bbeeefab0740f24a6a38dabb513b9233254ad0020c721c23e69bc820089",