瀏覽代碼

*: add ropsten chainID and guardiand implementation

Change-Id: Ib99316c28237d946eb2b6d013f4e275a620d4aa8
Leo 4 年之前
父節點
當前提交
8800d7bfd3

+ 97 - 41
node/cmd/guardiand/adminnodes.go

@@ -64,10 +64,19 @@ func runListNodes(cmd *cobra.Command, args []string) {
 
 	w := tabwriter.NewWriter(os.Stdout, 0, 8, 2, ' ', 0)
 
-	if showDetails {
-		_, _ = w.Write([]byte("Node key\tGuardian key\tNode name\tVersion\tLast seen\tUptime\tSolana\tEthereum\tTerra\tBSC\tPolygon\n"))
+	if *testnetMode {
+		// Include Ropsten in testnet mode
+		if showDetails {
+			_, _ = w.Write([]byte("Node key\tGuardian key\tNode name\tVersion\tLast seen\tUptime\tSolana\tEthereum\tTerra\tBSC\tPolygon\tRopsten\n"))
+		} else {
+			_, _ = w.Write([]byte("Node key\tGuardian key\tNode name\tVersion\tLast seen\tSolana\tEthereum\tTerra\tBSC\tPolygon\tRopsten\n"))
+		}
 	} else {
-		_, _ = w.Write([]byte("Node key\tGuardian key\tNode name\tVersion\tLast seen\tSolana\tEthereum\tTerra\tBSC\tPolygon\n"))
+		if showDetails {
+			_, _ = w.Write([]byte("Node key\tGuardian key\tNode name\tVersion\tLast seen\tUptime\tSolana\tEthereum\tTerra\tBSC\tPolygon\n"))
+		} else {
+			_, _ = w.Write([]byte("Node key\tGuardian key\tNode name\tVersion\tLast seen\tSolana\tEthereum\tTerra\tBSC\tPolygon\n"))
+		}
 	}
 
 	for _, h := range nodes {
@@ -91,45 +100,92 @@ func runListNodes(cmd *cobra.Command, args []string) {
 			}
 		}
 
-		if showDetails {
-			fmt.Fprintf(w,
-				"%s\t%s\t%s\t%s\t%s\t%s\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\n",
-				h.P2PNodeAddr,
-				h.RawHeartbeat.GuardianAddr,
-				h.RawHeartbeat.NodeName,
-				h.RawHeartbeat.Version,
-				time.Since(last),
-				time.Since(boot),
-				truncAddrs[vaa.ChainIDSolana],
-				heights[vaa.ChainIDSolana],
-				errors[vaa.ChainIDSolana],
-				truncAddrs[vaa.ChainIDEthereum],
-				heights[vaa.ChainIDEthereum],
-				errors[vaa.ChainIDEthereum],
-				truncAddrs[vaa.ChainIDTerra],
-				heights[vaa.ChainIDTerra],
-				errors[vaa.ChainIDTerra],
-				truncAddrs[vaa.ChainIDBSC],
-				heights[vaa.ChainIDBSC],
-				errors[vaa.ChainIDBSC],
-				truncAddrs[vaa.ChainIDPolygon],
-				heights[vaa.ChainIDPolygon],
-				errors[vaa.ChainIDPolygon],
-			)
+		if *testnetMode {
+			if showDetails {
+				fmt.Fprintf(w,
+					"%s\t%s\t%s\t%s\t%s\t%s\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\n",
+					h.P2PNodeAddr,
+					h.RawHeartbeat.GuardianAddr,
+					h.RawHeartbeat.NodeName,
+					h.RawHeartbeat.Version,
+					time.Since(last),
+					time.Since(boot),
+					truncAddrs[vaa.ChainIDSolana],
+					heights[vaa.ChainIDSolana],
+					errors[vaa.ChainIDSolana],
+					truncAddrs[vaa.ChainIDEthereum],
+					heights[vaa.ChainIDEthereum],
+					errors[vaa.ChainIDEthereum],
+					truncAddrs[vaa.ChainIDTerra],
+					heights[vaa.ChainIDTerra],
+					errors[vaa.ChainIDTerra],
+					truncAddrs[vaa.ChainIDBSC],
+					heights[vaa.ChainIDBSC],
+					errors[vaa.ChainIDBSC],
+					truncAddrs[vaa.ChainIDPolygon],
+					heights[vaa.ChainIDPolygon],
+					errors[vaa.ChainIDPolygon],
+					truncAddrs[vaa.ChainIDEthereumRopsten],
+					heights[vaa.ChainIDEthereumRopsten],
+					errors[vaa.ChainIDEthereumRopsten],
+				)
+			} else {
+				fmt.Fprintf(w,
+					"%s\t%s\t%s\t%s\t%s\t%d\t%d\t%d\t%d\t%d\t%d\n",
+					h.P2PNodeAddr,
+					h.RawHeartbeat.GuardianAddr,
+					h.RawHeartbeat.NodeName,
+					h.RawHeartbeat.Version,
+					time.Since(last),
+					heights[vaa.ChainIDSolana],
+					heights[vaa.ChainIDEthereum],
+					heights[vaa.ChainIDTerra],
+					heights[vaa.ChainIDBSC],
+					heights[vaa.ChainIDPolygon],
+					heights[vaa.ChainIDEthereumRopsten],
+				)
+			}
 		} else {
-			fmt.Fprintf(w,
-				"%s\t%s\t%s\t%s\t%s\t%d\t%d\t%d\t%d\t%d\n",
-				h.P2PNodeAddr,
-				h.RawHeartbeat.GuardianAddr,
-				h.RawHeartbeat.NodeName,
-				h.RawHeartbeat.Version,
-				time.Since(last),
-				heights[vaa.ChainIDSolana],
-				heights[vaa.ChainIDEthereum],
-				heights[vaa.ChainIDTerra],
-				heights[vaa.ChainIDBSC],
-				heights[vaa.ChainIDPolygon],
-			)
+			if showDetails {
+				fmt.Fprintf(w,
+					"%s\t%s\t%s\t%s\t%s\t%s\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\t%s %d (%d)\n",
+					h.P2PNodeAddr,
+					h.RawHeartbeat.GuardianAddr,
+					h.RawHeartbeat.NodeName,
+					h.RawHeartbeat.Version,
+					time.Since(last),
+					time.Since(boot),
+					truncAddrs[vaa.ChainIDSolana],
+					heights[vaa.ChainIDSolana],
+					errors[vaa.ChainIDSolana],
+					truncAddrs[vaa.ChainIDEthereum],
+					heights[vaa.ChainIDEthereum],
+					errors[vaa.ChainIDEthereum],
+					truncAddrs[vaa.ChainIDTerra],
+					heights[vaa.ChainIDTerra],
+					errors[vaa.ChainIDTerra],
+					truncAddrs[vaa.ChainIDBSC],
+					heights[vaa.ChainIDBSC],
+					errors[vaa.ChainIDBSC],
+					truncAddrs[vaa.ChainIDPolygon],
+					heights[vaa.ChainIDPolygon],
+					errors[vaa.ChainIDPolygon],
+				)
+			} else {
+				fmt.Fprintf(w,
+					"%s\t%s\t%s\t%s\t%s\t%d\t%d\t%d\t%d\t%d\n",
+					h.P2PNodeAddr,
+					h.RawHeartbeat.GuardianAddr,
+					h.RawHeartbeat.NodeName,
+					h.RawHeartbeat.Version,
+					time.Since(last),
+					heights[vaa.ChainIDSolana],
+					heights[vaa.ChainIDEthereum],
+					heights[vaa.ChainIDTerra],
+					heights[vaa.ChainIDBSC],
+					heights[vaa.ChainIDPolygon],
+				)
+			}
 		}
 	}
 

+ 34 - 0
node/cmd/guardiand/node.go

@@ -69,6 +69,9 @@ var (
 	polygonRPC      *string
 	polygonContract *string
 
+	ethRopstenRPC      *string
+	ethRopstenContract *string
+
 	terraWS       *string
 	terraLCD      *string
 	terraContract *string
@@ -79,6 +82,7 @@ var (
 	logLevel *string
 
 	unsafeDevMode   *bool
+	testnetMode     *bool
 	devNumGuardians *uint
 	nodeName        *string
 
@@ -125,6 +129,9 @@ func init() {
 	polygonRPC = NodeCmd.Flags().String("polygonRPC", "", "Polygon RPC URL")
 	polygonContract = NodeCmd.Flags().String("polygonContract", "", "Polygon contract address")
 
+	ethRopstenRPC = NodeCmd.Flags().String("ethRopstenRPC", "", "Ethereum Ropsten RPC URL")
+	ethRopstenContract = NodeCmd.Flags().String("ethRopstenContract", "", "Ethereum Ropsten contract address")
+
 	terraWS = NodeCmd.Flags().String("terraWS", "", "Path to terrad root for websocket connection")
 	terraLCD = NodeCmd.Flags().String("terraLCD", "", "Path to LCD service root for http calls")
 	terraContract = NodeCmd.Flags().String("terraContract", "", "Wormhole contract address on Terra blockchain")
@@ -135,6 +142,7 @@ func init() {
 	logLevel = NodeCmd.Flags().String("logLevel", "info", "Logging level (debug, info, warn, error, dpanic, panic, fatal)")
 
 	unsafeDevMode = NodeCmd.Flags().Bool("unsafeDevMode", false, "Launch node in unsafe, deterministic devnet mode")
+	testnetMode = NodeCmd.Flags().Bool("testnetMode", false, "Launch node in testnet mode (enables testnet-only features like Ropsten)")
 	devNumGuardians = NodeCmd.Flags().Uint("devNumGuardians", 5, "Number of devnet guardians to include in guardian set")
 	nodeName = NodeCmd.Flags().String("nodeName", "", "Node name to announce in gossip heartbeats")
 
@@ -249,6 +257,9 @@ func runNode(cmd *cobra.Command, args []string) {
 	readiness.RegisterComponent(common.ReadinessTerraSyncing)
 	readiness.RegisterComponent(common.ReadinessBSCSyncing)
 	readiness.RegisterComponent(common.ReadinessPolygonSyncing)
+	if *testnetMode {
+		readiness.RegisterComponent(common.ReadinessEthRopstenSyncing)
+	}
 
 	if *statusAddr != "" {
 		// Use a custom routing instead of using http.DefaultServeMux directly to avoid accidentally exposing packages
@@ -331,6 +342,21 @@ func runNode(cmd *cobra.Command, args []string) {
 	if *polygonContract == "" {
 		logger.Fatal("Please specify --polygonContract")
 	}
+	if *testnetMode {
+		if *ethRopstenRPC == "" {
+			logger.Fatal("Please specify --ethRopstenRPC")
+		}
+		if *ethRopstenContract == "" {
+			logger.Fatal("Please specify --ethRopstenContract")
+		}
+	} else {
+		if *ethRopstenRPC != "" {
+			logger.Fatal("Please do not specify --ethRopstenRPC in non-testnet mode")
+		}
+		if *ethRopstenContract != "" {
+			logger.Fatal("Please do not specify --ethRopstenContract in non-testnet mode")
+		}
+	}
 	if *nodeName == "" {
 		logger.Fatal("Please specify --nodeName")
 	}
@@ -396,6 +422,7 @@ func runNode(cmd *cobra.Command, args []string) {
 	ethContractAddr := eth_common.HexToAddress(*ethContract)
 	bscContractAddr := eth_common.HexToAddress(*bscContract)
 	polygonContractAddr := eth_common.HexToAddress(*polygonContract)
+	ethRopstenContractAddr := eth_common.HexToAddress(*ethRopstenContract)
 	solAddress, err := solana_types.PublicKeyFromBase58(*solanaContract)
 	if err != nil {
 		logger.Fatal("invalid Solana contract address", zap.Error(err))
@@ -528,6 +555,13 @@ func runNode(cmd *cobra.Command, args []string) {
 			return err
 		}
 
+		if *testnetMode {
+			if err := supervisor.Run(ctx, "ethropstenwatch",
+				ethereum.NewEthWatcher(*ethRopstenRPC, ethRopstenContractAddr, "ethropsten", common.ReadinessEthRopstenSyncing, vaa.ChainIDEthereumRopsten, lockC, setC).Run); err != nil {
+				return err
+			}
+		}
+
 		// Start Terra watcher only if configured
 		logger.Info("Starting Terra watcher")
 		if err := supervisor.Run(ctx, "terrawatch",

+ 6 - 5
node/pkg/common/readiness.go

@@ -3,9 +3,10 @@ package common
 import "github.com/certusone/wormhole/node/pkg/readiness"
 
 const (
-	ReadinessEthSyncing     readiness.Component = "ethSyncing"
-	ReadinessSolanaSyncing  readiness.Component = "solanaSyncing"
-	ReadinessTerraSyncing   readiness.Component = "terraSyncing"
-	ReadinessBSCSyncing     readiness.Component = "bscSyncing"
-	ReadinessPolygonSyncing readiness.Component = "polygonSyncing"
+	ReadinessEthSyncing        readiness.Component = "ethSyncing"
+	ReadinessSolanaSyncing     readiness.Component = "solanaSyncing"
+	ReadinessTerraSyncing      readiness.Component = "terraSyncing"
+	ReadinessBSCSyncing        readiness.Component = "bscSyncing"
+	ReadinessPolygonSyncing    readiness.Component = "polygonSyncing"
+	ReadinessEthRopstenSyncing readiness.Component = "ethRopstenSyncing"
 )

+ 6 - 0
node/pkg/vaa/structs.go

@@ -94,6 +94,8 @@ func (c ChainID) String() string {
 		return "bsc"
 	case ChainIDPolygon:
 		return "polygon"
+	case ChainIDEthereumRopsten:
+		return "ethereum-ropsten"
 	default:
 		return fmt.Sprintf("unknown chain ID: %d", c)
 	}
@@ -113,6 +115,8 @@ func ChainIDFromString(s string) (ChainID, error) {
 		return ChainIDBSC, nil
 	case "polygon":
 		return ChainIDPolygon, nil
+	case "ethereum-ropsten":
+		return ChainIDEthereumRopsten, nil
 	default:
 		return ChainIDUnset, fmt.Errorf("unknown chain ID: %s", s)
 	}
@@ -130,6 +134,8 @@ const (
 	ChainIDBSC ChainID = 4
 	// ChainIDPolygon is the ChainID of Polygon
 	ChainIDPolygon ChainID = 5
+	// ChainIDEthereumRopsten is the ChainID of Ethereum Ropsten
+	ChainIDEthereumRopsten ChainID = 10001
 
 	minVAALength        = 1 + 4 + 52 + 4 + 1 + 1
 	SupportedVAAVersion = 0x01

+ 3 - 0
proto/publicrpc/v1/publicrpc.proto

@@ -14,6 +14,9 @@ enum ChainID {
   CHAIN_ID_TERRA = 3;
   CHAIN_ID_BSC = 4;
   CHAIN_ID_POLYGON = 5;
+  // Special case - Eth has two testnets. CHAIN_ID_ETHEREUM is Goerli,
+  // but we also want to connect to Ropsten, so we add a separate chain.
+  CHAIN_ID_ETHEREUM_ROPSTEN = 10001;
 }
 
 // MessageID is a VAA's globally unique identifier (see data availability design document).

+ 3 - 1
sdk/js/src/utils/array.ts

@@ -5,6 +5,7 @@ import {
   CHAIN_ID_SOLANA,
   CHAIN_ID_TERRA,
   CHAIN_ID_POLYGON,
+  CHAIN_ID_ETHEREUM_ROPSTEN,
 } from "./consts";
 import { humanAddress, canonicalAddress, isNativeDenom } from "../terra";
 import { PublicKey } from "@solana/web3.js";
@@ -14,6 +15,7 @@ import { arrayify, zeroPad } from "@ethersproject/bytes";
 export const isEVMChain = (chainId: ChainId) =>
   chainId === CHAIN_ID_ETH ||
   chainId === CHAIN_ID_BSC ||
+  chainId === CHAIN_ID_ETHEREUM_ROPSTEN ||
   chainId === CHAIN_ID_POLYGON;
 
 export const isHexNativeTerra = (h: string) => h.startsWith("01");
@@ -29,7 +31,7 @@ export const hexToNativeString = (h: string | undefined, c: ChainId) => {
       ? undefined
       : c === CHAIN_ID_SOLANA
       ? new PublicKey(hexToUint8Array(h)).toString()
-      : c === CHAIN_ID_ETH || c === CHAIN_ID_BSC || c === CHAIN_ID_POLYGON
+      : c === CHAIN_ID_ETH || c === CHAIN_ID_BSC || c === CHAIN_ID_POLYGON || c === CHAIN_ID_ETHEREUM_ROPSTEN
       ? hexZeroPad(hexValue(hexToUint8Array(h)), 20)
       : c === CHAIN_ID_TERRA
       ? isHexNativeTerra(h)

+ 2 - 1
sdk/js/src/utils/consts.ts

@@ -1,9 +1,10 @@
-export type ChainId = 1 | 2 | 3 | 4 | 5;
+export type ChainId = 1 | 2 | 3 | 4 | 5 | 10001;
 export const CHAIN_ID_SOLANA: ChainId = 1;
 export const CHAIN_ID_ETH: ChainId = 2;
 export const CHAIN_ID_TERRA: ChainId = 3;
 export const CHAIN_ID_BSC: ChainId = 4;
 export const CHAIN_ID_POLYGON: ChainId = 5;
+export const CHAIN_ID_ETHEREUM_ROPSTEN: ChainId = 10001;
 
 export const WSOL_ADDRESS = "So11111111111111111111111111111111111111112";
 export const WSOL_DECIMALS = 9;