Skip to content

Commit

Permalink
Node/P2P: Add default bootstrap peers (wormhole-foundation#3852)
Browse files Browse the repository at this point in the history
* Node/P2P: Add default bootstrap peers

* Rework

* Update ccqlistener
  • Loading branch information
bruce-riley authored Mar 22, 2024
1 parent 9634d59 commit d036e70
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 68 deletions.
2 changes: 2 additions & 0 deletions devnet/query-server.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ spec:
- http://eth-devnet:8545
- --ethContract
- "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550"
- --network
- /wormhole/dev
# Hardcoded devnet bootstrap (generated from deterministic key in guardiand)
- --bootstrap
- /dns4/guardian-0.guardian/udp/8996/quic/p2p/12D3KooWL3XJ9EMCyZvmmGXL2LMiVBtrVa2BuESsJiXkSj7333Jw
Expand Down
2 changes: 2 additions & 0 deletions devnet/spy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ spec:
- /tmp/node.key
- --spyRPC
- "[::]:7072"
- --network
- /wormhole/dev
# Hardcoded devnet bootstrap (generated from deterministic key in guardiand)
- --bootstrap
- /dns4/guardian-0.guardian/udp/8999/quic/p2p/12D3KooWL3XJ9EMCyZvmmGXL2LMiVBtrVa2BuESsJiXkSj7333Jw
Expand Down
39 changes: 17 additions & 22 deletions docs/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ If you use the same RPC node for Wormhole v1, you also need the following additi
`getProgramAccount` queries:

<!-- cspell:disable -->

```
[... see above for other required parameters ...]
--account-index program-id
--account-index-include-key WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC # for mainnet
--account-index-include-key 5gQf5AUhAgWYgUCt9ouShm9H7dzzXUsLdssYwe5krKhg # for testnet
```

<!-- cspell:enable -->

Alternatively, if you want to run a general-purpose RPC node with indexes for all programs instead of only Wormhole,
Expand All @@ -72,10 +74,12 @@ leave out the filtering:
On mainnet, we strongly recommend blacklisting KIN and the token program to speed up catchup:

<!-- cspell:disable -->

```
--account-index-exclude-key kinXdEcpDQeHPEuQnqmUgtYykqKGVFq6CeVX5iAHJq6 # Mainnet only
--account-index-exclude-key TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA # Mainnet only
```

<!-- cspell:enable -->

Note that these indexes require extra disk space and may slow down catchup. The first startup after
Expand Down Expand Up @@ -261,27 +265,12 @@ may include support for remote signing.

## Bootstrap Peers

The following bootstrap peers are available in each environment.

### Mainnet

<!-- cspell:disable -->
```bash
--bootstrap "/dns4/wormhole-v2-mainnet-bootstrap.xlabs.xyz/udp/8999/quic/p2p/12D3KooWNQ9tVrcb64tw6bNs2CaNrUGPM7yRrKvBBheQ5yCyPHKC,/dns4/wormhole.mcf.rocks/udp/8999/quic/p2p/12D3KooWDZVv7BhZ8yFLkarNdaSWaB43D6UbQwExJ8nnGAEmfHcU,/dns4/wormhole-v2-mainnet-bootstrap.staking.fund/udp/8999/quic/p2p/12D3KooWG8obDX9DNi1KUwZNu9xkGwfKqTp2GFwuuHpWZ3nQruS1"

--ccqP2pBootstrap "/dns4/wormhole-v2-mainnet-bootstrap.xlabs.xyz/udp/8996/quic/p2p/12D3KooWNQ9tVrcb64tw6bNs2CaNrUGPM7yRrKvBBheQ5yCyPHKC,/dns4/wormhole.mcf.rocks/udp/8996/quic/p2p/12D3KooWDZVv7BhZ8yFLkarNdaSWaB43D6UbQwExJ8nnGAEmfHcU,/dns4/wormhole-v2-mainnet-bootstrap.staking.fund/udp/8996/quic/p2p/12D3KooWG8obDX9DNi1KUwZNu9xkGwfKqTp2GFwuuHpWZ3nQruS1"
```
<!-- cspell:enable -->
The list of supported bootstrap peers is defined in `node/pkg/p2p/network_consts.go`. That file also provides golang functions
for obtaining the network parameters (network ID and bootstrap peers) based on the environment (mainnet or testnet).

### Testnet

<!-- cspell:disable -->
```bash
--bootstrap "/dns4/t-guardian-01.nodes.stable.io/udp/8999/quic/p2p/12D3KooWCW3LGUtkCVkHZmVSZHzL3C4WRKWfqAiJPz1NR7dT9Bxh,/dns4/t-guardian-02.nodes.stable.io/udp/8999/quic/p2p/12D3KooWJXA6goBCiWM8ucjzc4jVUBSqL9Rri6UpjHbkMPErz5zK,/dns4/p2p-guardian-testnet-1.solana.p2p.org/udp/8999/quic/p2p/12D3KooWE4dmZwxhfjCKHLUqSaww96Cf7kmq1ZuKmzPz3MrJgZxp"

--ccqP2pBootstrap "/dns4/t-guardian-01.nodes.stable.io/udp/8996/quic/p2p/12D3KooWCW3LGUtkCVkHZmVSZHzL3C4WRKWfqAiJPz1NR7dT9Bxh,/dns4/t-guardian-02.nodes.stable.io/udp/8996/quic/p2p/12D3KooWJXA6goBCiWM8ucjzc4jVUBSqL9Rri6UpjHbkMPErz5zK,/dns4/p2p-guardian-testnet-1.solana.p2p.org/udp/8996/quic/p2p/12D3KooWE4dmZwxhfjCKHLUqSaww96Cf7kmq1ZuKmzPz3MrJgZxp"
```
<!-- cspell:enable -->
The common Wormhole applications (guardiand, spy and query proxy server) use those functions, so it is not necessary to specify
the actual bootstrap parameters in their configs. Developers of any new applications are strongly urged to do the same, and not
proliferate lists of bootstrap peers which might change over time.

## Run the Guardian Spy

Expand All @@ -290,27 +279,31 @@ The spy connects to the wormhole guardian peer to peer network and listens for n
Start the spy against the testnet wormhole guardian:

<!-- cspell:disable -->

```bash
docker run \
--platform=linux/amd64 \
-p 7073:7073 \
--entrypoint /guardiand \
ghcr.io/wormhole-foundation/guardiand:latest \
spy --nodeKey /node.key --spyRPC "[::]:7073" --network /wormhole/testnet/2/1 --bootstrap "/dns4/t-guardian-01.nodes.stable.io/udp/8999/quic/p2p/12D3KooWCW3LGUtkCVkHZmVSZHzL3C4WRKWfqAiJPz1NR7dT9Bxh,/dns4/t-guardian-02.nodes.stable.io/udp/8999/quic/p2p/12D3KooWJXA6goBCiWM8ucjzc4jVUBSqL9Rri6UpjHbkMPErz5zK,/dns4/p2p-guardian-testnet-1.solana.p2p.org/udp/8999/quic/p2p/12D3KooWE4dmZwxhfjCKHLUqSaww96Cf7kmq1ZuKmzPz3MrJgZxp"
spy --nodeKey /node.key --spyRPC "[::]:7073" --env testnet
```

<!-- cspell:enable -->

To run the spy against mainnet:

<!-- cspell:disable -->

```bash
docker run \
--platform=linux/amd64 \
-p 7073:7073 \
--entrypoint /guardiand \
ghcr.io/wormhole-foundation/guardiand:latest \
spy --nodeKey /node.key --spyRPC "[::]:7073" --network /wormhole/mainnet/2 --bootstrap /dns4/wormhole-v2-mainnet-bootstrap.xlabs.xyz/udp/8999/quic/p2p/12D3KooWNQ9tVrcb64tw6bNs2CaNrUGPM7yRrKvBBheQ5yCyPHKC,/dns4/wormhole.mcf.rocks/udp/8999/quic/p2p/12D3KooWDZVv7BhZ8yFLkarNdaSWaB43D6UbQwExJ8nnGAEmfHcU,/dns4/wormhole-v2-mainnet-bootstrap.staking.fund/udp/8999/quic/p2p/12D3KooWG8obDX9DNi1KUwZNu9xkGwfKqTp2GFwuuHpWZ3nQruS1
spy --nodeKey /node.key --spyRPC "[::]:7073" --env mainnet
```

<!-- cspell:enable -->

## Guardian Configurations
Expand All @@ -326,12 +319,14 @@ Configuration files, environment variables and flags are all supported.
**Example**:

<!-- cspell:disable -->

```yaml
ethRPC: "ws://eth-devnet:8545"
ethContract: "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550"
solanaRPC: "http://solana-devnet:8899"
solanaContract: "Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o"
```
<!-- cspell:enable -->
### Environment Variables
Expand Down
49 changes: 33 additions & 16 deletions node/cmd/ccq/query_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"github.com/certusone/wormhole/node/pkg/common"
"github.com/certusone/wormhole/node/pkg/p2p"
"github.com/certusone/wormhole/node/pkg/telemetry"
promremotew "github.com/certusone/wormhole/node/pkg/telemetry/prom_remote_write"
"github.com/certusone/wormhole/node/pkg/version"
Expand Down Expand Up @@ -50,10 +51,10 @@ var (
const DEV_NETWORK_ID = "/wormhole/dev"

func init() {
envStr = QueryServerCmd.Flags().String("env", "", "environment (dev, test, prod)")
p2pNetworkID = QueryServerCmd.Flags().String("network", DEV_NETWORK_ID, "P2P network identifier")
envStr = QueryServerCmd.Flags().String("env", "", "environment (devnet, testnet, mainnet)")
p2pNetworkID = QueryServerCmd.Flags().String("network", "", "P2P network identifier (optional, overrides default for environment)")
p2pPort = QueryServerCmd.Flags().Uint("port", 8995, "P2P UDP listener port")
p2pBootstrap = QueryServerCmd.Flags().String("bootstrap", "", "P2P bootstrap peers (comma-separated)")
p2pBootstrap = QueryServerCmd.Flags().String("bootstrap", "", "P2P bootstrap peers (optional for testnet or mainnet, overrides default, required for devnet)")
nodeKeyPath = QueryServerCmd.Flags().String("nodeKey", "", "Path to node key (will be generated if it doesn't exist)")
signerKeyPath = QueryServerCmd.Flags().String("signerKey", "", "Path to key used to sign unsigned queries")
listenAddr = QueryServerCmd.Flags().String("listenAddr", "[::]:6069", "Listen address for query server (disabled if blank)")
Expand Down Expand Up @@ -82,7 +83,6 @@ var QueryServerCmd = &cobra.Command{

func runQueryServer(cmd *cobra.Command, args []string) {
common.SetRestrictiveUmask()
networkID := *p2pNetworkID + "/ccq"

// Setup logging
lvl, err := ipfslog.LevelFromString(*logLevel)
Expand All @@ -94,6 +94,35 @@ func runQueryServer(cmd *cobra.Command, args []string) {
logger := ipfslog.Logger("query-server").Desugar()
ipfslog.SetAllLoggers(lvl)

env, err := common.ParseEnvironment(*envStr)
if err != nil || (env != common.UnsafeDevNet && env != common.TestNet && env != common.MainNet) {
if *envStr == "" {
logger.Fatal("Please specify --env")
}
logger.Fatal("Invalid value for --env, should be devnet, testnet or mainnet", zap.String("val", *envStr))
}

if *p2pNetworkID == "" {
*p2pNetworkID = p2p.GetNetworkId(env)
} else if env != common.UnsafeDevNet {
logger.Warn("overriding default p2p network ID", zap.String("p2pNetworkID", *p2pNetworkID))
}

if *p2pNetworkID == DEV_NETWORK_ID && env != common.UnsafeDevNet {
logger.Fatal("May not set --network to dev unless --env is also dev", zap.String("network", *p2pNetworkID), zap.String("env", *envStr))
}

networkID := *p2pNetworkID + "/ccq"

if *p2pBootstrap == "" {
*p2pBootstrap, err = p2p.GetCcqBootstrapPeers(env)
if err != nil {
logger.Fatal("failed to determine the bootstrap peers from the environment", zap.String("env", string(env)), zap.Error(err))
}
} else if env != common.UnsafeDevNet {
logger.Warn("overriding default p2p bootstrap peers", zap.String("p2pBootstrap", *p2pBootstrap))
}

if *telemetryLokiURL != "" {
logger.Info("Using Loki telemetry logger")
if *telemetryNodeName == "" {
Expand All @@ -114,18 +143,6 @@ func runQueryServer(cmd *cobra.Command, args []string) {
logger = tm.WrapLogger(logger) // Wrap logger with telemetry logger
}

env, err := common.ParseEnvironment(*envStr)
if err != nil || (env != common.UnsafeDevNet && env != common.TestNet && env != common.MainNet) {
if *envStr == "" {
logger.Fatal("Please specify --env")
}
logger.Fatal("Invalid value for --env, must be dev, test or prod", zap.String("val", *envStr))
}

if *p2pNetworkID == DEV_NETWORK_ID && env != common.UnsafeDevNet {
logger.Fatal("May not set --network to dev unless --env is also dev", zap.String("network", *p2pNetworkID), zap.String("env", *envStr))
}

// Verify flags
if *nodeKeyPath == "" {
logger.Fatal("Please specify --nodeKey")
Expand Down
70 changes: 50 additions & 20 deletions node/cmd/guardiand/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,9 @@ var (
)

func init() {
p2pNetworkID = NodeCmd.Flags().String("network", "/wormhole/dev", "P2P network identifier")
p2pNetworkID = NodeCmd.Flags().String("network", "", "P2P network identifier (optional, overrides default for environment)")
p2pPort = NodeCmd.Flags().Uint("port", p2p.DefaultPort, "P2P UDP listener port")
p2pBootstrap = NodeCmd.Flags().String("bootstrap", "", "P2P bootstrap peers (comma-separated)")
p2pBootstrap = NodeCmd.Flags().String("bootstrap", "", "P2P bootstrap peers (optional for mainnet or testnet, overrides default, required for unsafeDevMode)")

statusAddr = NodeCmd.Flags().String("statusAddr", "[::]:6060", "Listen address for status server (disabled if blank)")

Expand Down Expand Up @@ -407,7 +407,7 @@ func init() {
ccqEnabled = NodeCmd.Flags().Bool("ccqEnabled", false, "Enable cross chain query support")
ccqAllowedRequesters = NodeCmd.Flags().String("ccqAllowedRequesters", "", "Comma separated list of signers allowed to submit cross chain queries")
ccqP2pPort = NodeCmd.Flags().Uint("ccqP2pPort", 8996, "CCQ P2P UDP listener port")
ccqP2pBootstrap = NodeCmd.Flags().String("ccqP2pBootstrap", "", "CCQ P2P bootstrap peers (comma-separated)")
ccqP2pBootstrap = NodeCmd.Flags().String("ccqP2pBootstrap", "", "CCQ P2P bootstrap peers (optional for mainnet or testnet, overrides default, required for unsafeDevMode)")
ccqAllowedPeers = NodeCmd.Flags().String("ccqAllowedPeers", "", "CCQ allowed P2P peers (comma-separated)")
ccqBackfillCache = NodeCmd.Flags().Bool("ccqBackfillCache", true, "Should EVM chains backfill CCQ timestamp cache on startup")

Expand Down Expand Up @@ -469,6 +469,16 @@ func runNode(cmd *cobra.Command, args []string) {
os.Exit(1)
}

// Determine execution mode
var env common.Environment
if *unsafeDevMode {
env = common.UnsafeDevNet
} else if *testnetMode {
env = common.TestNet
} else {
env = common.MainNet
}

if *unsafeDevMode {
fmt.Print(devwarning)
}
Expand Down Expand Up @@ -514,6 +524,10 @@ func runNode(cmd *cobra.Command, args []string) {
logger = logger.Named(*nodeName)
}

if *unsafeDevMode && *testnetMode {
logger.Fatal("Cannot be in unsafeDevMode and testnetMode at the same time.")
}

// Override the default go-log config, which uses a magic environment variable.
ipfslog.SetAllLoggers(lvl)

Expand All @@ -525,8 +539,15 @@ func runNode(cmd *cobra.Command, args []string) {
}

// Use the first guardian node as bootstrap
*p2pBootstrap = fmt.Sprintf("/dns4/guardian-0.guardian/udp/%d/quic/p2p/%s", *p2pPort, g0key.String())
*ccqP2pBootstrap = fmt.Sprintf("/dns4/guardian-0.guardian/udp/%d/quic/p2p/%s", *ccqP2pPort, g0key.String())
if *p2pBootstrap == "" {
*p2pBootstrap = fmt.Sprintf("/dns4/guardian-0.guardian/udp/%d/quic/p2p/%s", *p2pPort, g0key.String())
}
if *ccqP2pBootstrap == "" {
*ccqP2pBootstrap = fmt.Sprintf("/dns4/guardian-0.guardian/udp/%d/quic/p2p/%s", *ccqP2pPort, g0key.String())
}
if *p2pNetworkID == "" {
*p2pNetworkID = p2p.GetNetworkId(env)
}

// Deterministic ganache ETH devnet address.
*ethContract = unsafeDevModeEvmContractAddress(*ethContract)
Expand All @@ -552,6 +573,30 @@ func runNode(cmd *cobra.Command, args []string) {
*baseSepoliaContract = unsafeDevModeEvmContractAddress(*baseSepoliaContract)
*optimismSepoliaContract = unsafeDevModeEvmContractAddress(*optimismSepoliaContract)
*polygonSepoliaContract = unsafeDevModeEvmContractAddress(*polygonSepoliaContract)
} else { // Mainnet or Testnet.
// If the network parameters are not specified, use the defaults. Log a warning if they are specified since we want to discourage this.
// Note that we don't want to prevent it, to allow for network upgrade testing.
if *p2pNetworkID == "" {
*p2pNetworkID = p2p.GetNetworkId(env)
} else {
logger.Warn("overriding default p2p network ID", zap.String("p2pNetworkID", *p2pNetworkID))
}
if *p2pBootstrap == "" {
*p2pBootstrap, err = p2p.GetBootstrapPeers(env)
if err != nil {
logger.Fatal("failed to determine p2p bootstrap peers", zap.String("env", string(env)), zap.Error(err))
}
} else {
logger.Warn("overriding default p2p bootstrap peers", zap.String("p2pBootstrap", *p2pBootstrap))
}
if *ccqP2pBootstrap == "" {
*ccqP2pBootstrap, err = p2p.GetCcqBootstrapPeers(env)
if err != nil {
logger.Fatal("failed to determine ccq bootstrap peers", zap.String("env", string(env)), zap.Error(err))
}
} else {
logger.Warn("overriding default ccq bootstrap peers", zap.String("ccqP2pBootstrap", *ccqP2pBootstrap))
}
}

// Verify flags
Expand Down Expand Up @@ -831,21 +876,6 @@ func runNode(cmd *cobra.Command, args []string) {
}
}

// Determine execution mode
// TODO: refactor usage of these variables elsewhere. *unsafeDevMode and *testnetMode should not be accessed directly.
var env common.Environment
if *unsafeDevMode {
env = common.UnsafeDevNet
} else if *testnetMode {
env = common.TestNet
} else {
env = common.MainNet
}

if *unsafeDevMode && *testnetMode {
logger.Fatal("Cannot be in unsafeDevMode and testnetMode at the same time.")
}

// Complain about Infura on mainnet.
//
// As it turns out, Infura has a bug where it would sometimes incorrectly round
Expand Down
31 changes: 29 additions & 2 deletions node/cmd/spy/spy.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ var (
)

var (
envStr *string

p2pNetworkID *string
p2pPort *uint
p2pBootstrap *string
Expand All @@ -49,9 +51,10 @@ var (
)

func init() {
p2pNetworkID = SpyCmd.Flags().String("network", "/wormhole/dev", "P2P network identifier")
envStr = SpyCmd.Flags().String("env", "", `environment (may be "testnet" or "mainnet", required unless "--bootstrap" is specified)`)
p2pNetworkID = SpyCmd.Flags().String("network", "", "P2P network identifier (optional for testnet or mainnet, overrides default, required for devnet)")
p2pPort = SpyCmd.Flags().Uint("port", 8999, "P2P UDP listener port")
p2pBootstrap = SpyCmd.Flags().String("bootstrap", "", "P2P bootstrap peers (comma-separated)")
p2pBootstrap = SpyCmd.Flags().String("bootstrap", "", "P2P bootstrap peers (optional for testnet or mainnet, overrides default, required for devnet)")

statusAddr = SpyCmd.Flags().String("statusAddr", "[::]:6060", "Listen address for status server (disabled if blank)")

Expand Down Expand Up @@ -237,6 +240,30 @@ func runSpy(cmd *cobra.Command, args []string) {

ipfslog.SetAllLoggers(lvl)

if *envStr != "" {
// If they specify --env then use the defaults for the network parameters and don't allow them to override them.
if *p2pNetworkID != "" || *p2pBootstrap != "" {
logger.Fatal(`If "--env" is specified, "--network" and "--bootstrap" may not be specified`)
}
env, err := common.ParseEnvironment(*envStr)
if err != nil || (env != common.MainNet && env != common.TestNet) {
logger.Fatal(`Invalid value for "--env", should be "mainnet" or "testnet"`)
}
*p2pNetworkID = p2p.GetNetworkId(env)
*p2pBootstrap, err = p2p.GetBootstrapPeers(env)
if err != nil {
logger.Fatal("failed to determine p2p bootstrap peers", zap.String("env", string(env)), zap.Error(err))
}
} else {
// If they don't specify --env, then --network and --bootstrap are required.
if *p2pNetworkID == "" {
logger.Fatal(`If "--env" is not specified, "--network" must be specified`)
}
if *p2pBootstrap == "" {
logger.Fatal(`If "--env" is not specified, "--bootstrap" must be specified`)
}
}

// Status server
if *statusAddr != "" {
router := mux.NewRouter()
Expand Down
Loading

0 comments on commit d036e70

Please sign in to comment.