node.go 57 KB

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