ソースを参照

node: optional chains in tilt

Evan Gray 3 年 前
コミット
59fd0d36c7
7 ファイル変更333 行追加243 行削除
  1. 9 7
      DEVELOP.md
  2. 146 81
      Tiltfile
  3. 1 68
      devnet/eth-devnet.yaml
  4. 69 0
      devnet/eth-devnet2.yaml
  5. 28 28
      devnet/node.yaml
  6. 2 1
      node/Dockerfile
  7. 78 58
      node/cmd/guardiand/node.go

+ 9 - 7
DEVELOP.md

@@ -7,7 +7,7 @@ The following dependencies are required for local development:
 - [Go](https://golang.org/dl/) >= 1.17.5
 - [Tilt](http://tilt.dev/) >= 0.20.8
 - Any of the local Kubernetes clusters supported by Tilt.
-  We strongly recommend [minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/) >= 
+  We strongly recommend [minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/) >=
   v1.21.0 with the kvm2 driver.
   - Tilt will use Minikube's embedded Docker server. If Minikube is not used, a local instance of
     [Docker](https://docs.docker.com/engine/install/) / moby-engine >= 19.03 is required.
@@ -33,12 +33,11 @@ to avoid having to specify `-n wormhole` for all commands:
 After installing all dependencies, just run `tilt up`.
 Whenever you modify a file, the devnet is automatically rebuilt and a rolling update is done.
 
-Launch the devnet while specifying the number of guardians nodes to run (default is five):
+Launch the devnet:
 
-    tilt up -- --num=1
+    tilt up
 
-If you want to work on non-consensus parts of the code, running with a single guardian is easiest since
-you won't have to wait for k8s to restart all pods.
+By default this runs a network consisting of one guardian, two ganache (Eth) chains, a Solana test validator, an Algorand sandbox, and LocalTerra for both Terra Classic and Terra 2. If you want to work on non-consensus parts of the code, running with a single guardian is easiest since you won't have to wait for k8s to restart all pods. See the usage guide below for arguments to customize the tilt network.
 
 ## Usage
 
@@ -59,6 +58,10 @@ of nodes diverges from the guardian set - otherwise, `tilt down --delete-namespa
 
     tilt args -- --num=2
 
+Run without all optional networks:
+
+    tilt up -- --algorand=false --evm2=false --solana=false --terra_classic=false --terra2=false
+
 Tear down cluster:
 
     tilt down --delete-namespaces
@@ -161,7 +164,6 @@ Set the include path:
 
 ![](https://i.imgur.com/bDij6Cu.png)
 
-
 ### BigTable event persistence
 
 Guardian events can be persisted to a cloud BigTable instance by passing a GCP project and service account key to Tilt.
@@ -194,4 +196,4 @@ Get yourself a working shell:
 
 Use the `--guardiand_debug` Tilt argument to run guardiand within a dlv session. The session will be exposed just like
 any other Tilt services. You can then connect any IDE that supports Go debugging, like IntelliJ (add a "Go Remote"
-target and specify the host and port your Tilt instance runs on). 
+target and specify the host and port your Tilt instance runs on).

+ 146 - 81
Tiltfile

@@ -39,7 +39,10 @@ config.define_string("webHost", False, "Public hostname for port forwards")
 
 # Components
 config.define_bool("algorand", False, "Enable Algorand component")
+config.define_bool("evm2", False, "Enable second Eth component")
 config.define_bool("solana", False, "Enable Solana component")
+config.define_bool("terra_classic", False, "Enable Terra Classic component")
+config.define_bool("terra2", False, "Enable Terra 2 component")
 config.define_bool("explorer", False, "Enable explorer component")
 config.define_bool("bridge_ui", False, "Enable bridge UI component")
 config.define_bool("spy_relayer", False, "Enable spy relayer")
@@ -55,7 +58,10 @@ gcpProject = cfg.get("gcpProject", "local-dev")
 bigTableKeyPath = cfg.get("bigTableKeyPath", "./event_database/devnet_key.json")
 webHost = cfg.get("webHost", "localhost")
 algorand = cfg.get("algorand", True)
+evm2 = cfg.get("evm2", True)
 solana = cfg.get("solana", True)
+terra_classic = cfg.get("terra_classic", True)
+terra2 = cfg.get("terra2", True)
 ci = cfg.get("ci", False)
 explorer = cfg.get("explorer", ci)
 bridge_ui = cfg.get("bridge_ui", ci)
@@ -188,13 +194,72 @@ def build_node_yaml():
                     gcpProject,
                 ]
 
+            if evm2:
+                container["command"] += [
+                    "--bscRPC",
+                    "ws://eth-devnet2:8545",
+                ]
+            else:
+                container["command"] += [
+                    "--bscRPC",
+                    "ws://eth-devnet:8545",
+                ]
+
+            if solana:
+                container["command"] += [
+                    "--solanaWS",
+                    "ws://solana-devnet:8900",
+                    "--solanaRPC",
+                    "http://solana-devnet:8899",
+                ]
+
+            if terra_classic:
+                container["command"] += [
+                    "--terraWS",
+                    "ws://terra-terrad:26657/websocket",
+                    "--terraLCD",
+                    "http://terra-terrad:1317",
+                    "--terraContract",
+                    "terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5",
+                ]
+
+            if terra2:
+                container["command"] += [
+                    "--terra2WS",
+                    "ws://terra2-terrad:26657/websocket",
+                    "--terra2LCD",
+                    "http://terra2-terrad:1317",
+                    "--terra2Contract",
+                    "terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au",
+                ]
+
+            if algorand:
+                container["command"] += [
+                    "--algorandAppID",
+                    "4",
+                    "--algorandIndexerRPC",
+                    "http://algorand:8980",
+                    "--algorandIndexerToken",
+                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+                    "--algorandAlgodRPC",
+                    "http://algorand:4001",
+                    "--algorandAlgodToken",
+                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+                ]
+
     return encode_yaml_stream(node_yaml)
 
 k8s_yaml_with_ns(build_node_yaml())
 
-guardian_resource_deps = ["proto-gen", "eth-devnet", "eth-devnet2", "terra-terrad", "terra2-terrad"]
+guardian_resource_deps = ["proto-gen", "eth-devnet"]
+if evm2:
+    guardian_resource_deps = guardian_resource_deps + ["eth-devnet2"]
 if solana:
     guardian_resource_deps = guardian_resource_deps + ["solana-devnet"]
+if terra_classic:
+    guardian_resource_deps = guardian_resource_deps + ["terra-terrad"]
+if terra2:
+    guardian_resource_deps = guardian_resource_deps + ["terra2-terrad"]
 
 k8s_resource(
     "guardian",
@@ -369,15 +434,18 @@ k8s_resource(
     trigger_mode = trigger_mode,
 )
 
-k8s_resource(
-    "eth-devnet2",
-    port_forwards = [
-        port_forward(8546, name = "Ganache RPC [:8546]", host = webHost),
-    ],
-    resource_deps = ["const-gen"],
-    labels = ["evm"],
-    trigger_mode = trigger_mode,
-)
+if evm2:
+    k8s_yaml_with_ns("devnet/eth-devnet2.yaml")
+
+    k8s_resource(
+        "eth-devnet2",
+        port_forwards = [
+            port_forward(8546, name = "Ganache RPC [:8546]", host = webHost),
+        ],
+        resource_deps = ["const-gen"],
+        labels = ["evm"],
+        trigger_mode = trigger_mode,
+    )
 
 if bridge_ui:
     entrypoint = "npm run build && /app/node_modules/.bin/serve -s build -n"
@@ -465,7 +533,6 @@ if e2e:
     )
 
 # bigtable
-
 if explorer:
     k8s_yaml_with_ns("devnet/bigtable.yaml")
 
@@ -498,87 +565,85 @@ if explorer:
         trigger_mode = trigger_mode,
     )
 
-# terra devnet
-
-docker_build(
-    ref = "terra-image",
-    context = "./terra/devnet",
-    dockerfile = "terra/devnet/Dockerfile",
-)
-
-docker_build(
-    ref = "terra-contracts",
-    context = "./terra",
-    dockerfile = "./terra/Dockerfile",
-)
+if terra_classic:
+    docker_build(
+        ref = "terra-image",
+        context = "./terra/devnet",
+        dockerfile = "terra/devnet/Dockerfile",
+    )
 
-k8s_yaml_with_ns("devnet/terra-devnet.yaml")
+    docker_build(
+        ref = "terra-contracts",
+        context = "./terra",
+        dockerfile = "./terra/Dockerfile",
+    )
 
-k8s_resource(
-    "terra-terrad",
-    port_forwards = [
-        port_forward(26657, name = "Terra RPC [:26657]", host = webHost),
-        port_forward(1317, name = "Terra LCD [:1317]", host = webHost),
-    ],
-    resource_deps = ["const-gen"],
-    labels = ["terra"],
-    trigger_mode = trigger_mode,
-)
+    k8s_yaml_with_ns("devnet/terra-devnet.yaml")
 
-k8s_resource(
-    "terra-postgres",
-    labels = ["terra"],
-    trigger_mode = trigger_mode,
-)
+    k8s_resource(
+        "terra-terrad",
+        port_forwards = [
+            port_forward(26657, name = "Terra RPC [:26657]", host = webHost),
+            port_forward(1317, name = "Terra LCD [:1317]", host = webHost),
+        ],
+        resource_deps = ["const-gen"],
+        labels = ["terra"],
+        trigger_mode = trigger_mode,
+    )
 
-k8s_resource(
-    "terra-fcd",
-    resource_deps = ["terra-terrad", "terra-postgres"],
-    port_forwards = [port_forward(3060, name = "Terra FCD [:3060]", host = webHost)],
-    labels = ["terra"],
-    trigger_mode = trigger_mode,
-)
+    k8s_resource(
+        "terra-postgres",
+        labels = ["terra"],
+        trigger_mode = trigger_mode,
+    )
 
-# terra 2 devnet
+    k8s_resource(
+        "terra-fcd",
+        resource_deps = ["terra-terrad", "terra-postgres"],
+        port_forwards = [port_forward(3060, name = "Terra FCD [:3060]", host = webHost)],
+        labels = ["terra"],
+        trigger_mode = trigger_mode,
+    )
 
-docker_build(
-    ref = "terra2-image",
-    context = "./cosmwasm/devnet",
-    dockerfile = "cosmwasm/devnet/Dockerfile",
-)
+if terra2:
+    docker_build(
+        ref = "terra2-image",
+        context = "./cosmwasm/devnet",
+        dockerfile = "cosmwasm/devnet/Dockerfile",
+    )
 
-docker_build(
-    ref = "terra2-contracts",
-    context = "./cosmwasm",
-    dockerfile = "./cosmwasm/Dockerfile",
-)
+    docker_build(
+        ref = "terra2-contracts",
+        context = "./cosmwasm",
+        dockerfile = "./cosmwasm/Dockerfile",
+    )
 
-k8s_yaml_with_ns("devnet/terra2-devnet.yaml")
+    k8s_yaml_with_ns("devnet/terra2-devnet.yaml")
 
-k8s_resource(
-    "terra2-terrad",
-    port_forwards = [
-        port_forward(26658, container_port = 26657, name = "Terra 2 RPC [:26658]", host = webHost),
-        port_forward(1318, container_port = 1317, name = "Terra 2 LCD [:1318]", host = webHost),
-    ],
-    resource_deps = ["const-gen"],
-    labels = ["terra2"],
-    trigger_mode = trigger_mode,
-)
+    k8s_resource(
+        "terra2-terrad",
+        port_forwards = [
+            port_forward(26658, container_port = 26657, name = "Terra 2 RPC [:26658]", host = webHost),
+            port_forward(1318, container_port = 1317, name = "Terra 2 LCD [:1318]", host = webHost),
+        ],
+        resource_deps = ["const-gen"],
+        labels = ["terra2"],
+        trigger_mode = trigger_mode,
+    )
 
-k8s_resource(
-    "terra2-postgres",
-    labels = ["terra2"],
-    trigger_mode = trigger_mode,
-)
+    k8s_resource(
+        "terra2-postgres",
+        labels = ["terra2"],
+        trigger_mode = trigger_mode,
+    )
 
-k8s_resource(
-    "terra2-fcd",
-    resource_deps = ["terra2-terrad", "terra2-postgres"],
-    port_forwards = [port_forward(3061, container_port = 3060, name = "Terra 2 FCD [:3061]", host = webHost)],
-    labels = ["terra2"],
-    trigger_mode = trigger_mode,
-)
+    k8s_resource(
+        "terra2-fcd",
+        resource_deps = ["terra2-terrad", "terra2-postgres"],
+        port_forwards = [port_forward(3061, container_port = 3060, name = "Terra 2 FCD [:3061]", host = webHost)],
+        labels = ["terra2"],
+        trigger_mode = trigger_mode,
+    )
 
 if algorand:
     k8s_yaml_with_ns("devnet/algorand-devnet.yaml")

+ 1 - 68
devnet/eth-devnet.yaml

@@ -14,22 +14,6 @@ spec:
   selector:
     app: eth-devnet
 ---
-apiVersion: v1
-kind: Service
-metadata:
-  name: eth-devnet2
-  labels:
-    app: eth-devnet2
-spec:
-  ports:
-    - port: 8546
-      targetPort: 8545
-      name: rpc
-      protocol: TCP
-  clusterIP: None
-  selector:
-    app: eth-devnet2
----
 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
@@ -82,55 +66,4 @@ spec:
             - -c
             - "npx truffle exec mine.js"
 ---
-apiVersion: apps/v1
-kind: StatefulSet
-metadata:
-  name: eth-devnet2
-spec:
-  selector:
-    matchLabels:
-      app: eth-devnet2
-  serviceName: eth-devnet2
-  replicas: 1
-  template:
-    metadata:
-      labels:
-        app: eth-devnet2
-    spec:
-      terminationGracePeriodSeconds: 1
-      containers:
-        - name: ganache
-          image: eth-node
-          command:
-            - npx
-            - ganache-cli
-            - -e 10000
-            - --deterministic
-            - --time="1970-01-01T00:00:00+00:00"
-            - --host=0.0.0.0
-            - --chainId=1397
-          ports:
-            - containerPort: 8545
-              name: rpc
-              protocol: TCP
-          readinessProbe:
-            tcpSocket:
-              port: rpc
-        - name: tests
-          image: eth-node
-          stdin: true
-          command:
-            - /bin/sh
-            - -c
-            - "sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g' .env && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_solana_chain.js && npx truffle exec scripts/register_terra_chain.js && npx truffle exec scripts/register_terra2_chain.js && npx truffle exec scripts/register_eth_chain.js && npx truffle exec scripts/register_algo_chain.js && nc -lkp 2000 0.0.0.0"
-          readinessProbe:
-            periodSeconds: 1
-            failureThreshold: 300
-            tcpSocket:
-              port: 2000
-        - name: mine
-          image: eth-node
-          command:
-            - /bin/sh
-            - -c
-            - "npx truffle exec mine.js"
+

+ 69 - 0
devnet/eth-devnet2.yaml

@@ -0,0 +1,69 @@
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: eth-devnet2
+  labels:
+    app: eth-devnet2
+spec:
+  ports:
+    - port: 8546
+      targetPort: 8545
+      name: rpc
+      protocol: TCP
+  clusterIP: None
+  selector:
+    app: eth-devnet2
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: eth-devnet2
+spec:
+  selector:
+    matchLabels:
+      app: eth-devnet2
+  serviceName: eth-devnet2
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: eth-devnet2
+    spec:
+      terminationGracePeriodSeconds: 1
+      containers:
+        - name: ganache
+          image: eth-node
+          command:
+            - npx
+            - ganache-cli
+            - -e 10000
+            - --deterministic
+            - --time="1970-01-01T00:00:00+00:00"
+            - --host=0.0.0.0
+            - --chainId=1397
+          ports:
+            - containerPort: 8545
+              name: rpc
+              protocol: TCP
+          readinessProbe:
+            tcpSocket:
+              port: rpc
+        - name: tests
+          image: eth-node
+          stdin: true
+          command:
+            - /bin/sh
+            - -c
+            - "sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g' .env && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_solana_chain.js && npx truffle exec scripts/register_terra_chain.js && npx truffle exec scripts/register_terra2_chain.js && npx truffle exec scripts/register_eth_chain.js && npx truffle exec scripts/register_algo_chain.js && nc -lkp 2000 0.0.0.0"
+          readinessProbe:
+            periodSeconds: 1
+            failureThreshold: 300
+            tcpSocket:
+              port: 2000
+        - name: mine
+          image: eth-node
+          command:
+            - /bin/sh
+            - -c
+            - "npx truffle exec mine.js"

+ 28 - 28
devnet/node.yaml

@@ -69,8 +69,8 @@ spec:
             - node
             - --ethRPC
             - ws://eth-devnet:8545
-            - --bscRPC
-            - ws://eth-devnet2:8545
+            # - --bscRPC
+            # - ws://eth-devnet2:8545
             - --polygonRPC
             - ws://eth-devnet:8545
             - --avalancheRPC
@@ -93,34 +93,34 @@ spec:
             - ws://eth-devnet:8545
             - --neonRPC
             - ws://eth-devnet:8545
-            - --terraWS
-            - ws://terra-terrad:26657/websocket
-            - --terraLCD
-            - http://terra-terrad:1317
-            - --terraContract
-            - terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5
-            - --terra2WS
-            - ws://terra2-terrad:26657/websocket
-            - --terra2LCD
-            - http://terra2-terrad:1317
-            - --terra2Contract
-            - terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au
-            - --algorandAppID
-            - "4"
-            - --algorandIndexerRPC
-            - http://algorand:8980
-            - --algorandIndexerToken
-            - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-            - --algorandAlgodRPC
-            - http://algorand:4001
-            - --algorandAlgodToken
-            - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+            # - --terraWS
+            # - ws://terra-terrad:26657/websocket
+            # - --terraLCD
+            # - http://terra-terrad:1317
+            # - --terraContract
+            # - terra18vd8fpwxzck93qlwghaj6arh4p7c5n896xzem5
+            # - --terra2WS
+            # - ws://terra2-terrad:26657/websocket
+            # - --terra2LCD
+            # - http://terra2-terrad:1317
+            # - --terra2Contract
+            # - terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au
+            # - --algorandAppID
+            # - "4"
+            # - --algorandIndexerRPC
+            # - http://algorand:8980
+            # - --algorandIndexerToken
+            # - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+            # - --algorandAlgodRPC
+            # - http://algorand:4001
+            # - --algorandAlgodToken
+            # - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
             - --solanaContract
             - Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o
-            - --solanaWS
-            - ws://solana-devnet:8900
-            - --solanaRPC
-            - http://solana-devnet:8899
+            # - --solanaWS
+            # - ws://solana-devnet:8900
+            # - --solanaRPC
+            # - http://solana-devnet:8899
             - --unsafeDevMode
             - --guardianKey
             - /tmp/bridge.key

+ 2 - 1
node/Dockerfile

@@ -1,5 +1,6 @@
 # syntax=docker.io/docker/dockerfile:1.3@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2
-FROM docker.io/golang:1.17.5@sha256:90d1ab81f3d157ca649a9ff8d251691b810d95ea6023a03cdca139df58bca599 AS build
+FROM --platform=linux/amd64 docker.io/golang:1.17.5@sha256:90d1ab81f3d157ca649a9ff8d251691b810d95ea6023a03cdca139df58bca599 AS build
+# libwasmvm.so is not compatible with arm
 
 # Support additional root CAs
 COPY go.mod cert.pem* /certs/

+ 78 - 58
node/cmd/guardiand/node.go

@@ -350,10 +350,16 @@ func runNode(cmd *cobra.Command, args []string) {
 
 	// Register components for readiness checks.
 	readiness.RegisterComponent(common.ReadinessEthSyncing)
-	readiness.RegisterComponent(common.ReadinessSolanaSyncing)
-	readiness.RegisterComponent(common.ReadinessTerraSyncing)
-	readiness.RegisterComponent(common.ReadinessTerra2Syncing)
-	if *testnetMode || *unsafeDevMode {
+	if *solanaWsRPC != "" {
+		readiness.RegisterComponent(common.ReadinessSolanaSyncing)
+	}
+	if *terraWS != "" {
+		readiness.RegisterComponent(common.ReadinessTerraSyncing)
+	}
+	if *terra2WS != "" {
+		readiness.RegisterComponent(common.ReadinessTerra2Syncing)
+	}
+	if *algorandIndexerRPC != "" {
 		readiness.RegisterComponent(common.ReadinessAlgorandSyncing)
 	}
 	readiness.RegisterComponent(common.ReadinessBSCSyncing)
@@ -561,51 +567,59 @@ func runNode(cmd *cobra.Command, args []string) {
 		logger.Fatal("Please specify --nodeName")
 	}
 
-	if *solanaContract == "" {
-		logger.Fatal("Please specify --solanaContract")
-	}
-	if *solanaWsRPC == "" {
-		logger.Fatal("Please specify --solanaWsUrl")
-	}
-	if *solanaRPC == "" {
-		logger.Fatal("Please specify --solanaUrl")
-	}
+	// Solana, Terra Classic, Terra 2, and Algorand are optional in devnet
+	if !*unsafeDevMode {
 
-	if *terraWS == "" {
-		logger.Fatal("Please specify --terraWS")
-	}
-	if *terraLCD == "" {
-		logger.Fatal("Please specify --terraLCD")
-	}
-	if *terraContract == "" {
-		logger.Fatal("Please specify --terraContract")
-	}
-	if *terra2WS == "" {
-		logger.Fatal("Please specify --terra2WS")
-	}
-	if *terra2LCD == "" {
-		logger.Fatal("Please specify --terra2LCD")
-	}
-	if *terra2Contract == "" {
-		logger.Fatal("Please specify --terra2Contract")
-	}
-	if *testnetMode || *unsafeDevMode {
-		if *algorandIndexerRPC == "" {
-			logger.Fatal("Please specify --algorandIndexerRPC")
+		if *solanaContract == "" {
+			logger.Fatal("Please specify --solanaContract")
 		}
-		if *algorandIndexerToken == "" {
-			logger.Fatal("Please specify --algorandIndexerToken")
+		if *solanaWsRPC == "" {
+			logger.Fatal("Please specify --solanaWsUrl")
 		}
-		if *algorandAlgodRPC == "" {
-			logger.Fatal("Please specify --algorandAlgodRPC")
+		if *solanaRPC == "" {
+			logger.Fatal("Please specify --solanaUrl")
 		}
-		if *algorandAlgodToken == "" {
-			logger.Fatal("Please specify --algorandAlgodToken")
+
+		if *terraWS == "" {
+			logger.Fatal("Please specify --terraWS")
+		}
+		if *terraLCD == "" {
+			logger.Fatal("Please specify --terraLCD")
 		}
-		if *algorandAppID == 0 {
-			logger.Fatal("Please specify --algorandAppID")
+		if *terraContract == "" {
+			logger.Fatal("Please specify --terraContract")
 		}
+
+		if *terra2WS == "" {
+			logger.Fatal("Please specify --terra2WS")
+		}
+		if *terra2LCD == "" {
+			logger.Fatal("Please specify --terra2LCD")
+		}
+		if *terra2Contract == "" {
+			logger.Fatal("Please specify --terra2Contract")
+		}
+
+		if *testnetMode {
+			if *algorandIndexerRPC == "" {
+				logger.Fatal("Please specify --algorandIndexerRPC")
+			}
+			if *algorandIndexerToken == "" {
+				logger.Fatal("Please specify --algorandIndexerToken")
+			}
+			if *algorandAlgodRPC == "" {
+				logger.Fatal("Please specify --algorandAlgodRPC")
+			}
+			if *algorandAlgodToken == "" {
+				logger.Fatal("Please specify --algorandAlgodToken")
+			}
+			if *algorandAppID == 0 {
+				logger.Fatal("Please specify --algorandAppID")
+			}
+		}
+
 	}
+
 	if *bigTablePersistenceEnabled {
 		if *bigTableGCPProject == "" {
 			logger.Fatal("Please specify --bigTableGCPProject")
@@ -941,16 +955,20 @@ func runNode(cmd *cobra.Command, args []string) {
 			}
 		}
 
-		logger.Info("Starting Terra watcher")
-		if err := supervisor.Run(ctx, "terrawatch",
-			cosmwasm.NewWatcher(*terraWS, *terraLCD, *terraContract, lockC, setC, chainObsvReqC[vaa.ChainIDTerra], common.ReadinessTerraSyncing, vaa.ChainIDTerra).Run); err != nil {
-			return err
+		if *terraWS != "" {
+			logger.Info("Starting Terra watcher")
+			if err := supervisor.Run(ctx, "terrawatch",
+				cosmwasm.NewWatcher(*terraWS, *terraLCD, *terraContract, lockC, setC, chainObsvReqC[vaa.ChainIDTerra], common.ReadinessTerraSyncing, vaa.ChainIDTerra).Run); err != nil {
+				return err
+			}
 		}
 
-		logger.Info("Starting Terra 2 watcher")
-		if err := supervisor.Run(ctx, "terra2watch",
-			cosmwasm.NewWatcher(*terra2WS, *terra2LCD, *terra2Contract, lockC, setC, chainObsvReqC[vaa.ChainIDTerra2], common.ReadinessTerra2Syncing, vaa.ChainIDTerra2).Run); err != nil {
-			return err
+		if *terra2WS != "" {
+			logger.Info("Starting Terra 2 watcher")
+			if err := supervisor.Run(ctx, "terra2watch",
+				cosmwasm.NewWatcher(*terra2WS, *terra2LCD, *terra2Contract, lockC, setC, chainObsvReqC[vaa.ChainIDTerra2], common.ReadinessTerra2Syncing, vaa.ChainIDTerra2).Run); err != nil {
+				return err
+			}
 		}
 
 		if *testnetMode {
@@ -961,21 +979,23 @@ func runNode(cmd *cobra.Command, args []string) {
 			}
 		}
 
-		if *testnetMode || *unsafeDevMode {
+		if *algorandIndexerRPC != "" {
 			if err := supervisor.Run(ctx, "algorandwatch",
 				algorand.NewWatcher(*algorandIndexerRPC, *algorandIndexerToken, *algorandAlgodRPC, *algorandAlgodToken, *algorandAppID, lockC, setC, chainObsvReqC[vaa.ChainIDAlgorand]).Run); err != nil {
 				return err
 			}
 		}
 
-		if err := supervisor.Run(ctx, "solwatch-confirmed",
-			solana.NewSolanaWatcher(*solanaWsRPC, *solanaRPC, solAddress, lockC, nil, rpc.CommitmentConfirmed).Run); err != nil {
-			return err
-		}
+		if *solanaWsRPC != "" {
+			if err := supervisor.Run(ctx, "solwatch-confirmed",
+				solana.NewSolanaWatcher(*solanaWsRPC, *solanaRPC, solAddress, lockC, nil, rpc.CommitmentConfirmed).Run); err != nil {
+				return err
+			}
 
-		if err := supervisor.Run(ctx, "solwatch-finalized",
-			solana.NewSolanaWatcher(*solanaWsRPC, *solanaRPC, solAddress, lockC, chainObsvReqC[vaa.ChainIDSolana], rpc.CommitmentFinalized).Run); err != nil {
-			return err
+			if err := supervisor.Run(ctx, "solwatch-finalized",
+				solana.NewSolanaWatcher(*solanaWsRPC, *solanaRPC, solAddress, lockC, chainObsvReqC[vaa.ChainIDSolana], rpc.CommitmentFinalized).Run); err != nil {
+				return err
+			}
 		}
 
 		p := processor.NewProcessor(ctx,