node.go 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492
  1. package guardiand
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. "net"
  7. _ "net/http/pprof" // #nosec G108 we are using a custom router (`router := mux.NewRouter()`) and thus not automatically expose pprof.
  8. "os"
  9. "os/signal"
  10. "path"
  11. "runtime"
  12. "strings"
  13. "syscall"
  14. "time"
  15. "github.com/certusone/wormhole/node/pkg/watchers"
  16. "github.com/certusone/wormhole/node/pkg/watchers/ibc"
  17. ethcrypto "github.com/ethereum/go-ethereum/crypto"
  18. "github.com/certusone/wormhole/node/pkg/watchers/cosmwasm"
  19. "github.com/certusone/wormhole/node/pkg/watchers/algorand"
  20. "github.com/certusone/wormhole/node/pkg/watchers/aptos"
  21. "github.com/certusone/wormhole/node/pkg/watchers/evm"
  22. "github.com/certusone/wormhole/node/pkg/watchers/near"
  23. "github.com/certusone/wormhole/node/pkg/watchers/solana"
  24. "github.com/certusone/wormhole/node/pkg/watchers/sui"
  25. "github.com/certusone/wormhole/node/pkg/wormconn"
  26. "github.com/certusone/wormhole/node/pkg/db"
  27. "github.com/certusone/wormhole/node/pkg/telemetry"
  28. "github.com/certusone/wormhole/node/pkg/version"
  29. "github.com/gagliardetto/solana-go/rpc"
  30. "go.uber.org/zap/zapcore"
  31. "github.com/certusone/wormhole/node/pkg/common"
  32. "github.com/certusone/wormhole/node/pkg/devnet"
  33. "github.com/certusone/wormhole/node/pkg/node"
  34. "github.com/certusone/wormhole/node/pkg/p2p"
  35. "github.com/certusone/wormhole/node/pkg/supervisor"
  36. promremotew "github.com/certusone/wormhole/node/pkg/telemetry/prom_remote_write"
  37. libp2p_crypto "github.com/libp2p/go-libp2p/core/crypto"
  38. "github.com/libp2p/go-libp2p/core/peer"
  39. "github.com/spf13/cobra"
  40. "github.com/wormhole-foundation/wormhole/sdk/vaa"
  41. "go.uber.org/zap"
  42. ipfslog "github.com/ipfs/go-log/v2"
  43. )
  44. var (
  45. p2pNetworkID *string
  46. p2pPort *uint
  47. p2pBootstrap *string
  48. nodeKeyPath *string
  49. adminSocketPath *string
  50. publicGRPCSocketPath *string
  51. dataDir *string
  52. statusAddr *string
  53. guardianKeyPath *string
  54. solanaContract *string
  55. ethRPC *string
  56. ethContract *string
  57. bscRPC *string
  58. bscContract *string
  59. polygonRPC *string
  60. polygonContract *string
  61. auroraRPC *string
  62. auroraContract *string
  63. fantomRPC *string
  64. fantomContract *string
  65. avalancheRPC *string
  66. avalancheContract *string
  67. oasisRPC *string
  68. oasisContract *string
  69. karuraRPC *string
  70. karuraContract *string
  71. acalaRPC *string
  72. acalaContract *string
  73. klaytnRPC *string
  74. klaytnContract *string
  75. celoRPC *string
  76. celoContract *string
  77. moonbeamRPC *string
  78. moonbeamContract *string
  79. neonRPC *string
  80. neonContract *string
  81. terraWS *string
  82. terraLCD *string
  83. terraContract *string
  84. terra2WS *string
  85. terra2LCD *string
  86. terra2Contract *string
  87. injectiveWS *string
  88. injectiveLCD *string
  89. injectiveContract *string
  90. xplaWS *string
  91. xplaLCD *string
  92. xplaContract *string
  93. gatewayWS *string
  94. gatewayLCD *string
  95. gatewayContract *string
  96. algorandIndexerRPC *string
  97. algorandIndexerToken *string
  98. algorandAlgodRPC *string
  99. algorandAlgodToken *string
  100. algorandAppID *uint64
  101. nearRPC *string
  102. nearContract *string
  103. wormchainURL *string
  104. wormchainKeyPath *string
  105. wormchainKeyPassPhrase *string
  106. ibcWS *string
  107. ibcLCD *string
  108. ibcBlockHeightURL *string
  109. ibcContract *string
  110. accountantContract *string
  111. accountantWS *string
  112. accountantCheckEnabled *bool
  113. accountantKeyPath *string
  114. accountantKeyPassPhrase *string
  115. aptosRPC *string
  116. aptosAccount *string
  117. aptosHandle *string
  118. suiRPC *string
  119. suiWS *string
  120. suiMoveEventType *string
  121. solanaRPC *string
  122. pythnetContract *string
  123. pythnetRPC *string
  124. pythnetWS *string
  125. arbitrumRPC *string
  126. arbitrumContract *string
  127. optimismRPC *string
  128. optimismContract *string
  129. baseRPC *string
  130. baseContract *string
  131. scrollRPC *string
  132. scrollContract *string
  133. sepoliaRPC *string
  134. sepoliaContract *string
  135. logLevel *string
  136. publicRpcLogDetailStr *string
  137. publicRpcLogToTelemetry *bool
  138. unsafeDevMode *bool
  139. testnetMode *bool
  140. nodeName *string
  141. publicRPC *string
  142. publicWeb *string
  143. tlsHostname *string
  144. tlsProdEnv *bool
  145. disableHeartbeatVerify *bool
  146. disableTelemetry *bool
  147. // Loki cloud logging parameters
  148. telemetryLokiURL *string
  149. // Prometheus remote write URL
  150. promRemoteURL *string
  151. chainGovernorEnabled *bool
  152. ccqEnabled *bool
  153. ccqAllowedRequesters *string
  154. ccqP2pPort *uint
  155. ccqP2pBootstrap *string
  156. ccqAllowedPeers *string
  157. gatewayRelayerContract *string
  158. gatewayRelayerKeyPath *string
  159. gatewayRelayerKeyPassPhrase *string
  160. )
  161. func init() {
  162. p2pNetworkID = NodeCmd.Flags().String("network", "/wormhole/dev", "P2P network identifier")
  163. p2pPort = NodeCmd.Flags().Uint("port", p2p.DefaultPort, "P2P UDP listener port")
  164. p2pBootstrap = NodeCmd.Flags().String("bootstrap", "", "P2P bootstrap peers (comma-separated)")
  165. statusAddr = NodeCmd.Flags().String("statusAddr", "[::]:6060", "Listen address for status server (disabled if blank)")
  166. nodeKeyPath = NodeCmd.Flags().String("nodeKey", "", "Path to node key (will be generated if it doesn't exist)")
  167. adminSocketPath = NodeCmd.Flags().String("adminSocket", "", "Admin gRPC service UNIX domain socket path")
  168. publicGRPCSocketPath = NodeCmd.Flags().String("publicGRPCSocket", "", "Public gRPC service UNIX domain socket path")
  169. dataDir = NodeCmd.Flags().String("dataDir", "", "Data directory")
  170. guardianKeyPath = NodeCmd.Flags().String("guardianKey", "", "Path to guardian key (required)")
  171. solanaContract = NodeCmd.Flags().String("solanaContract", "", "Address of the Solana program (required)")
  172. ethRPC = NodeCmd.Flags().String("ethRPC", "", "Ethereum RPC URL")
  173. ethContract = NodeCmd.Flags().String("ethContract", "", "Ethereum contract address")
  174. bscRPC = NodeCmd.Flags().String("bscRPC", "", "Binance Smart Chain RPC URL")
  175. bscContract = NodeCmd.Flags().String("bscContract", "", "Binance Smart Chain contract address")
  176. polygonRPC = NodeCmd.Flags().String("polygonRPC", "", "Polygon RPC URL")
  177. polygonContract = NodeCmd.Flags().String("polygonContract", "", "Polygon contract address")
  178. avalancheRPC = NodeCmd.Flags().String("avalancheRPC", "", "Avalanche RPC URL")
  179. avalancheContract = NodeCmd.Flags().String("avalancheContract", "", "Avalanche contract address")
  180. oasisRPC = NodeCmd.Flags().String("oasisRPC", "", "Oasis RPC URL")
  181. oasisContract = NodeCmd.Flags().String("oasisContract", "", "Oasis contract address")
  182. auroraRPC = NodeCmd.Flags().String("auroraRPC", "", "Aurora Websocket RPC URL")
  183. auroraContract = NodeCmd.Flags().String("auroraContract", "", "Aurora contract address")
  184. fantomRPC = NodeCmd.Flags().String("fantomRPC", "", "Fantom Websocket RPC URL")
  185. fantomContract = NodeCmd.Flags().String("fantomContract", "", "Fantom contract address")
  186. karuraRPC = NodeCmd.Flags().String("karuraRPC", "", "Karura RPC URL")
  187. karuraContract = NodeCmd.Flags().String("karuraContract", "", "Karura contract address")
  188. acalaRPC = NodeCmd.Flags().String("acalaRPC", "", "Acala RPC URL")
  189. acalaContract = NodeCmd.Flags().String("acalaContract", "", "Acala contract address")
  190. klaytnRPC = NodeCmd.Flags().String("klaytnRPC", "", "Klaytn RPC URL")
  191. klaytnContract = NodeCmd.Flags().String("klaytnContract", "", "Klaytn contract address")
  192. celoRPC = NodeCmd.Flags().String("celoRPC", "", "Celo RPC URL")
  193. celoContract = NodeCmd.Flags().String("celoContract", "", "Celo contract address")
  194. moonbeamRPC = NodeCmd.Flags().String("moonbeamRPC", "", "Moonbeam RPC URL")
  195. moonbeamContract = NodeCmd.Flags().String("moonbeamContract", "", "Moonbeam contract address")
  196. neonRPC = NodeCmd.Flags().String("neonRPC", "", "Neon RPC URL")
  197. neonContract = NodeCmd.Flags().String("neonContract", "", "Neon contract address")
  198. terraWS = NodeCmd.Flags().String("terraWS", "", "Path to terrad root for websocket connection")
  199. terraLCD = NodeCmd.Flags().String("terraLCD", "", "Path to LCD service root for http calls")
  200. terraContract = NodeCmd.Flags().String("terraContract", "", "Wormhole contract address on Terra blockchain")
  201. terra2WS = NodeCmd.Flags().String("terra2WS", "", "Path to terrad root for websocket connection")
  202. terra2LCD = NodeCmd.Flags().String("terra2LCD", "", "Path to LCD service root for http calls")
  203. terra2Contract = NodeCmd.Flags().String("terra2Contract", "", "Wormhole contract address on Terra 2 blockchain")
  204. injectiveWS = NodeCmd.Flags().String("injectiveWS", "", "Path to root for Injective websocket connection")
  205. injectiveLCD = NodeCmd.Flags().String("injectiveLCD", "", "Path to LCD service root for Injective http calls")
  206. injectiveContract = NodeCmd.Flags().String("injectiveContract", "", "Wormhole contract address on Injective blockchain")
  207. xplaWS = NodeCmd.Flags().String("xplaWS", "", "Path to root for XPLA websocket connection")
  208. xplaLCD = NodeCmd.Flags().String("xplaLCD", "", "Path to LCD service root for XPLA http calls")
  209. xplaContract = NodeCmd.Flags().String("xplaContract", "", "Wormhole contract address on XPLA blockchain")
  210. gatewayWS = NodeCmd.Flags().String("gatewayWS", "", "Path to root for Gateway watcher websocket connection")
  211. gatewayLCD = NodeCmd.Flags().String("gatewayLCD", "", "Path to LCD service root for Gateway watcher http calls")
  212. gatewayContract = NodeCmd.Flags().String("gatewayContract", "", "Wormhole contract address on Gateway blockchain")
  213. algorandIndexerRPC = NodeCmd.Flags().String("algorandIndexerRPC", "", "Algorand Indexer RPC URL")
  214. algorandIndexerToken = NodeCmd.Flags().String("algorandIndexerToken", "", "Algorand Indexer access token")
  215. algorandAlgodRPC = NodeCmd.Flags().String("algorandAlgodRPC", "", "Algorand Algod RPC URL")
  216. algorandAlgodToken = NodeCmd.Flags().String("algorandAlgodToken", "", "Algorand Algod access token")
  217. algorandAppID = NodeCmd.Flags().Uint64("algorandAppID", 0, "Algorand app id")
  218. nearRPC = NodeCmd.Flags().String("nearRPC", "", "near RPC URL")
  219. nearContract = NodeCmd.Flags().String("nearContract", "", "near contract")
  220. wormchainURL = NodeCmd.Flags().String("wormchainURL", "", "wormhole-chain gRPC URL")
  221. // TODO: These are deprecated. Get rid of them once the guardians have had a chance to migrate off of them.
  222. wormchainKeyPath = NodeCmd.Flags().String("wormchainKeyPath", "", "path to wormhole-chain private key for signing transactions")
  223. wormchainKeyPassPhrase = NodeCmd.Flags().String("wormchainKeyPassPhrase", "", "pass phrase used to unarmor the wormchain key file")
  224. ibcWS = NodeCmd.Flags().String("ibcWS", "", "Websocket used to listen to the IBC receiver smart contract on wormchain")
  225. ibcLCD = NodeCmd.Flags().String("ibcLCD", "", "Path to LCD service root for http calls")
  226. ibcBlockHeightURL = NodeCmd.Flags().String("ibcBlockHeightURL", "", "Optional URL to query for the block height (generated from ibcWS if not specified)")
  227. ibcContract = NodeCmd.Flags().String("ibcContract", "", "Address of the IBC smart contract on wormchain")
  228. accountantWS = NodeCmd.Flags().String("accountantWS", "", "Websocket used to listen to the accountant smart contract on wormchain")
  229. accountantContract = NodeCmd.Flags().String("accountantContract", "", "Address of the accountant smart contract on wormchain")
  230. accountantKeyPath = NodeCmd.Flags().String("accountantKeyPath", "", "path to accountant private key for signing transactions")
  231. accountantKeyPassPhrase = NodeCmd.Flags().String("accountantKeyPassPhrase", "", "pass phrase used to unarmor the accountant key file")
  232. accountantCheckEnabled = NodeCmd.Flags().Bool("accountantCheckEnabled", false, "Should accountant be enforced on transfers")
  233. aptosRPC = NodeCmd.Flags().String("aptosRPC", "", "aptos RPC URL")
  234. aptosAccount = NodeCmd.Flags().String("aptosAccount", "", "aptos account")
  235. aptosHandle = NodeCmd.Flags().String("aptosHandle", "", "aptos handle")
  236. suiRPC = NodeCmd.Flags().String("suiRPC", "", "sui RPC URL")
  237. suiWS = NodeCmd.Flags().String("suiWS", "", "sui WS URL")
  238. suiMoveEventType = NodeCmd.Flags().String("suiMoveEventType", "", "sui move event type for publish_message")
  239. solanaRPC = NodeCmd.Flags().String("solanaRPC", "", "Solana RPC URL (required)")
  240. pythnetContract = NodeCmd.Flags().String("pythnetContract", "", "Address of the PythNet program (required)")
  241. pythnetRPC = NodeCmd.Flags().String("pythnetRPC", "", "PythNet RPC URL (required)")
  242. pythnetWS = NodeCmd.Flags().String("pythnetWS", "", "PythNet WS URL")
  243. arbitrumRPC = NodeCmd.Flags().String("arbitrumRPC", "", "Arbitrum RPC URL")
  244. arbitrumContract = NodeCmd.Flags().String("arbitrumContract", "", "Arbitrum contract address")
  245. sepoliaRPC = NodeCmd.Flags().String("sepoliaRPC", "", "Sepolia RPC URL")
  246. sepoliaContract = NodeCmd.Flags().String("sepoliaContract", "", "Sepolia contract address")
  247. optimismRPC = NodeCmd.Flags().String("optimismRPC", "", "Optimism RPC URL")
  248. optimismContract = NodeCmd.Flags().String("optimismContract", "", "Optimism contract address")
  249. scrollRPC = NodeCmd.Flags().String("scrollRPC", "", "Scroll RPC URL")
  250. scrollContract = NodeCmd.Flags().String("scrollContract", "", "Scroll contract address")
  251. baseRPC = NodeCmd.Flags().String("baseRPC", "", "Base RPC URL")
  252. baseContract = NodeCmd.Flags().String("baseContract", "", "Base contract address")
  253. logLevel = NodeCmd.Flags().String("logLevel", "info", "Logging level (debug, info, warn, error, dpanic, panic, fatal)")
  254. publicRpcLogDetailStr = NodeCmd.Flags().String("publicRpcLogDetail", "full", "The detail with which public RPC requests shall be logged (none=no logging, minimal=only log gRPC methods, full=log gRPC method, payload (up to 200 bytes) and user agent (up to 200 bytes))")
  255. publicRpcLogToTelemetry = NodeCmd.Flags().Bool("logPublicRpcToTelemetry", true, "whether or not to include publicRpc request logs in telemetry")
  256. unsafeDevMode = NodeCmd.Flags().Bool("unsafeDevMode", false, "Launch node in unsafe, deterministic devnet mode")
  257. testnetMode = NodeCmd.Flags().Bool("testnetMode", false, "Launch node in testnet mode (enables testnet-only features)")
  258. nodeName = NodeCmd.Flags().String("nodeName", "", "Node name to announce in gossip heartbeats")
  259. publicRPC = NodeCmd.Flags().String("publicRPC", "", "Listen address for public gRPC interface")
  260. publicWeb = NodeCmd.Flags().String("publicWeb", "", "Listen address for public REST and gRPC Web interface")
  261. tlsHostname = NodeCmd.Flags().String("tlsHostname", "", "If set, serve publicWeb as TLS with this hostname using Let's Encrypt")
  262. tlsProdEnv = NodeCmd.Flags().Bool("tlsProdEnv", false,
  263. "Use the production Let's Encrypt environment instead of staging")
  264. disableHeartbeatVerify = NodeCmd.Flags().Bool("disableHeartbeatVerify", false,
  265. "Disable heartbeat signature verification (useful during network startup)")
  266. disableTelemetry = NodeCmd.Flags().Bool("disableTelemetry", false,
  267. "Disable telemetry")
  268. telemetryLokiURL = NodeCmd.Flags().String("telemetryLokiURL", "", "Loki cloud logging URL")
  269. promRemoteURL = NodeCmd.Flags().String("promRemoteURL", "", "Prometheus remote write URL (Grafana)")
  270. chainGovernorEnabled = NodeCmd.Flags().Bool("chainGovernorEnabled", false, "Run the chain governor")
  271. ccqEnabled = NodeCmd.Flags().Bool("ccqEnabled", false, "Enable cross chain query support")
  272. ccqAllowedRequesters = NodeCmd.Flags().String("ccqAllowedRequesters", "", "Comma separated list of signers allowed to submit cross chain queries")
  273. ccqP2pPort = NodeCmd.Flags().Uint("ccqP2pPort", 8996, "CCQ P2P UDP listener port")
  274. ccqP2pBootstrap = NodeCmd.Flags().String("ccqP2pBootstrap", "", "CCQ P2P bootstrap peers (comma-separated)")
  275. ccqAllowedPeers = NodeCmd.Flags().String("ccqAllowedPeers", "", "CCQ allowed P2P peers (comma-separated)")
  276. gatewayRelayerContract = NodeCmd.Flags().String("gatewayRelayerContract", "", "Address of the smart contract on wormchain to receive relayed VAAs")
  277. gatewayRelayerKeyPath = NodeCmd.Flags().String("gatewayRelayerKeyPath", "", "Path to gateway relayer private key for signing transactions")
  278. gatewayRelayerKeyPassPhrase = NodeCmd.Flags().String("gatewayRelayerKeyPassPhrase", "", "Pass phrase used to unarmor the gateway relayer key file")
  279. }
  280. var (
  281. rootCtx context.Context
  282. rootCtxCancel context.CancelFunc
  283. )
  284. // "Why would anyone do this?" are famous last words.
  285. //
  286. // We already forcibly override RPC URLs and keys in dev mode to prevent security
  287. // risks from operator error, but an extra warning won't hurt.
  288. const devwarning = `
  289. +++++++++++++++++++++++++++++++++++++++++++++++++++
  290. | NODE IS RUNNING IN INSECURE DEVELOPMENT MODE |
  291. | |
  292. | Do not use --unsafeDevMode in prod. |
  293. +++++++++++++++++++++++++++++++++++++++++++++++++++
  294. `
  295. // NodeCmd represents the node command
  296. var NodeCmd = &cobra.Command{
  297. Use: "node",
  298. Short: "Run the guardiand node",
  299. Run: runNode,
  300. }
  301. // This variable may be overridden by the -X linker flag to "dev" in which case
  302. // we enforce the --unsafeDevMode flag. Only development binaries/docker images
  303. // are distributed. Production binaries are required to be built from source by
  304. // guardians to reduce risk from a compromised builder.
  305. var Build = "prod"
  306. func runNode(cmd *cobra.Command, args []string) {
  307. if Build == "dev" && !*unsafeDevMode {
  308. fmt.Println("This is a development build. --unsafeDevMode must be enabled.")
  309. os.Exit(1)
  310. }
  311. if *unsafeDevMode {
  312. fmt.Print(devwarning)
  313. }
  314. if *testnetMode || *unsafeDevMode {
  315. fmt.Println("Not locking in memory.")
  316. } else {
  317. common.LockMemory()
  318. }
  319. common.SetRestrictiveUmask()
  320. // Refuse to run as root in production mode.
  321. if !*unsafeDevMode && os.Geteuid() == 0 {
  322. fmt.Println("can't run as uid 0")
  323. os.Exit(1)
  324. }
  325. // Set up logging. The go-log zap wrapper that libp2p uses is compatible with our
  326. // usage of zap in supervisor, which is nice.
  327. lvl, err := ipfslog.LevelFromString(*logLevel)
  328. if err != nil {
  329. fmt.Println("Invalid log level")
  330. os.Exit(1)
  331. }
  332. logger := zap.New(zapcore.NewCore(
  333. consoleEncoder{zapcore.NewConsoleEncoder(
  334. zap.NewDevelopmentEncoderConfig())},
  335. zapcore.AddSync(zapcore.Lock(os.Stderr)),
  336. zap.NewAtomicLevelAt(zapcore.Level(lvl))))
  337. if *unsafeDevMode {
  338. // Use the hostname as nodeName. For production, we don't want to do this to
  339. // prevent accidentally leaking sensitive hostnames.
  340. hostname, err := os.Hostname()
  341. if err != nil {
  342. panic(err)
  343. }
  344. *nodeName = hostname
  345. // Put node name into the log for development.
  346. logger = logger.Named(*nodeName)
  347. }
  348. // Override the default go-log config, which uses a magic environment variable.
  349. ipfslog.SetAllLoggers(lvl)
  350. // In devnet mode, we automatically set a number of flags that rely on deterministic keys.
  351. if *unsafeDevMode {
  352. g0key, err := peer.IDFromPrivateKey(devnet.DeterministicP2PPrivKeyByIndex(0))
  353. if err != nil {
  354. panic(err)
  355. }
  356. // Use the first guardian node as bootstrap
  357. *p2pBootstrap = fmt.Sprintf("/dns4/guardian-0.guardian/udp/%d/quic/p2p/%s", *p2pPort, g0key.String())
  358. *ccqP2pBootstrap = fmt.Sprintf("/dns4/guardian-0.guardian/udp/%d/quic/p2p/%s", *ccqP2pPort, g0key.String())
  359. // Deterministic ganache ETH devnet address.
  360. *ethContract = unsafeDevModeEvmContractAddress(*ethContract)
  361. *bscContract = unsafeDevModeEvmContractAddress(*bscContract)
  362. *polygonContract = unsafeDevModeEvmContractAddress(*polygonContract)
  363. *avalancheContract = unsafeDevModeEvmContractAddress(*avalancheContract)
  364. *oasisContract = unsafeDevModeEvmContractAddress(*oasisContract)
  365. *auroraContract = unsafeDevModeEvmContractAddress(*auroraContract)
  366. *fantomContract = unsafeDevModeEvmContractAddress(*fantomContract)
  367. *karuraContract = unsafeDevModeEvmContractAddress(*karuraContract)
  368. *acalaContract = unsafeDevModeEvmContractAddress(*acalaContract)
  369. *klaytnContract = unsafeDevModeEvmContractAddress(*klaytnContract)
  370. *celoContract = unsafeDevModeEvmContractAddress(*celoContract)
  371. *moonbeamContract = unsafeDevModeEvmContractAddress(*moonbeamContract)
  372. *neonContract = unsafeDevModeEvmContractAddress(*neonContract)
  373. *arbitrumContract = unsafeDevModeEvmContractAddress(*arbitrumContract)
  374. *optimismContract = unsafeDevModeEvmContractAddress(*optimismContract)
  375. *baseContract = unsafeDevModeEvmContractAddress(*baseContract)
  376. *sepoliaContract = unsafeDevModeEvmContractAddress(*sepoliaContract)
  377. *scrollContract = unsafeDevModeEvmContractAddress(*scrollContract)
  378. }
  379. // Verify flags
  380. if *nodeKeyPath == "" && !*unsafeDevMode { // In devnet mode, keys are deterministically generated.
  381. logger.Fatal("Please specify --nodeKey")
  382. }
  383. if *guardianKeyPath == "" {
  384. logger.Fatal("Please specify --guardianKey")
  385. }
  386. if *adminSocketPath == "" {
  387. logger.Fatal("Please specify --adminSocket")
  388. }
  389. if *adminSocketPath == *publicGRPCSocketPath {
  390. logger.Fatal("--adminSocket must not equal --publicGRPCSocket")
  391. }
  392. if (*publicRPC != "" || *publicWeb != "") && *publicGRPCSocketPath == "" {
  393. logger.Fatal("If either --publicRPC or --publicWeb is specified, --publicGRPCSocket must also be specified")
  394. }
  395. if *dataDir == "" {
  396. logger.Fatal("Please specify --dataDir")
  397. }
  398. if *ethRPC == "" {
  399. logger.Fatal("Please specify --ethRPC")
  400. }
  401. if *ethContract == "" {
  402. logger.Fatal("Please specify --ethContract")
  403. }
  404. if *bscRPC == "" {
  405. logger.Fatal("Please specify --bscRPC")
  406. }
  407. if *bscContract == "" {
  408. logger.Fatal("Please specify --bscContract")
  409. }
  410. if *polygonRPC == "" {
  411. logger.Fatal("Please specify --polygonRPC")
  412. }
  413. if *polygonContract == "" {
  414. logger.Fatal("Please specify --polygonContract")
  415. }
  416. if *avalancheRPC == "" {
  417. logger.Fatal("Please specify --avalancheRPC")
  418. }
  419. if *oasisRPC == "" {
  420. logger.Fatal("Please specify --oasisRPC")
  421. }
  422. if *fantomRPC == "" {
  423. logger.Fatal("Please specify --fantomRPC")
  424. }
  425. if *fantomContract == "" && !*unsafeDevMode {
  426. logger.Fatal("Please specify --fantomContract")
  427. }
  428. if *auroraRPC == "" {
  429. logger.Fatal("Please specify --auroraRPC")
  430. }
  431. if *auroraContract == "" && !*unsafeDevMode {
  432. logger.Fatal("Please specify --auroraContract")
  433. }
  434. if *karuraRPC == "" {
  435. logger.Fatal("Please specify --karuraRPC")
  436. }
  437. if *karuraContract == "" && !*unsafeDevMode {
  438. logger.Fatal("Please specify --karuraContract")
  439. }
  440. if *acalaRPC == "" {
  441. logger.Fatal("Please specify --acalaRPC")
  442. }
  443. if *acalaContract == "" && !*unsafeDevMode {
  444. logger.Fatal("Please specify --acalaContract")
  445. }
  446. if *klaytnRPC == "" {
  447. logger.Fatal("Please specify --klaytnRPC")
  448. }
  449. if *klaytnContract == "" && !*unsafeDevMode {
  450. logger.Fatal("Please specify --klaytnContract")
  451. }
  452. if *celoRPC == "" {
  453. logger.Fatal("Please specify --celoRPC")
  454. }
  455. if *celoContract == "" && !*unsafeDevMode {
  456. logger.Fatal("Please specify --celoContract")
  457. }
  458. if *nearRPC != "" {
  459. if *nearContract == "" {
  460. logger.Fatal("If --nearRPC is specified, then --nearContract must be specified")
  461. }
  462. } else if *nearContract != "" {
  463. logger.Fatal("If --nearRPC is not specified, then --nearContract must not be specified")
  464. }
  465. if *moonbeamRPC == "" {
  466. logger.Fatal("Please specify --moonbeamRPC")
  467. }
  468. if *moonbeamContract == "" {
  469. logger.Fatal("Please specify --moonbeamContract")
  470. }
  471. if *arbitrumRPC == "" {
  472. logger.Fatal("Please specify --arbitrumRPC")
  473. }
  474. if *arbitrumContract == "" {
  475. logger.Fatal("Please specify --arbitrumContract")
  476. }
  477. if *xplaWS != "" {
  478. if *xplaLCD == "" || *xplaContract == "" {
  479. logger.Fatal("If --xplaWS is specified, then --xplaLCD and --xplaContract must be specified")
  480. }
  481. } else if *xplaLCD != "" || *xplaContract != "" {
  482. logger.Fatal("If --xplaWS is not specified, then --xplaLCD and --xplaContract must not be specified")
  483. }
  484. if *aptosRPC != "" {
  485. if *aptosAccount == "" {
  486. logger.Fatal("If --aptosRPC is specified, then --aptosAccount must be specified")
  487. }
  488. if *aptosHandle == "" {
  489. logger.Fatal("If --aptosRPC is specified, then --aptosHandle must be specified")
  490. }
  491. }
  492. if *suiRPC != "" {
  493. if *suiWS == "" {
  494. logger.Fatal("If --suiRPC is specified, then --suiWS must be specified")
  495. }
  496. if *suiMoveEventType == "" {
  497. logger.Fatal("If --suiRPC is specified, then --suiMoveEventType must be specified")
  498. }
  499. }
  500. if (*optimismRPC == "") != (*optimismContract == "") {
  501. logger.Fatal("Both --optimismContract and --optimismRPC must be set together or both unset")
  502. }
  503. if (*baseRPC == "") != (*baseContract == "") {
  504. logger.Fatal("Both --baseContract and --baseRPC must be set together or both unset")
  505. }
  506. // Scroll should not be allowed in mainnet until its finality policy is understood and implemented in the watcher.
  507. if *scrollRPC != "" && !*testnetMode && !*unsafeDevMode {
  508. logger.Fatal("scroll is currently only supported in devnet and testnet")
  509. }
  510. if (*scrollRPC == "") != (*scrollContract == "") {
  511. logger.Fatal("Both --scrollContract and --scrollRPC must be set together or both unset")
  512. }
  513. if *gatewayWS != "" {
  514. if *gatewayLCD == "" || *gatewayContract == "" {
  515. logger.Fatal("If --gatewayWS is specified, then --gatewayLCD and --gatewayContract must be specified")
  516. }
  517. } else if *gatewayLCD != "" || *gatewayContract != "" {
  518. logger.Fatal("If --gatewayWS is not specified, then --gatewayLCD and --gatewayContract must not be specified")
  519. }
  520. if *testnetMode {
  521. if *neonRPC == "" {
  522. logger.Fatal("Please specify --neonRPC")
  523. }
  524. if *neonContract == "" {
  525. logger.Fatal("Please specify --neonContract")
  526. }
  527. if *sepoliaRPC == "" {
  528. logger.Fatal("Please specify --sepoliaRPC")
  529. }
  530. if *sepoliaContract == "" {
  531. logger.Fatal("Please specify --sepoliaContract")
  532. }
  533. } else {
  534. if *neonRPC != "" && !*unsafeDevMode {
  535. logger.Fatal("Please do not specify --neonRPC")
  536. }
  537. if *neonContract != "" && !*unsafeDevMode {
  538. logger.Fatal("Please do not specify --neonContract")
  539. }
  540. if *sepoliaRPC != "" && !*unsafeDevMode {
  541. logger.Fatal("Please do not specify --sepoliaRPC")
  542. }
  543. if *sepoliaContract != "" && !*unsafeDevMode {
  544. logger.Fatal("Please do not specify --sepoliaContract")
  545. }
  546. }
  547. var publicRpcLogDetail common.GrpcLogDetail
  548. switch *publicRpcLogDetailStr {
  549. case "none":
  550. publicRpcLogDetail = common.GrpcLogDetailNone
  551. case "minimal":
  552. publicRpcLogDetail = common.GrpcLogDetailMinimal
  553. case "full":
  554. publicRpcLogDetail = common.GrpcLogDetailFull
  555. default:
  556. logger.Fatal("--publicRpcLogDetail should be one of (none, minimal, full)")
  557. }
  558. if *nodeName == "" {
  559. logger.Fatal("Please specify --nodeName")
  560. }
  561. // Solana, Terra Classic, Terra 2, and Algorand are optional in devnet
  562. if !*unsafeDevMode {
  563. if *solanaContract == "" {
  564. logger.Fatal("Please specify --solanaContract")
  565. }
  566. if *solanaRPC == "" {
  567. logger.Fatal("Please specify --solanaRPC")
  568. }
  569. if *terraWS == "" {
  570. logger.Fatal("Please specify --terraWS")
  571. }
  572. if *terraLCD == "" {
  573. logger.Fatal("Please specify --terraLCD")
  574. }
  575. if *terraContract == "" {
  576. logger.Fatal("Please specify --terraContract")
  577. }
  578. if *terra2WS == "" {
  579. logger.Fatal("Please specify --terra2WS")
  580. }
  581. if *terra2LCD == "" {
  582. logger.Fatal("Please specify --terra2LCD")
  583. }
  584. if *terra2Contract == "" {
  585. logger.Fatal("Please specify --terra2Contract")
  586. }
  587. if *algorandIndexerRPC == "" {
  588. logger.Fatal("Please specify --algorandIndexerRPC")
  589. }
  590. if *algorandAlgodRPC == "" {
  591. logger.Fatal("Please specify --algorandAlgodRPC")
  592. }
  593. if *algorandAlgodToken == "" {
  594. logger.Fatal("Please specify --algorandAlgodToken")
  595. }
  596. if *algorandAppID == 0 {
  597. logger.Fatal("Please specify --algorandAppID")
  598. }
  599. if *pythnetContract == "" {
  600. logger.Fatal("Please specify --pythnetContract")
  601. }
  602. if *pythnetRPC == "" {
  603. logger.Fatal("Please specify --pythnetRPC")
  604. }
  605. if *pythnetWS == "" {
  606. logger.Fatal("Please specify --pythnetWS")
  607. }
  608. if *injectiveWS == "" {
  609. logger.Fatal("Please specify --injectiveWS")
  610. }
  611. if *injectiveLCD == "" {
  612. logger.Fatal("Please specify --injectiveLCD")
  613. }
  614. if *injectiveContract == "" {
  615. logger.Fatal("Please specify --injectiveContract")
  616. }
  617. }
  618. // Determine execution mode
  619. // TODO: refactor usage of these variables elsewhere. *unsafeDevMode and *testnetMode should not be accessed directly.
  620. var env common.Environment
  621. if *unsafeDevMode {
  622. env = common.UnsafeDevNet
  623. } else if *testnetMode {
  624. env = common.TestNet
  625. } else {
  626. env = common.MainNet
  627. }
  628. if *unsafeDevMode && *testnetMode {
  629. logger.Fatal("Cannot be in unsafeDevMode and testnetMode at the same time.")
  630. }
  631. // Complain about Infura on mainnet.
  632. //
  633. // As it turns out, Infura has a bug where it would sometimes incorrectly round
  634. // block timestamps, which causes consensus issues - the timestamp is part of
  635. // the VAA and nodes using Infura would sometimes derive an incorrect VAA,
  636. // accidentally attacking the network by signing a conflicting VAA.
  637. //
  638. // Node operators do not usually rely on Infura in the first place - doing
  639. // so is insecure, since nodes blindly trust the connected nodes to verify
  640. // on-chain message proofs. However, node operators sometimes used
  641. // Infura during migrations where their primary node was offline, causing
  642. // the aforementioned consensus oddities which were eventually found to
  643. // be Infura-related. This is generally to the detriment of network security
  644. // and a judgement call made by individual operators. In the case of Infura,
  645. // we know it's actively dangerous so let's make an opinionated argument.
  646. //
  647. // Insert "I'm a sign, not a cop" meme.
  648. //
  649. if strings.Contains(*ethRPC, "mainnet.infura.io") ||
  650. strings.Contains(*polygonRPC, "polygon-mainnet.infura.io") {
  651. logger.Fatal("Infura is known to send incorrect blocks - please use your own nodes")
  652. }
  653. // In devnet mode, we generate a deterministic guardian key and write it to disk.
  654. if *unsafeDevMode {
  655. err := devnet.GenerateAndStoreDevnetGuardianKey(*guardianKeyPath)
  656. if err != nil {
  657. logger.Fatal("failed to generate devnet guardian key", zap.Error(err))
  658. }
  659. }
  660. // Database
  661. db := db.OpenDb(logger, dataDir)
  662. defer db.Close()
  663. // Guardian key
  664. gk, err := common.LoadGuardianKey(*guardianKeyPath, *unsafeDevMode)
  665. if err != nil {
  666. logger.Fatal("failed to load guardian key", zap.Error(err))
  667. }
  668. logger.Info("Loaded guardian key", zap.String(
  669. "address", ethcrypto.PubkeyToAddress(gk.PublicKey).String()))
  670. // Load p2p private key
  671. var p2pKey libp2p_crypto.PrivKey
  672. if *unsafeDevMode {
  673. idx, err := devnet.GetDevnetIndex()
  674. if err != nil {
  675. logger.Fatal("Failed to parse hostname - are we running in devnet?")
  676. }
  677. p2pKey = devnet.DeterministicP2PPrivKeyByIndex(int64(idx))
  678. if idx != 0 {
  679. // try to connect to guardian-0
  680. for {
  681. _, err := net.LookupIP("guardian-0.guardian")
  682. if err == nil {
  683. break
  684. }
  685. logger.Info("Error resolving guardian-0.guardian. Trying again...")
  686. time.Sleep(time.Second)
  687. }
  688. // TODO this is a hack. If this is not the bootstrap Guardian, we wait 10s such that the bootstrap Guardian has enough time to start.
  689. // This may no longer be necessary because now the p2p.go ensures that it can connect to at least one bootstrap peer and will
  690. // exit the whole guardian if it is unable to. Sleeping here for a bit may reduce overall startup time by preventing unnecessary restarts, though.
  691. logger.Info("This is not a bootstrap Guardian. Waiting another 10 seconds for the bootstrap guardian to come online.")
  692. time.Sleep(time.Second * 10)
  693. }
  694. } else {
  695. p2pKey, err = common.GetOrCreateNodeKey(logger, *nodeKeyPath)
  696. if err != nil {
  697. logger.Fatal("Failed to load node key", zap.Error(err))
  698. }
  699. }
  700. rpcMap := make(map[string]string)
  701. rpcMap["acalaRPC"] = *acalaRPC
  702. rpcMap["algorandIndexerRPC"] = *algorandIndexerRPC
  703. rpcMap["algorandAlgodRPC"] = *algorandAlgodRPC
  704. rpcMap["aptosRPC"] = *aptosRPC
  705. rpcMap["arbitrumRPC"] = *arbitrumRPC
  706. rpcMap["auroraRPC"] = *auroraRPC
  707. rpcMap["avalancheRPC"] = *avalancheRPC
  708. rpcMap["baseRPC"] = *baseRPC
  709. rpcMap["bscRPC"] = *bscRPC
  710. rpcMap["celoRPC"] = *celoRPC
  711. rpcMap["ethRPC"] = *ethRPC
  712. rpcMap["fantomRPC"] = *fantomRPC
  713. rpcMap["ibcBlockHeightURL"] = *ibcBlockHeightURL
  714. rpcMap["ibcLCD"] = *ibcLCD
  715. rpcMap["ibcWS"] = *ibcWS
  716. rpcMap["karuraRPC"] = *karuraRPC
  717. rpcMap["klaytnRPC"] = *klaytnRPC
  718. rpcMap["moonbeamRPC"] = *moonbeamRPC
  719. rpcMap["nearRPC"] = *nearRPC
  720. rpcMap["neonRPC"] = *neonRPC
  721. rpcMap["oasisRPC"] = *oasisRPC
  722. rpcMap["optimismRPC"] = *optimismRPC
  723. rpcMap["polygonRPC"] = *polygonRPC
  724. rpcMap["pythnetRPC"] = *pythnetRPC
  725. rpcMap["pythnetWS"] = *pythnetWS
  726. if env == common.TestNet {
  727. rpcMap["sepoliaRPC"] = *sepoliaRPC
  728. }
  729. rpcMap["scrollRPC"] = *scrollRPC
  730. rpcMap["solanaRPC"] = *solanaRPC
  731. rpcMap["suiRPC"] = *suiRPC
  732. rpcMap["terraWS"] = *terraWS
  733. rpcMap["terraLCD"] = *terraLCD
  734. rpcMap["terra2WS"] = *terra2WS
  735. rpcMap["terra2LCD"] = *terra2LCD
  736. rpcMap["gatewayWS"] = *gatewayWS
  737. rpcMap["gatewayLCD"] = *gatewayLCD
  738. rpcMap["xplaWS"] = *xplaWS
  739. rpcMap["xplaLCD"] = *xplaLCD
  740. for _, ibcChain := range ibc.Chains {
  741. rpcMap[ibcChain.String()] = "IBC"
  742. }
  743. // Node's main lifecycle context.
  744. rootCtx, rootCtxCancel = context.WithCancel(context.Background())
  745. defer rootCtxCancel()
  746. // Handle SIGTERM
  747. sigterm := make(chan os.Signal, 1)
  748. signal.Notify(sigterm, syscall.SIGTERM)
  749. go func() {
  750. <-sigterm
  751. logger.Info("Received sigterm. exiting.")
  752. rootCtxCancel()
  753. }()
  754. usingLoki := *telemetryLokiURL != ""
  755. var hasTelemetryCredential bool = usingLoki
  756. // Telemetry is enabled by default in mainnet/testnet. In devnet it is disabled by default
  757. if !*disableTelemetry && (!*unsafeDevMode || *unsafeDevMode && hasTelemetryCredential) {
  758. if !hasTelemetryCredential {
  759. logger.Fatal("Please specify --telemetryLokiURL or set --disableTelemetry=false")
  760. }
  761. // Get libp2p peer ID from private key
  762. pk := p2pKey.GetPublic()
  763. peerID, err := peer.IDFromPublicKey(pk)
  764. if err != nil {
  765. logger.Fatal("Failed to get peer ID from private key", zap.Error(err))
  766. }
  767. labels := map[string]string{
  768. "node_name": *nodeName,
  769. "node_key": peerID.Pretty(),
  770. "guardian_addr": ethcrypto.PubkeyToAddress(gk.PublicKey).String(),
  771. "network": *p2pNetworkID,
  772. "version": version.Version(),
  773. }
  774. skipPrivateLogs := !*publicRpcLogToTelemetry
  775. var tm *telemetry.Telemetry
  776. if usingLoki {
  777. logger.Info("Using Loki telemetry logger",
  778. zap.String("publicRpcLogDetail", *publicRpcLogDetailStr),
  779. zap.Bool("logPublicRpcToTelemetry", *publicRpcLogToTelemetry))
  780. tm, err = telemetry.NewLokiCloudLogger(context.Background(), logger, *telemetryLokiURL, "wormhole", skipPrivateLogs, labels)
  781. if err != nil {
  782. logger.Fatal("Failed to initialize telemetry", zap.Error(err))
  783. }
  784. }
  785. defer tm.Close()
  786. logger = tm.WrapLogger(logger) // Wrap logger with telemetry logger
  787. }
  788. // log golang version
  789. logger.Info("golang version", zap.String("golang_version", runtime.Version()))
  790. // Redirect ipfs logs to plain zap
  791. ipfslog.SetPrimaryCore(logger.Core())
  792. wormchainId := "wormchain"
  793. if *testnetMode {
  794. wormchainId = "wormchain-testnet-0"
  795. }
  796. var accountantWormchainConn *wormconn.ClientConn
  797. if *accountantContract != "" {
  798. // TODO: wormchainKeyPath and wormchainKeyPassPhrase are being replaced by accountantKeyPath and accountantKeyPassPhrase.
  799. // Give the guardians time to migrate off of the old parameters, but then remove them.
  800. keyPath := *accountantKeyPath
  801. if keyPath == "" {
  802. if *wormchainKeyPath == "" {
  803. logger.Fatal("if accountantContract is specified, accountantKeyPath is required", zap.String("component", "gacct"))
  804. }
  805. logger.Error("the wormchainKeyPath parameter is deprecated, please change to accountantKeyPath", zap.String("component", "gacct"))
  806. keyPath = *wormchainKeyPath
  807. } else if *wormchainKeyPath != "" {
  808. logger.Fatal("the wormchainKeyPath parameter is obsolete, please remove it", zap.String("component", "gacct"))
  809. }
  810. keyPassPhrase := *accountantKeyPassPhrase
  811. if keyPassPhrase == "" {
  812. if *wormchainKeyPassPhrase == "" {
  813. logger.Fatal("if accountantContract is specified, accountantKeyPassPhrase is required", zap.String("component", "gacct"))
  814. }
  815. logger.Error("the wormchainKeyPassPhrase parameter is deprecated, please change to accountantKeyPassPhrase", zap.String("component", "gacct"))
  816. keyPassPhrase = *wormchainKeyPassPhrase
  817. } else if *wormchainKeyPassPhrase != "" {
  818. logger.Fatal("the wormchainKeyPassPhrase parameter is obsolete, please remove it", zap.String("component", "gacct"))
  819. }
  820. keyPathName := keyPath
  821. if *unsafeDevMode {
  822. idx, err := devnet.GetDevnetIndex()
  823. if err != nil {
  824. logger.Fatal("failed to get devnet index", zap.Error(err), zap.String("component", "gacct"))
  825. }
  826. keyPathName = fmt.Sprint(keyPath, idx)
  827. }
  828. wormchainKey, err := wormconn.LoadWormchainPrivKey(keyPathName, keyPassPhrase)
  829. if err != nil {
  830. logger.Fatal("failed to load wormchain private key", zap.Error(err), zap.String("component", "gacct"))
  831. }
  832. // Connect to wormchain.
  833. logger.Info("Connecting to wormchain", zap.String("wormchainURL", *wormchainURL), zap.String("keyPath", keyPathName), zap.String("component", "gacct"))
  834. accountantWormchainConn, err = wormconn.NewConn(rootCtx, *wormchainURL, wormchainKey, wormchainId)
  835. if err != nil {
  836. logger.Fatal("failed to connect to wormchain", zap.Error(err), zap.String("component", "gacct"))
  837. }
  838. }
  839. var gatewayRelayerWormchainConn *wormconn.ClientConn
  840. if *gatewayRelayerContract != "" {
  841. if *wormchainURL == "" {
  842. logger.Fatal("if gatewayRelayerContract is specified, wormchainURL is required", zap.String("component", "gwrelayer"))
  843. }
  844. if *gatewayRelayerKeyPath == "" {
  845. logger.Fatal("if gatewayRelayerContract is specified, gatewayRelayerKeyPath is required", zap.String("component", "gwrelayer"))
  846. }
  847. if *gatewayRelayerKeyPassPhrase == "" {
  848. logger.Fatal("if gatewayRelayerContract is specified, gatewayRelayerKeyPassPhrase is required", zap.String("component", "gwrelayer"))
  849. }
  850. wormchainKeyPathName := *gatewayRelayerKeyPath
  851. if *unsafeDevMode {
  852. idx, err := devnet.GetDevnetIndex()
  853. if err != nil {
  854. logger.Fatal("failed to get devnet index", zap.Error(err), zap.String("component", "gwrelayer"))
  855. }
  856. wormchainKeyPathName = fmt.Sprint(*gatewayRelayerKeyPath, idx)
  857. }
  858. wormchainKey, err := wormconn.LoadWormchainPrivKey(wormchainKeyPathName, *gatewayRelayerKeyPassPhrase)
  859. if err != nil {
  860. logger.Fatal("failed to load private key", zap.Error(err), zap.String("component", "gwrelayer"))
  861. }
  862. logger.Info("Connecting to wormchain", zap.String("wormchainURL", *wormchainURL), zap.String("keyPath", wormchainKeyPathName), zap.String("component", "gwrelayer"))
  863. gatewayRelayerWormchainConn, err = wormconn.NewConn(rootCtx, *wormchainURL, wormchainKey, wormchainId)
  864. if err != nil {
  865. logger.Fatal("failed to connect to wormchain", zap.Error(err), zap.String("component", "gwrelayer"))
  866. }
  867. }
  868. usingPromRemoteWrite := *promRemoteURL != ""
  869. if usingPromRemoteWrite {
  870. var info promremotew.PromTelemetryInfo
  871. info.PromRemoteURL = *promRemoteURL
  872. info.Labels = map[string]string{
  873. "node_name": *nodeName,
  874. "guardian_addr": ethcrypto.PubkeyToAddress(gk.PublicKey).String(),
  875. "network": *p2pNetworkID,
  876. "version": version.Version(),
  877. "product": "wormhole",
  878. }
  879. promLogger := logger.With(zap.String("component", "prometheus_scraper"))
  880. errC := make(chan error)
  881. common.StartRunnable(rootCtx, errC, false, "prometheus_scraper", func(ctx context.Context) error {
  882. t := time.NewTicker(15 * time.Second)
  883. for {
  884. select {
  885. case <-ctx.Done():
  886. return nil
  887. case <-t.C:
  888. err := promremotew.ScrapeAndSendLocalMetrics(ctx, info, promLogger)
  889. if err != nil {
  890. promLogger.Error("ScrapeAndSendLocalMetrics error", zap.Error(err))
  891. continue
  892. }
  893. }
  894. }
  895. })
  896. }
  897. var watcherConfigs = []watchers.WatcherConfig{}
  898. if shouldStart(ethRPC) {
  899. wc := &evm.WatcherConfig{
  900. NetworkID: "eth",
  901. ChainID: vaa.ChainIDEthereum,
  902. Rpc: *ethRPC,
  903. Contract: *ethContract,
  904. GuardianSetUpdateChain: true,
  905. }
  906. watcherConfigs = append(watcherConfigs, wc)
  907. }
  908. if shouldStart(bscRPC) {
  909. wc := &evm.WatcherConfig{
  910. NetworkID: "bsc",
  911. ChainID: vaa.ChainIDBSC,
  912. Rpc: *bscRPC,
  913. Contract: *bscContract,
  914. }
  915. watcherConfigs = append(watcherConfigs, wc)
  916. }
  917. if shouldStart(polygonRPC) {
  918. wc := &evm.WatcherConfig{
  919. NetworkID: "polygon",
  920. ChainID: vaa.ChainIDPolygon,
  921. Rpc: *polygonRPC,
  922. Contract: *polygonContract,
  923. }
  924. watcherConfigs = append(watcherConfigs, wc)
  925. }
  926. if shouldStart(avalancheRPC) {
  927. wc := &evm.WatcherConfig{
  928. NetworkID: "avalanche",
  929. ChainID: vaa.ChainIDAvalanche,
  930. Rpc: *avalancheRPC,
  931. Contract: *avalancheContract,
  932. }
  933. watcherConfigs = append(watcherConfigs, wc)
  934. }
  935. if shouldStart(oasisRPC) {
  936. wc := &evm.WatcherConfig{
  937. NetworkID: "oasis",
  938. ChainID: vaa.ChainIDOasis,
  939. Rpc: *oasisRPC,
  940. Contract: *oasisContract,
  941. }
  942. watcherConfigs = append(watcherConfigs, wc)
  943. }
  944. if shouldStart(auroraRPC) {
  945. wc := &evm.WatcherConfig{
  946. NetworkID: "aurora",
  947. ChainID: vaa.ChainIDAurora,
  948. Rpc: *auroraRPC,
  949. Contract: *auroraContract,
  950. }
  951. watcherConfigs = append(watcherConfigs, wc)
  952. }
  953. if shouldStart(fantomRPC) {
  954. wc := &evm.WatcherConfig{
  955. NetworkID: "fantom",
  956. ChainID: vaa.ChainIDFantom,
  957. Rpc: *fantomRPC,
  958. Contract: *fantomContract,
  959. }
  960. watcherConfigs = append(watcherConfigs, wc)
  961. }
  962. if shouldStart(karuraRPC) {
  963. wc := &evm.WatcherConfig{
  964. NetworkID: "karura",
  965. ChainID: vaa.ChainIDKarura,
  966. Rpc: *karuraRPC,
  967. Contract: *karuraContract,
  968. }
  969. watcherConfigs = append(watcherConfigs, wc)
  970. }
  971. if shouldStart(acalaRPC) {
  972. wc := &evm.WatcherConfig{
  973. NetworkID: "acala",
  974. ChainID: vaa.ChainIDAcala,
  975. Rpc: *acalaRPC,
  976. Contract: *acalaContract,
  977. }
  978. watcherConfigs = append(watcherConfigs, wc)
  979. }
  980. if shouldStart(klaytnRPC) {
  981. wc := &evm.WatcherConfig{
  982. NetworkID: "klaytn",
  983. ChainID: vaa.ChainIDKlaytn,
  984. Rpc: *klaytnRPC,
  985. Contract: *klaytnContract,
  986. }
  987. watcherConfigs = append(watcherConfigs, wc)
  988. }
  989. if shouldStart(celoRPC) {
  990. wc := &evm.WatcherConfig{
  991. NetworkID: "celo",
  992. ChainID: vaa.ChainIDCelo,
  993. Rpc: *celoRPC,
  994. Contract: *celoContract,
  995. }
  996. watcherConfigs = append(watcherConfigs, wc)
  997. }
  998. if shouldStart(moonbeamRPC) {
  999. wc := &evm.WatcherConfig{
  1000. NetworkID: "moonbeam",
  1001. ChainID: vaa.ChainIDMoonbeam,
  1002. Rpc: *moonbeamRPC,
  1003. Contract: *moonbeamContract,
  1004. }
  1005. watcherConfigs = append(watcherConfigs, wc)
  1006. }
  1007. if shouldStart(arbitrumRPC) {
  1008. wc := &evm.WatcherConfig{
  1009. NetworkID: "arbitrum",
  1010. ChainID: vaa.ChainIDArbitrum,
  1011. Rpc: *arbitrumRPC,
  1012. Contract: *arbitrumContract,
  1013. L1FinalizerRequired: "eth",
  1014. }
  1015. watcherConfigs = append(watcherConfigs, wc)
  1016. }
  1017. if shouldStart(optimismRPC) {
  1018. wc := &evm.WatcherConfig{
  1019. NetworkID: "optimism",
  1020. ChainID: vaa.ChainIDOptimism,
  1021. Rpc: *optimismRPC,
  1022. Contract: *optimismContract,
  1023. }
  1024. watcherConfigs = append(watcherConfigs, wc)
  1025. }
  1026. if shouldStart(baseRPC) {
  1027. wc := &evm.WatcherConfig{
  1028. NetworkID: "base",
  1029. ChainID: vaa.ChainIDBase,
  1030. Rpc: *baseRPC,
  1031. Contract: *baseContract,
  1032. }
  1033. watcherConfigs = append(watcherConfigs, wc)
  1034. }
  1035. if shouldStart(scrollRPC) {
  1036. wc := &evm.WatcherConfig{
  1037. NetworkID: "scroll",
  1038. ChainID: vaa.ChainIDScroll,
  1039. Rpc: *scrollRPC,
  1040. Contract: *scrollContract,
  1041. }
  1042. watcherConfigs = append(watcherConfigs, wc)
  1043. }
  1044. if shouldStart(terraWS) {
  1045. wc := &cosmwasm.WatcherConfig{
  1046. NetworkID: "terra",
  1047. ChainID: vaa.ChainIDTerra,
  1048. Websocket: *terraWS,
  1049. Lcd: *terraLCD,
  1050. Contract: *terraContract,
  1051. }
  1052. watcherConfigs = append(watcherConfigs, wc)
  1053. }
  1054. if shouldStart(terra2WS) {
  1055. wc := &cosmwasm.WatcherConfig{
  1056. NetworkID: "terra2",
  1057. ChainID: vaa.ChainIDTerra2,
  1058. Websocket: *terra2WS,
  1059. Lcd: *terra2LCD,
  1060. Contract: *terra2Contract,
  1061. }
  1062. watcherConfigs = append(watcherConfigs, wc)
  1063. }
  1064. if shouldStart(xplaWS) {
  1065. wc := &cosmwasm.WatcherConfig{
  1066. NetworkID: "xpla",
  1067. ChainID: vaa.ChainIDXpla,
  1068. Websocket: *xplaWS,
  1069. Lcd: *xplaLCD,
  1070. Contract: *xplaContract,
  1071. }
  1072. watcherConfigs = append(watcherConfigs, wc)
  1073. }
  1074. if shouldStart(injectiveWS) {
  1075. wc := &cosmwasm.WatcherConfig{
  1076. NetworkID: "injective",
  1077. ChainID: vaa.ChainIDInjective,
  1078. Websocket: *injectiveWS,
  1079. Lcd: *injectiveLCD,
  1080. Contract: *injectiveContract,
  1081. }
  1082. watcherConfigs = append(watcherConfigs, wc)
  1083. }
  1084. if shouldStart(algorandIndexerRPC) {
  1085. wc := &algorand.WatcherConfig{
  1086. NetworkID: "algorand",
  1087. ChainID: vaa.ChainIDAlgorand,
  1088. IndexerRPC: *algorandIndexerRPC,
  1089. IndexerToken: *algorandIndexerToken,
  1090. AlgodRPC: *algorandAlgodRPC,
  1091. AlgodToken: *algorandAlgodToken,
  1092. AppID: *algorandAppID,
  1093. }
  1094. watcherConfigs = append(watcherConfigs, wc)
  1095. }
  1096. if shouldStart(nearRPC) {
  1097. wc := &near.WatcherConfig{
  1098. NetworkID: "near",
  1099. ChainID: vaa.ChainIDNear,
  1100. Rpc: *nearRPC,
  1101. Contract: *nearContract,
  1102. }
  1103. watcherConfigs = append(watcherConfigs, wc)
  1104. }
  1105. if shouldStart(aptosRPC) {
  1106. wc := &aptos.WatcherConfig{
  1107. NetworkID: "aptos",
  1108. ChainID: vaa.ChainIDAptos,
  1109. Rpc: *aptosRPC,
  1110. Account: *aptosAccount,
  1111. Handle: *aptosHandle,
  1112. }
  1113. watcherConfigs = append(watcherConfigs, wc)
  1114. }
  1115. if shouldStart(suiRPC) {
  1116. wc := &sui.WatcherConfig{
  1117. NetworkID: "sui",
  1118. ChainID: vaa.ChainIDSui,
  1119. Rpc: *suiRPC,
  1120. Websocket: *suiWS,
  1121. SuiMoveEventType: *suiMoveEventType,
  1122. }
  1123. watcherConfigs = append(watcherConfigs, wc)
  1124. }
  1125. if shouldStart(solanaRPC) {
  1126. // confirmed watcher
  1127. wc := &solana.WatcherConfig{
  1128. NetworkID: "solana-confirmed",
  1129. ChainID: vaa.ChainIDSolana,
  1130. Rpc: *solanaRPC,
  1131. Websocket: "",
  1132. Contract: *solanaContract,
  1133. ReceiveObsReq: false,
  1134. Commitment: rpc.CommitmentConfirmed,
  1135. }
  1136. watcherConfigs = append(watcherConfigs, wc)
  1137. // finalized watcher
  1138. wc = &solana.WatcherConfig{
  1139. NetworkID: "solana-finalized",
  1140. ChainID: vaa.ChainIDSolana,
  1141. Rpc: *solanaRPC,
  1142. Websocket: "",
  1143. Contract: *solanaContract,
  1144. ReceiveObsReq: true,
  1145. Commitment: rpc.CommitmentFinalized,
  1146. }
  1147. watcherConfigs = append(watcherConfigs, wc)
  1148. }
  1149. if shouldStart(pythnetRPC) {
  1150. wc := &solana.WatcherConfig{
  1151. NetworkID: "pythnet",
  1152. ChainID: vaa.ChainIDPythNet,
  1153. Rpc: *pythnetRPC,
  1154. Websocket: *pythnetWS,
  1155. Contract: *pythnetContract,
  1156. ReceiveObsReq: false,
  1157. Commitment: rpc.CommitmentConfirmed,
  1158. }
  1159. watcherConfigs = append(watcherConfigs, wc)
  1160. }
  1161. if shouldStart(gatewayWS) {
  1162. wc := &cosmwasm.WatcherConfig{
  1163. NetworkID: "gateway",
  1164. ChainID: vaa.ChainIDWormchain,
  1165. Websocket: *gatewayWS,
  1166. Lcd: *gatewayLCD,
  1167. Contract: *gatewayContract,
  1168. }
  1169. watcherConfigs = append(watcherConfigs, wc)
  1170. }
  1171. if *testnetMode {
  1172. if shouldStart(neonRPC) {
  1173. if !shouldStart(solanaRPC) {
  1174. log.Fatalf("If neon is enabled then solana must also be enabled.")
  1175. }
  1176. wc := &evm.WatcherConfig{
  1177. NetworkID: "neon",
  1178. ChainID: vaa.ChainIDNeon,
  1179. Rpc: *neonRPC,
  1180. Contract: *neonContract,
  1181. L1FinalizerRequired: "solana-finalized",
  1182. }
  1183. watcherConfigs = append(watcherConfigs, wc)
  1184. }
  1185. if shouldStart(sepoliaRPC) {
  1186. wc := &evm.WatcherConfig{
  1187. NetworkID: "sepolia",
  1188. ChainID: vaa.ChainIDSepolia,
  1189. Rpc: *sepoliaRPC,
  1190. Contract: *sepoliaContract,
  1191. }
  1192. watcherConfigs = append(watcherConfigs, wc)
  1193. }
  1194. }
  1195. var ibcWatcherConfig *node.IbcWatcherConfig = nil
  1196. if shouldStart(ibcWS) {
  1197. ibcWatcherConfig = &node.IbcWatcherConfig{
  1198. Websocket: *ibcWS,
  1199. Lcd: *ibcLCD,
  1200. BlockHeightURL: *ibcBlockHeightURL,
  1201. Contract: *ibcContract,
  1202. }
  1203. }
  1204. guardianNode := node.NewGuardianNode(
  1205. env,
  1206. gk,
  1207. )
  1208. guardianOptions := []*node.GuardianOption{
  1209. node.GuardianOptionDatabase(db),
  1210. node.GuardianOptionWatchers(watcherConfigs, ibcWatcherConfig),
  1211. node.GuardianOptionAccountant(*accountantContract, *accountantWS, *accountantCheckEnabled, accountantWormchainConn),
  1212. node.GuardianOptionGovernor(*chainGovernorEnabled),
  1213. node.GuardianOptionGatewayRelayer(*gatewayRelayerContract, gatewayRelayerWormchainConn),
  1214. node.GuardianOptionQueryHandler(*ccqEnabled, *ccqAllowedRequesters),
  1215. node.GuardianOptionAdminService(*adminSocketPath, ethRPC, ethContract, rpcMap),
  1216. node.GuardianOptionP2P(p2pKey, *p2pNetworkID, *p2pBootstrap, *nodeName, *disableHeartbeatVerify, *p2pPort, *ccqP2pBootstrap, *ccqP2pPort, *ccqAllowedPeers, ibc.GetFeatures),
  1217. node.GuardianOptionStatusServer(*statusAddr),
  1218. node.GuardianOptionProcessor(),
  1219. }
  1220. if shouldStart(publicGRPCSocketPath) {
  1221. guardianOptions = append(guardianOptions, node.GuardianOptionPublicRpcSocket(*publicGRPCSocketPath, publicRpcLogDetail))
  1222. if shouldStart(publicRPC) {
  1223. guardianOptions = append(guardianOptions, node.GuardianOptionPublicrpcTcpService(*publicRPC, publicRpcLogDetail))
  1224. }
  1225. if shouldStart(publicWeb) {
  1226. guardianOptions = append(guardianOptions,
  1227. node.GuardianOptionPublicWeb(*publicWeb, *publicGRPCSocketPath, *tlsHostname, *tlsProdEnv, path.Join(*dataDir, "autocert")),
  1228. )
  1229. }
  1230. }
  1231. // Run supervisor with Guardian Node as root.
  1232. supervisor.New(rootCtx, logger, guardianNode.Run(rootCtxCancel, guardianOptions...),
  1233. // It's safer to crash and restart the process in case we encounter a panic,
  1234. // rather than attempting to reschedule the runnable.
  1235. supervisor.WithPropagatePanic)
  1236. <-rootCtx.Done()
  1237. logger.Info("root context cancelled, exiting...")
  1238. }
  1239. func shouldStart(rpc *string) bool {
  1240. return *rpc != "" && *rpc != "none"
  1241. }
  1242. func unsafeDevModeEvmContractAddress(contractAddr string) string {
  1243. if contractAddr != "" {
  1244. return contractAddr
  1245. }
  1246. return devnet.GanacheWormholeContractAddress.Hex()
  1247. }