2020-10-28 14:41:38 -07:00
package guardiand
2020-08-02 14:12:58 -07:00
import (
"context"
2022-01-09 12:56:59 -08:00
"encoding/base64"
2022-02-08 14:16:43 -08:00
"encoding/hex"
2020-08-02 14:12:58 -07:00
"fmt"
2022-05-23 02:25:24 -07:00
"log"
"net/http"
_ "net/http/pprof" // #nosec G108 we are using a custom router (`router := mux.NewRouter()`) and thus not automatically expose pprof.
"os"
"path"
"strings"
2021-12-02 16:02:32 -08:00
"github.com/certusone/wormhole/node/pkg/db"
2021-10-05 11:13:07 -07:00
"github.com/certusone/wormhole/node/pkg/notify/discord"
2022-01-09 12:56:59 -08:00
"github.com/certusone/wormhole/node/pkg/telemetry"
"github.com/certusone/wormhole/node/pkg/version"
2021-12-02 16:02:32 -08:00
"github.com/gagliardetto/solana-go/rpc"
2022-01-06 08:58:56 -08:00
"go.uber.org/zap/zapcore"
2021-08-06 21:28:46 -07:00
2021-07-28 06:56:19 -07:00
solana_types "github.com/gagliardetto/solana-go"
2021-02-04 02:26:01 -08:00
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus/promhttp"
2021-08-26 01:35:09 -07:00
"github.com/certusone/wormhole/node/pkg/common"
"github.com/certusone/wormhole/node/pkg/devnet"
"github.com/certusone/wormhole/node/pkg/ethereum"
"github.com/certusone/wormhole/node/pkg/p2p"
"github.com/certusone/wormhole/node/pkg/processor"
gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
"github.com/certusone/wormhole/node/pkg/readiness"
"github.com/certusone/wormhole/node/pkg/reporter"
solana "github.com/certusone/wormhole/node/pkg/solana"
"github.com/certusone/wormhole/node/pkg/supervisor"
"github.com/certusone/wormhole/node/pkg/vaa"
2021-12-02 16:02:32 -08:00
eth_common "github.com/ethereum/go-ethereum/common"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/spf13/cobra"
"go.uber.org/zap"
2021-08-26 01:35:09 -07:00
"github.com/certusone/wormhole/node/pkg/terra"
2020-11-16 04:28:07 -08:00
2021-12-22 08:22:04 -08:00
"github.com/certusone/wormhole/node/pkg/algorand"
2020-08-02 14:12:58 -07:00
ipfslog "github.com/ipfs/go-log/v2"
)
var (
2020-10-28 14:41:38 -07:00
p2pNetworkID * string
p2pPort * uint
p2pBootstrap * string
2020-08-16 08:05:58 -07:00
2020-10-28 14:41:38 -07:00
nodeKeyPath * string
2020-08-16 08:05:58 -07:00
2020-11-19 03:53:19 -08:00
adminSocketPath * string
2021-07-21 11:56:25 -07:00
dataDir * string
2021-01-24 08:20:04 -08:00
statusAddr * string
2021-08-30 07:19:00 -07:00
guardianKeyPath * string
solanaContract * string
2020-11-19 03:53:17 -08:00
2021-07-09 05:56:52 -07:00
ethRPC * string
ethContract * string
2020-08-16 08:05:58 -07:00
2021-07-28 06:32:49 -07:00
bscRPC * string
bscContract * string
2022-05-25 23:53:47 -07:00
polygonRPC * string
polygonContract * string
polygonCheckpoint * string
2021-10-18 08:53:13 -07:00
2021-11-22 07:49:41 -08:00
ethRopstenRPC * string
ethRopstenContract * string
2022-03-15 07:41:10 -07:00
auroraRPC * string
auroraContract * string
2022-03-03 13:40:32 -08:00
fantomRPC * string
fantomContract * string
2022-02-02 09:50:10 -08:00
2021-12-09 13:40:55 -08:00
avalancheRPC * string
avalancheContract * string
2021-12-20 11:40:58 -08:00
oasisRPC * string
oasisContract * string
2022-03-03 13:40:32 -08:00
karuraRPC * string
karuraContract * string
acalaRPC * string
acalaContract * string
2022-04-04 15:11:03 -07:00
klaytnRPC * string
klaytnContract * string
2022-04-28 09:20:38 -07:00
celoRPC * string
celoContract * string
2022-05-10 08:23:07 -07:00
moonbeamRPC * string
moonbeamContract * string
2020-11-16 04:28:07 -08:00
terraWS * string
terraLCD * string
terraContract * string
2022-04-29 12:56:08 -07:00
algorandIndexerRPC * string
algorandIndexerToken * string
2022-05-10 04:41:59 -07:00
algorandAlgodRPC * string
algorandAlgodToken * string
2022-05-10 08:23:07 -07:00
algorandAppID * uint64
2021-12-22 08:22:04 -08:00
2021-01-21 02:31:32 -08:00
solanaWsRPC * string
solanaRPC * string
2020-10-28 14:41:38 -07:00
logLevel * string
2020-08-17 09:20:15 -07:00
2020-10-28 14:41:38 -07:00
unsafeDevMode * bool
2021-11-22 07:49:41 -08:00
testnetMode * bool
2020-10-28 14:41:38 -07:00
devNumGuardians * uint
nodeName * string
2021-05-12 22:57:08 -07:00
2021-08-20 16:52:07 -07:00
publicRPC * string
publicWeb * string
2021-07-07 02:39:48 -07:00
2021-08-20 15:44:37 -07:00
tlsHostname * string
tlsProdEnv * bool
2021-08-05 08:01:36 -07:00
disableHeartbeatVerify * bool
2022-01-09 12:56:59 -08:00
disableTelemetry * bool
telemetryKey * string
2021-08-05 08:01:36 -07:00
2021-10-05 11:13:07 -07:00
discordToken * string
discordChannel * string
2021-07-07 02:39:48 -07:00
bigTablePersistenceEnabled * bool
bigTableGCPProject * string
bigTableInstanceName * string
bigTableTableName * string
2021-11-04 02:00:52 -07:00
bigTableTopicName * string
2021-07-07 02:39:48 -07:00
bigTableKeyPath * string
2020-08-02 14:12:58 -07:00
)
2020-10-28 14:41:38 -07:00
func init ( ) {
2021-08-30 07:19:00 -07:00
p2pNetworkID = NodeCmd . Flags ( ) . String ( "network" , "/wormhole/dev" , "P2P network identifier" )
p2pPort = NodeCmd . Flags ( ) . Uint ( "port" , 8999 , "P2P UDP listener port" )
p2pBootstrap = NodeCmd . Flags ( ) . String ( "bootstrap" , "" , "P2P bootstrap peers (comma-separated)" )
2020-10-28 14:41:38 -07:00
2021-08-30 07:19:00 -07:00
statusAddr = NodeCmd . Flags ( ) . String ( "statusAddr" , "[::]:6060" , "Listen address for status server (disabled if blank)" )
2021-01-24 08:20:04 -08:00
2021-08-30 07:19:00 -07:00
nodeKeyPath = NodeCmd . Flags ( ) . String ( "nodeKey" , "" , "Path to node key (will be generated if it doesn't exist)" )
2020-10-28 14:41:38 -07:00
2021-08-30 07:19:00 -07:00
adminSocketPath = NodeCmd . Flags ( ) . String ( "adminSocket" , "" , "Admin gRPC service UNIX domain socket path" )
2020-11-19 03:53:19 -08:00
2021-08-30 07:19:00 -07:00
dataDir = NodeCmd . Flags ( ) . String ( "dataDir" , "" , "Data directory" )
2021-07-21 11:56:25 -07:00
2021-08-30 07:19:00 -07:00
guardianKeyPath = NodeCmd . Flags ( ) . String ( "guardianKey" , "" , "Path to guardian key (required)" )
solanaContract = NodeCmd . Flags ( ) . String ( "solanaContract" , "" , "Address of the Solana program (required)" )
2020-11-19 03:53:17 -08:00
2021-08-30 07:19:00 -07:00
ethRPC = NodeCmd . Flags ( ) . String ( "ethRPC" , "" , "Ethereum RPC URL" )
ethContract = NodeCmd . Flags ( ) . String ( "ethContract" , "" , "Ethereum contract address" )
2020-10-28 14:41:38 -07:00
2021-08-30 07:19:00 -07:00
bscRPC = NodeCmd . Flags ( ) . String ( "bscRPC" , "" , "Binance Smart Chain RPC URL" )
bscContract = NodeCmd . Flags ( ) . String ( "bscContract" , "" , "Binance Smart Chain contract address" )
2021-07-28 06:32:49 -07:00
2021-10-18 08:53:13 -07:00
polygonRPC = NodeCmd . Flags ( ) . String ( "polygonRPC" , "" , "Polygon RPC URL" )
polygonContract = NodeCmd . Flags ( ) . String ( "polygonContract" , "" , "Polygon contract address" )
2022-05-25 23:53:47 -07:00
polygonCheckpoint = NodeCmd . Flags ( ) . String ( "polygonCheckpoint" , "" , "Polygon checkpoint query URL" )
2021-10-18 08:53:13 -07:00
2021-11-22 07:49:41 -08:00
ethRopstenRPC = NodeCmd . Flags ( ) . String ( "ethRopstenRPC" , "" , "Ethereum Ropsten RPC URL" )
ethRopstenContract = NodeCmd . Flags ( ) . String ( "ethRopstenContract" , "" , "Ethereum Ropsten contract address" )
2021-12-09 13:40:55 -08:00
avalancheRPC = NodeCmd . Flags ( ) . String ( "avalancheRPC" , "" , "Avalanche RPC URL" )
avalancheContract = NodeCmd . Flags ( ) . String ( "avalancheContract" , "" , "Avalanche contract address" )
2021-12-20 11:40:58 -08:00
oasisRPC = NodeCmd . Flags ( ) . String ( "oasisRPC" , "" , "Oasis RPC URL" )
oasisContract = NodeCmd . Flags ( ) . String ( "oasisContract" , "" , "Oasis contract address" )
2022-03-15 07:41:10 -07:00
auroraRPC = NodeCmd . Flags ( ) . String ( "auroraRPC" , "" , "Aurora Websocket RPC URL" )
auroraContract = NodeCmd . Flags ( ) . String ( "auroraContract" , "" , "Aurora contract address" )
2022-02-02 09:50:10 -08:00
fantomRPC = NodeCmd . Flags ( ) . String ( "fantomRPC" , "" , "Fantom Websocket RPC URL" )
fantomContract = NodeCmd . Flags ( ) . String ( "fantomContract" , "" , "Fantom contract address" )
2022-03-03 13:40:32 -08:00
karuraRPC = NodeCmd . Flags ( ) . String ( "karuraRPC" , "" , "Karura RPC URL" )
karuraContract = NodeCmd . Flags ( ) . String ( "karuraContract" , "" , "Karura contract address" )
acalaRPC = NodeCmd . Flags ( ) . String ( "acalaRPC" , "" , "Acala RPC URL" )
acalaContract = NodeCmd . Flags ( ) . String ( "acalaContract" , "" , "Acala contract address" )
2022-04-04 15:11:03 -07:00
klaytnRPC = NodeCmd . Flags ( ) . String ( "klaytnRPC" , "" , "Klaytn RPC URL" )
klaytnContract = NodeCmd . Flags ( ) . String ( "klaytnContract" , "" , "Klaytn contract address" )
2022-04-28 09:20:38 -07:00
celoRPC = NodeCmd . Flags ( ) . String ( "celoRPC" , "" , "Celo RPC URL" )
celoContract = NodeCmd . Flags ( ) . String ( "celoContract" , "" , "Celo contract address" )
2022-05-10 08:23:07 -07:00
moonbeamRPC = NodeCmd . Flags ( ) . String ( "moonbeamRPC" , "" , "Moonbeam RPC URL" )
moonbeamContract = NodeCmd . Flags ( ) . String ( "moonbeamContract" , "" , "Moonbeam contract address" )
2021-08-30 07:19:00 -07:00
terraWS = NodeCmd . Flags ( ) . String ( "terraWS" , "" , "Path to terrad root for websocket connection" )
terraLCD = NodeCmd . Flags ( ) . String ( "terraLCD" , "" , "Path to LCD service root for http calls" )
terraContract = NodeCmd . Flags ( ) . String ( "terraContract" , "" , "Wormhole contract address on Terra blockchain" )
2020-11-16 04:28:07 -08:00
2022-04-29 12:56:08 -07:00
algorandIndexerRPC = NodeCmd . Flags ( ) . String ( "algorandIndexerRPC" , "" , "Algorand Indexer RPC URL" )
algorandIndexerToken = NodeCmd . Flags ( ) . String ( "algorandIndexerToken" , "" , "Algorand Indexer access token" )
2022-05-10 04:41:59 -07:00
algorandAlgodRPC = NodeCmd . Flags ( ) . String ( "algorandAlgodRPC" , "" , "Algorand Algod RPC URL" )
algorandAlgodToken = NodeCmd . Flags ( ) . String ( "algorandAlgodToken" , "" , "Algorand Algod access token" )
2022-04-29 12:56:08 -07:00
algorandAppID = NodeCmd . Flags ( ) . Uint64 ( "algorandAppID" , 0 , "Algorand app id" )
2021-12-22 08:22:04 -08:00
2021-08-30 07:19:00 -07:00
solanaWsRPC = NodeCmd . Flags ( ) . String ( "solanaWS" , "" , "Solana Websocket URL (required" )
solanaRPC = NodeCmd . Flags ( ) . String ( "solanaRPC" , "" , "Solana RPC URL (required" )
2021-01-21 02:31:32 -08:00
2021-08-30 07:19:00 -07:00
logLevel = NodeCmd . Flags ( ) . String ( "logLevel" , "info" , "Logging level (debug, info, warn, error, dpanic, panic, fatal)" )
2020-10-28 14:41:38 -07:00
2021-08-30 07:19:00 -07:00
unsafeDevMode = NodeCmd . Flags ( ) . Bool ( "unsafeDevMode" , false , "Launch node in unsafe, deterministic devnet mode" )
2021-11-22 07:49:41 -08:00
testnetMode = NodeCmd . Flags ( ) . Bool ( "testnetMode" , false , "Launch node in testnet mode (enables testnet-only features like Ropsten)" )
2021-08-30 07:19:00 -07:00
devNumGuardians = NodeCmd . Flags ( ) . Uint ( "devNumGuardians" , 5 , "Number of devnet guardians to include in guardian set" )
nodeName = NodeCmd . Flags ( ) . String ( "nodeName" , "" , "Node name to announce in gossip heartbeats" )
2021-05-12 22:57:08 -07:00
2021-08-30 07:19:00 -07:00
publicRPC = NodeCmd . Flags ( ) . String ( "publicRPC" , "" , "Listen address for public gRPC interface" )
publicWeb = NodeCmd . Flags ( ) . String ( "publicWeb" , "" , "Listen address for public REST and gRPC Web interface" )
2021-08-20 15:44:37 -07:00
2021-08-30 07:19:00 -07:00
tlsHostname = NodeCmd . Flags ( ) . String ( "tlsHostname" , "" , "If set, serve publicWeb as TLS with this hostname using Let's Encrypt" )
tlsProdEnv = NodeCmd . Flags ( ) . Bool ( "tlsProdEnv" , false ,
2021-08-20 15:44:37 -07:00
"Use the production Let's Encrypt environment instead of staging" )
2021-07-07 02:39:48 -07:00
2021-08-30 07:19:00 -07:00
disableHeartbeatVerify = NodeCmd . Flags ( ) . Bool ( "disableHeartbeatVerify" , false ,
2021-08-05 08:01:36 -07:00
"Disable heartbeat signature verification (useful during network startup)" )
2022-01-09 12:56:59 -08:00
disableTelemetry = NodeCmd . Flags ( ) . Bool ( "disableTelemetry" , false ,
"Disable telemetry" )
telemetryKey = NodeCmd . Flags ( ) . String ( "telemetryKey" , "" ,
"Telemetry write key" )
2021-08-05 08:01:36 -07:00
2021-10-05 11:13:07 -07:00
discordToken = NodeCmd . Flags ( ) . String ( "discordToken" , "" , "Discord bot token (optional)" )
discordChannel = NodeCmd . Flags ( ) . String ( "discordChannel" , "" , "Discord channel name (optional)" )
2021-08-30 07:19:00 -07:00
bigTablePersistenceEnabled = NodeCmd . Flags ( ) . Bool ( "bigTablePersistenceEnabled" , false , "Turn on forwarding events to BigTable" )
bigTableGCPProject = NodeCmd . Flags ( ) . String ( "bigTableGCPProject" , "" , "Google Cloud project ID for storing events" )
bigTableInstanceName = NodeCmd . Flags ( ) . String ( "bigTableInstanceName" , "" , "BigTable instance name for storing events" )
bigTableTableName = NodeCmd . Flags ( ) . String ( "bigTableTableName" , "" , "BigTable table name to store events in" )
2021-11-04 02:00:52 -07:00
bigTableTopicName = NodeCmd . Flags ( ) . String ( "bigTableTopicName" , "" , "GCP topic name to publish to" )
2021-08-30 07:19:00 -07:00
bigTableKeyPath = NodeCmd . Flags ( ) . String ( "bigTableKeyPath" , "" , "Path to json Service Account key" )
2020-10-28 14:41:38 -07:00
}
2020-08-17 05:55:51 -07:00
var (
rootCtx context . Context
rootCtxCancel context . CancelFunc
)
2020-08-19 05:23:00 -07:00
// "Why would anyone do this?" are famous last words.
//
// We already forcibly override RPC URLs and keys in dev mode to prevent security
// risks from operator error, but an extra warning won't hurt.
const devwarning = `
++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +
| NODE IS RUNNING IN INSECURE DEVELOPMENT MODE |
| |
| Do not use - unsafeDevMode in prod . |
++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +
`
2021-08-30 07:19:00 -07:00
// NodeCmd represents the node command
var NodeCmd = & cobra . Command {
Use : "node" ,
Short : "Run the guardiand node" ,
Run : runNode ,
2020-10-28 14:41:38 -07:00
}
2020-08-02 14:12:58 -07:00
2021-08-30 07:19:00 -07:00
func runNode ( cmd * cobra . Command , args [ ] string ) {
2020-08-19 05:23:00 -07:00
if * unsafeDevMode {
fmt . Print ( devwarning )
}
2021-12-02 16:02:32 -08:00
common . LockMemory ( )
common . SetRestrictiveUmask ( )
2020-10-22 07:51:56 -07:00
2021-08-02 04:26:57 -07:00
// Refuse to run as root in production mode.
if ! * unsafeDevMode && os . Geteuid ( ) == 0 {
fmt . Println ( "can't run as uid 0" )
os . Exit ( 1 )
}
2020-08-02 14:12:58 -07:00
// Set up logging. The go-log zap wrapper that libp2p uses is compatible with our
// usage of zap in supervisor, which is nice.
lvl , err := ipfslog . LevelFromString ( * logLevel )
if err != nil {
fmt . Println ( "Invalid log level" )
os . Exit ( 1 )
}
2022-01-25 03:59:18 -08:00
logger := zap . New ( zapcore . NewCore (
consoleEncoder { zapcore . NewConsoleEncoder (
zap . NewDevelopmentEncoderConfig ( ) ) } ,
zapcore . AddSync ( zapcore . Lock ( os . Stderr ) ) ,
zap . NewAtomicLevelAt ( zapcore . Level ( lvl ) ) ) )
2022-01-06 08:58:56 -08:00
if * unsafeDevMode {
// Use the hostname as nodeName. For production, we don't want to do this to
// prevent accidentally leaking sensitive hostnames.
hostname , err := os . Hostname ( )
if err != nil {
panic ( err )
}
* nodeName = hostname
// Put node name into the log for development.
logger = logger . Named ( * nodeName )
}
2020-08-02 14:12:58 -07:00
// Override the default go-log config, which uses a magic environment variable.
ipfslog . SetAllLoggers ( lvl )
2020-11-27 15:46:37 -08:00
// Register components for readiness checks.
2020-11-29 04:30:18 -08:00
readiness . RegisterComponent ( common . ReadinessEthSyncing )
readiness . RegisterComponent ( common . ReadinessSolanaSyncing )
2021-07-20 13:07:51 -07:00
readiness . RegisterComponent ( common . ReadinessTerraSyncing )
2022-04-29 12:56:08 -07:00
if * testnetMode || * unsafeDevMode {
2021-12-22 08:22:04 -08:00
readiness . RegisterComponent ( common . ReadinessAlgorandSyncing )
}
2021-10-28 14:25:12 -07:00
readiness . RegisterComponent ( common . ReadinessBSCSyncing )
readiness . RegisterComponent ( common . ReadinessPolygonSyncing )
2021-12-14 14:27:17 -08:00
readiness . RegisterComponent ( common . ReadinessAvalancheSyncing )
2021-12-21 12:55:31 -08:00
readiness . RegisterComponent ( common . ReadinessOasisSyncing )
2022-04-09 05:06:10 -07:00
readiness . RegisterComponent ( common . ReadinessAuroraSyncing )
2022-03-01 17:32:31 -08:00
readiness . RegisterComponent ( common . ReadinessFantomSyncing )
2022-05-02 11:28:17 -07:00
readiness . RegisterComponent ( common . ReadinessKaruraSyncing )
2022-06-02 09:18:44 -07:00
readiness . RegisterComponent ( common . ReadinessAcalaSyncing )
2022-05-16 07:06:17 -07:00
readiness . RegisterComponent ( common . ReadinessKlaytnSyncing )
2022-05-12 09:12:40 -07:00
readiness . RegisterComponent ( common . ReadinessCeloSyncing )
2022-03-01 17:32:31 -08:00
2021-11-22 07:49:41 -08:00
if * testnetMode {
readiness . RegisterComponent ( common . ReadinessEthRopstenSyncing )
2022-05-10 08:23:07 -07:00
readiness . RegisterComponent ( common . ReadinessMoonbeamSyncing )
2021-11-22 07:49:41 -08:00
}
2020-11-27 15:46:37 -08:00
2021-01-24 08:20:04 -08:00
if * statusAddr != "" {
// Use a custom routing instead of using http.DefaultServeMux directly to avoid accidentally exposing packages
// that register themselves with it by default (like pprof).
router := mux . NewRouter ( )
// pprof server. NOT necessarily safe to expose publicly - only enable it in dev mode to avoid exposing it by
// accident. There's benefit to having pprof enabled on production nodes, but we would likely want to expose it
// via a dedicated port listening on localhost, or via the admin UNIX socket.
if * unsafeDevMode {
// Pass requests to http.DefaultServeMux, which pprof automatically registers with as an import side-effect.
router . PathPrefix ( "/debug/pprof/" ) . Handler ( http . DefaultServeMux )
}
2020-11-27 15:46:37 -08:00
2021-01-24 08:20:04 -08:00
// Simple endpoint exposing node readiness (safe to expose to untrusted clients)
router . HandleFunc ( "/readyz" , readiness . Handler )
// Prometheus metrics (safe to expose to untrusted clients)
router . Handle ( "/metrics" , promhttp . Handler ( ) )
go func ( ) {
logger . Info ( "status server listening on [::]:6060" )
2022-05-23 02:25:24 -07:00
// SECURITY: If making changes, ensure that we always do `router := mux.NewRouter()` before this to avoid accidentally exposing pprof
2021-08-05 08:30:10 -07:00
logger . Error ( "status server crashed" , zap . Error ( http . ListenAndServe ( * statusAddr , router ) ) )
2020-08-19 05:23:00 -07:00
} ( )
2021-01-24 08:20:04 -08:00
}
2020-08-19 05:23:00 -07:00
2021-01-24 08:20:04 -08:00
// In devnet mode, we automatically set a number of flags that rely on deterministic keys.
if * unsafeDevMode {
2020-08-19 05:23:00 -07:00
g0key , err := peer . IDFromPrivateKey ( devnet . DeterministicP2PPrivKeyByIndex ( 0 ) )
if err != nil {
panic ( err )
}
// Use the first guardian node as bootstrap
* p2pBootstrap = fmt . Sprintf ( "/dns4/guardian-0.guardian/udp/%d/quic/p2p/%s" , * p2pPort , g0key . String ( ) )
// Deterministic ganache ETH devnet address.
2021-08-30 07:19:00 -07:00
* ethContract = devnet . GanacheWormholeContractAddress . Hex ( )
* bscContract = devnet . GanacheWormholeContractAddress . Hex ( )
2021-10-18 08:53:13 -07:00
* polygonContract = devnet . GanacheWormholeContractAddress . Hex ( )
2021-12-14 15:16:11 -08:00
* avalancheContract = devnet . GanacheWormholeContractAddress . Hex ( )
2021-12-20 11:40:58 -08:00
* oasisContract = devnet . GanacheWormholeContractAddress . Hex ( )
2022-03-15 07:41:10 -07:00
* auroraContract = devnet . GanacheWormholeContractAddress . Hex ( )
2022-02-02 09:50:10 -08:00
* fantomContract = devnet . GanacheWormholeContractAddress . Hex ( )
2022-03-03 13:40:32 -08:00
* karuraContract = devnet . GanacheWormholeContractAddress . Hex ( )
* acalaContract = devnet . GanacheWormholeContractAddress . Hex ( )
2022-04-04 15:11:03 -07:00
* klaytnContract = devnet . GanacheWormholeContractAddress . Hex ( )
2022-04-28 09:20:38 -07:00
* celoContract = devnet . GanacheWormholeContractAddress . Hex ( )
2022-05-10 08:23:07 -07:00
* moonbeamContract = devnet . GanacheWormholeContractAddress . Hex ( )
2020-08-19 05:23:00 -07:00
}
2020-08-02 14:12:58 -07:00
2020-08-03 13:33:35 -07:00
// Verify flags
2020-08-19 05:23:00 -07:00
if * nodeKeyPath == "" && ! * unsafeDevMode { // In devnet mode, keys are deterministically generated.
2020-11-20 12:18:29 -08:00
logger . Fatal ( "Please specify --nodeKey" )
2020-08-03 13:33:35 -07:00
}
2021-08-30 07:19:00 -07:00
if * guardianKeyPath == "" {
logger . Fatal ( "Please specify --guardianKey" )
2020-11-19 03:53:17 -08:00
}
2020-11-19 03:53:19 -08:00
if * adminSocketPath == "" {
2020-11-20 12:18:29 -08:00
logger . Fatal ( "Please specify --adminSocket" )
2020-11-19 03:53:19 -08:00
}
2021-07-21 11:56:25 -07:00
if * dataDir == "" {
logger . Fatal ( "Please specify --dataDir" )
}
2020-08-16 08:05:58 -07:00
if * ethRPC == "" {
2020-11-20 12:18:29 -08:00
logger . Fatal ( "Please specify --ethRPC" )
2020-08-16 08:05:58 -07:00
}
2020-08-19 05:23:00 -07:00
if * ethContract == "" {
2020-11-20 12:18:29 -08:00
logger . Fatal ( "Please specify --ethContract" )
2020-08-19 05:23:00 -07:00
}
2021-07-28 06:32:49 -07:00
if * bscRPC == "" {
logger . Fatal ( "Please specify --bscRPC" )
}
if * bscContract == "" {
logger . Fatal ( "Please specify --bscContract" )
}
2021-10-18 08:53:13 -07:00
if * polygonRPC == "" {
logger . Fatal ( "Please specify --polygonRPC" )
}
if * polygonContract == "" {
logger . Fatal ( "Please specify --polygonContract" )
}
2021-12-14 14:27:17 -08:00
if * avalancheRPC == "" {
logger . Fatal ( "Please specify --avalancheRPC" )
}
2021-12-21 12:55:31 -08:00
if * oasisRPC == "" {
logger . Fatal ( "Please specify --oasisRPC" )
}
2022-02-28 13:32:22 -08:00
if * fantomRPC == "" {
logger . Fatal ( "Please specify --fantomRPC" )
}
if * fantomContract == "" && ! * unsafeDevMode {
logger . Fatal ( "Please specify --fantomContract" )
}
2022-04-09 05:06:10 -07:00
if * auroraRPC == "" {
logger . Fatal ( "Please specify --auroraRPC" )
}
if * auroraContract == "" && ! * unsafeDevMode {
logger . Fatal ( "Please specify --auroraContract" )
}
2022-05-02 11:28:17 -07:00
if * karuraRPC == "" {
logger . Fatal ( "Please specify --karuraRPC" )
}
if * karuraContract == "" && ! * unsafeDevMode {
logger . Fatal ( "Please specify --karuraContract" )
}
2022-06-02 09:18:44 -07:00
if * acalaRPC == "" {
logger . Fatal ( "Please specify --acalaRPC" )
}
if * acalaContract == "" && ! * unsafeDevMode {
logger . Fatal ( "Please specify --acalaContract" )
}
2022-05-16 07:06:17 -07:00
if * klaytnRPC == "" {
logger . Fatal ( "Please specify --klaytnRPC" )
}
if * klaytnContract == "" && ! * unsafeDevMode {
logger . Fatal ( "Please specify --klaytnContract" )
}
2022-05-12 09:12:40 -07:00
if * celoRPC == "" {
logger . Fatal ( "Please specify --celoRPC" )
}
if * celoContract == "" && ! * unsafeDevMode {
logger . Fatal ( "Please specify --celoContract" )
}
2021-11-22 07:49:41 -08:00
if * testnetMode {
if * ethRopstenRPC == "" {
logger . Fatal ( "Please specify --ethRopstenRPC" )
}
if * ethRopstenContract == "" {
logger . Fatal ( "Please specify --ethRopstenContract" )
}
2022-05-10 08:23:07 -07:00
if * moonbeamRPC == "" {
logger . Fatal ( "Please specify --moonbeamRPC" )
}
if * moonbeamContract == "" {
logger . Fatal ( "Please specify --moonbeamContract" )
}
2021-11-22 07:49:41 -08:00
} else {
if * ethRopstenRPC != "" {
logger . Fatal ( "Please do not specify --ethRopstenRPC in non-testnet mode" )
}
if * ethRopstenContract != "" {
logger . Fatal ( "Please do not specify --ethRopstenContract in non-testnet mode" )
}
2022-05-10 08:23:07 -07:00
if * moonbeamRPC != "" && ! * unsafeDevMode {
logger . Fatal ( "Please do not specify --moonbeamRPC" )
}
if * moonbeamContract != "" && ! * unsafeDevMode {
logger . Fatal ( "Please do not specify --moonbeamContract" )
}
2021-11-22 07:49:41 -08:00
}
2020-08-17 10:22:12 -07:00
if * nodeName == "" {
2020-11-20 12:18:29 -08:00
logger . Fatal ( "Please specify --nodeName" )
2020-08-17 10:22:12 -07:00
}
2021-01-21 02:31:32 -08:00
2021-08-30 07:19:00 -07:00
if * solanaContract == "" {
logger . Fatal ( "Please specify --solanaContract" )
2021-01-21 02:31:32 -08:00
}
if * solanaWsRPC == "" {
logger . Fatal ( "Please specify --solanaWsUrl" )
}
if * solanaRPC == "" {
logger . Fatal ( "Please specify --solanaUrl" )
}
2021-07-20 13:07:51 -07:00
if * terraWS == "" {
logger . Fatal ( "Please specify --terraWS" )
}
if * terraLCD == "" {
logger . Fatal ( "Please specify --terraLCD" )
}
if * terraContract == "" {
logger . Fatal ( "Please specify --terraContract" )
}
2022-04-29 12:56:08 -07:00
if * testnetMode || * unsafeDevMode {
if * algorandIndexerRPC == "" {
logger . Fatal ( "Please specify --algorandIndexerRPC" )
2021-12-22 08:22:04 -08:00
}
2022-04-29 12:56:08 -07:00
if * algorandIndexerToken == "" {
logger . Fatal ( "Please specify --algorandIndexerToken" )
2021-12-22 08:22:04 -08:00
}
2022-05-10 04:41:59 -07:00
if * algorandAlgodRPC == "" {
logger . Fatal ( "Please specify --algorandAlgodRPC" )
}
if * algorandAlgodToken == "" {
logger . Fatal ( "Please specify --algorandAlgodToken" )
}
2022-04-29 12:56:08 -07:00
if * algorandAppID == 0 {
logger . Fatal ( "Please specify --algorandAppID" )
2021-12-22 08:22:04 -08:00
}
}
2021-07-07 02:39:48 -07:00
if * bigTablePersistenceEnabled {
if * bigTableGCPProject == "" {
logger . Fatal ( "Please specify --bigTableGCPProject" )
}
if * bigTableInstanceName == "" {
logger . Fatal ( "Please specify --bigTableInstanceName" )
}
if * bigTableTableName == "" {
logger . Fatal ( "Please specify --bigTableTableName" )
}
2021-11-04 02:00:52 -07:00
if * bigTableTopicName == "" {
logger . Fatal ( "Please specify --bigTableTopicName" )
}
2021-07-07 02:39:48 -07:00
if * bigTableKeyPath == "" {
logger . Fatal ( "Please specify --bigTableKeyPath" )
}
}
2021-10-18 08:23:55 -07:00
// Complain about Infura on mainnet.
//
// As it turns out, Infura has a bug where it would sometimes incorrectly round
// block timestamps, which causes consensus issues - the timestamp is part of
// the VAA and nodes using Infura would sometimes derive an incorrect VAA,
// accidentally attacking the network by signing a conflicting VAA.
//
// Node operators do not usually rely on Infura in the first place - doing
// so is insecure, since nodes blindly trust the connected nodes to verify
// on-chain message proofs. However, node operators sometimes used
// Infura during migrations where their primary node was offline, causing
// the aforementioned consensus oddities which were eventually found to
// be Infura-related. This is generally to the detriment of network security
// and a judgement call made by individual operators. In the case of Infura,
// we know it's actively dangerous so let's make an opinionated argument.
//
// Insert "I'm a sign, not a cop" meme.
//
2021-10-26 16:42:00 -07:00
if strings . Contains ( * ethRPC , "mainnet.infura.io" ) ||
strings . Contains ( * polygonRPC , "polygon-mainnet.infura.io" ) {
2021-10-18 08:23:55 -07:00
logger . Fatal ( "Infura is known to send incorrect blocks - please use your own nodes" )
}
2020-08-16 08:05:58 -07:00
ethContractAddr := eth_common . HexToAddress ( * ethContract )
2021-07-28 06:32:49 -07:00
bscContractAddr := eth_common . HexToAddress ( * bscContract )
2021-10-18 08:53:13 -07:00
polygonContractAddr := eth_common . HexToAddress ( * polygonContract )
2021-11-22 07:49:41 -08:00
ethRopstenContractAddr := eth_common . HexToAddress ( * ethRopstenContract )
2021-12-09 13:40:55 -08:00
avalancheContractAddr := eth_common . HexToAddress ( * avalancheContract )
2021-12-20 11:40:58 -08:00
oasisContractAddr := eth_common . HexToAddress ( * oasisContract )
2022-03-15 07:41:10 -07:00
auroraContractAddr := eth_common . HexToAddress ( * auroraContract )
2022-02-02 09:50:10 -08:00
fantomContractAddr := eth_common . HexToAddress ( * fantomContract )
2022-03-03 13:40:32 -08:00
karuraContractAddr := eth_common . HexToAddress ( * karuraContract )
acalaContractAddr := eth_common . HexToAddress ( * acalaContract )
2022-04-04 15:11:03 -07:00
klaytnContractAddr := eth_common . HexToAddress ( * klaytnContract )
2022-04-28 09:20:38 -07:00
celoContractAddr := eth_common . HexToAddress ( * celoContract )
2022-05-10 08:23:07 -07:00
moonbeamContractAddr := eth_common . HexToAddress ( * moonbeamContract )
2021-08-30 07:19:00 -07:00
solAddress , err := solana_types . PublicKeyFromBase58 ( * solanaContract )
2021-01-21 02:31:32 -08:00
if err != nil {
2021-08-30 07:19:00 -07:00
logger . Fatal ( "invalid Solana contract address" , zap . Error ( err ) )
2021-01-21 02:31:32 -08:00
}
2020-08-03 13:33:35 -07:00
2020-11-19 03:53:17 -08:00
// In devnet mode, we generate a deterministic guardian key and write it to disk.
if * unsafeDevMode {
gk , err := generateDevnetGuardianKey ( )
if err != nil {
logger . Fatal ( "failed to generate devnet guardian key" , zap . Error ( err ) )
}
2021-08-30 07:19:00 -07:00
err = writeGuardianKey ( gk , "auto-generated deterministic devnet key" , * guardianKeyPath , true )
2020-11-19 03:53:17 -08:00
if err != nil {
logger . Fatal ( "failed to write devnet guardian key" , zap . Error ( err ) )
}
}
2021-07-30 13:40:01 -07:00
// Database
dbPath := path . Join ( * dataDir , "db" )
if err := os . MkdirAll ( dbPath , 0700 ) ; err != nil {
logger . Fatal ( "failed to create database directory" , zap . Error ( err ) )
}
db , err := db . Open ( dbPath )
if err != nil {
logger . Fatal ( "failed to open database" , zap . Error ( err ) )
}
defer db . Close ( )
2020-08-17 10:36:17 -07:00
// Guardian key
2021-08-30 07:19:00 -07:00
gk , err := loadGuardianKey ( * guardianKeyPath )
2020-11-19 03:53:17 -08:00
if err != nil {
logger . Fatal ( "failed to load guardian key" , zap . Error ( err ) )
}
2021-02-03 04:01:51 -08:00
guardianAddr := ethcrypto . PubkeyToAddress ( gk . PublicKey ) . String ( )
2020-11-19 03:53:17 -08:00
logger . Info ( "Loaded guardian key" , zap . String (
2021-02-03 04:01:51 -08:00
"address" , guardianAddr ) )
p2p . DefaultRegistry . SetGuardianAddress ( guardianAddr )
2020-08-17 09:20:15 -07:00
2020-08-02 14:12:58 -07:00
// Node's main lifecycle context.
2020-08-17 05:55:51 -07:00
rootCtx , rootCtxCancel = context . WithCancel ( context . Background ( ) )
defer rootCtxCancel ( )
2020-08-02 14:12:58 -07:00
2020-08-16 08:05:58 -07:00
// Ethereum lock event channel
2021-04-15 02:36:29 -07:00
lockC := make ( chan * common . MessagePublication )
2020-08-19 05:23:00 -07:00
// Ethereum incoming guardian set updates
setC := make ( chan * common . GuardianSet )
// Outbound gossip message queue
sendC := make ( chan [ ] byte )
2020-08-21 04:00:40 -07:00
// Inbound observations
2020-11-20 13:35:00 -08:00
obsvC := make ( chan * gossipv1 . SignedObservation , 50 )
2020-08-20 12:48:58 -07:00
2021-09-13 06:03:26 -07:00
// Inbound signed VAAs
signedInC := make ( chan * gossipv1 . SignedVAAWithQuorum , 50 )
2022-02-08 14:16:43 -08:00
// Inbound observation requests from the p2p service (for all chains)
2021-12-20 13:23:45 -08:00
obsvReqC := make ( chan * gossipv1 . ObservationRequest , 50 )
// Outbound observation requests
obsvReqSendC := make ( chan * gossipv1 . ObservationRequest )
2020-11-19 03:53:19 -08:00
// Injected VAAs (manually generated rather than created via observation)
injectC := make ( chan * vaa . VAA )
2021-07-31 09:51:38 -07:00
// Guardian set state managed by processor
2021-08-03 11:03:00 -07:00
gst := common . NewGuardianSetState ( )
2021-07-31 09:51:38 -07:00
2022-02-08 14:16:43 -08:00
// Per-chain observation requests
chainObsvReqC := make ( map [ vaa . ChainID ] chan * gossipv1 . ObservationRequest )
// Observation request channel for each chain supporting observation requests.
chainObsvReqC [ vaa . ChainIDSolana ] = make ( chan * gossipv1 . ObservationRequest )
chainObsvReqC [ vaa . ChainIDEthereum ] = make ( chan * gossipv1 . ObservationRequest )
2022-02-09 09:54:33 -08:00
chainObsvReqC [ vaa . ChainIDTerra ] = make ( chan * gossipv1 . ObservationRequest )
2022-02-08 14:16:43 -08:00
chainObsvReqC [ vaa . ChainIDBSC ] = make ( chan * gossipv1 . ObservationRequest )
chainObsvReqC [ vaa . ChainIDPolygon ] = make ( chan * gossipv1 . ObservationRequest )
chainObsvReqC [ vaa . ChainIDAvalanche ] = make ( chan * gossipv1 . ObservationRequest )
chainObsvReqC [ vaa . ChainIDOasis ] = make ( chan * gossipv1 . ObservationRequest )
2022-04-29 12:56:08 -07:00
if * testnetMode || * unsafeDevMode {
chainObsvReqC [ vaa . ChainIDAlgorand ] = make ( chan * gossipv1 . ObservationRequest )
}
2022-04-09 05:06:10 -07:00
chainObsvReqC [ vaa . ChainIDAurora ] = make ( chan * gossipv1 . ObservationRequest )
2022-04-04 12:08:16 -07:00
chainObsvReqC [ vaa . ChainIDFantom ] = make ( chan * gossipv1 . ObservationRequest )
2022-05-02 11:28:17 -07:00
chainObsvReqC [ vaa . ChainIDKarura ] = make ( chan * gossipv1 . ObservationRequest )
2022-06-02 09:18:44 -07:00
chainObsvReqC [ vaa . ChainIDAcala ] = make ( chan * gossipv1 . ObservationRequest )
2022-05-16 07:06:17 -07:00
chainObsvReqC [ vaa . ChainIDKlaytn ] = make ( chan * gossipv1 . ObservationRequest )
2022-05-12 09:12:40 -07:00
chainObsvReqC [ vaa . ChainIDCelo ] = make ( chan * gossipv1 . ObservationRequest )
2022-02-08 14:16:43 -08:00
if * testnetMode {
2022-05-10 08:23:07 -07:00
chainObsvReqC [ vaa . ChainIDMoonbeam ] = make ( chan * gossipv1 . ObservationRequest )
2022-02-08 14:16:43 -08:00
chainObsvReqC [ vaa . ChainIDEthereumRopsten ] = make ( chan * gossipv1 . ObservationRequest )
}
// Multiplex observation requests to the appropriate chain
go func ( ) {
for {
select {
case <- rootCtx . Done ( ) :
return
case req := <- obsvReqC :
if channel , ok := chainObsvReqC [ vaa . ChainID ( req . ChainId ) ] ; ok {
channel <- req
} else {
logger . Error ( "unknown chain ID for reobservation request" ,
zap . Uint32 ( "chain_id" , req . ChainId ) ,
zap . String ( "tx_hash" , hex . EncodeToString ( req . TxHash ) ) )
}
}
}
} ( )
2021-10-05 11:13:07 -07:00
var notifier * discord . DiscordNotifier
if * discordToken != "" {
notifier , err = discord . NewDiscordNotifier ( * discordToken , * discordChannel , logger )
if err != nil {
logger . Error ( "failed to initialize Discord bot" , zap . Error ( err ) )
}
}
2020-10-28 14:41:37 -07:00
// Load p2p private key
var priv crypto . PrivKey
if * unsafeDevMode {
idx , err := devnet . GetDevnetIndex ( )
if err != nil {
logger . Fatal ( "Failed to parse hostname - are we running in devnet?" )
}
priv = devnet . DeterministicP2PPrivKeyByIndex ( int64 ( idx ) )
} else {
2021-12-02 16:02:32 -08:00
priv , err = common . GetOrCreateNodeKey ( logger , * nodeKeyPath )
2020-10-28 14:41:37 -07:00
if err != nil {
logger . Fatal ( "Failed to load node key" , zap . Error ( err ) )
}
}
2022-01-09 12:56:59 -08:00
// Enable unless it is disabled. For devnet, only when --telemetryKey is set.
if ! * disableTelemetry && ( ! * unsafeDevMode || * unsafeDevMode && * telemetryKey != "" ) {
logger . Info ( "Telemetry enabled" )
if * telemetryKey == "" {
logger . Fatal ( "Please specify --telemetryKey" )
}
creds , err := decryptTelemetryServiceAccount ( )
if err != nil {
logger . Fatal ( "Failed to decrypt telemetry service account" , zap . Error ( err ) )
}
// Get libp2p peer ID from private key
pk := priv . GetPublic ( )
peerID , err := peer . IDFromPublicKey ( pk )
if err != nil {
logger . Fatal ( "Failed to get peer ID from private key" , zap . Error ( err ) )
}
tm , err := telemetry . New ( context . Background ( ) , telemetryProject , creds , map [ string ] string {
"node_name" : * nodeName ,
"node_key" : peerID . Pretty ( ) ,
"guardian_addr" : guardianAddr ,
"network" : * p2pNetworkID ,
"version" : version . Version ( ) ,
} )
if err != nil {
logger . Fatal ( "Failed to initialize telemetry" , zap . Error ( err ) )
}
defer tm . Close ( )
logger = tm . WrapLogger ( logger )
} else {
logger . Info ( "Telemetry disabled" )
}
// Redirect ipfs logs to plain zap
ipfslog . SetPrimaryCore ( logger . Core ( ) )
2021-08-09 22:29:21 -07:00
// provides methods for reporting progress toward message attestation, and channels for receiving attestation lifecyclye events.
attestationEvents := reporter . EventListener ( logger )
2021-08-21 13:47:15 -07:00
publicrpcService , publicrpcServer , err := publicrpcServiceRunnable ( logger , * publicRPC , db , gst )
2021-08-09 22:29:21 -07:00
2021-07-22 04:26:19 -07:00
if err != nil {
log . Fatal ( "failed to create publicrpc service socket" , zap . Error ( err ) )
}
2021-05-12 22:57:08 -07:00
2021-07-22 04:31:46 -07:00
// local admin service socket
2021-12-20 13:23:45 -08:00
adminService , err := adminServiceRunnable ( logger , * adminSocketPath , injectC , signedInC , obsvReqSendC , db , gst )
2021-07-22 04:31:46 -07:00
if err != nil {
logger . Fatal ( "failed to create admin service socket" , zap . Error ( err ) )
}
2021-08-20 16:52:07 -07:00
publicwebService , err := publicwebServiceRunnable ( logger , * publicWeb , * adminSocketPath , publicrpcServer ,
2021-08-20 15:44:37 -07:00
* tlsHostname , * tlsProdEnv , path . Join ( * dataDir , "autocert" ) )
2021-07-30 16:18:53 -07:00
if err != nil {
log . Fatal ( "failed to create publicrpc service socket" , zap . Error ( err ) )
}
2020-08-02 14:12:58 -07:00
// Run supervisor.
2020-08-17 09:20:15 -07:00
supervisor . New ( rootCtx , logger , func ( ctx context . Context ) error {
2020-10-28 14:41:37 -07:00
if err := supervisor . Run ( ctx , "p2p" , p2p . Run (
2021-12-20 13:23:45 -08:00
obsvC , obsvReqC , obsvReqSendC , sendC , signedInC , priv , gk , gst , * p2pPort , * p2pNetworkID , * p2pBootstrap , * nodeName , * disableHeartbeatVerify , rootCtxCancel ) ) ; err != nil {
2020-08-02 14:12:58 -07:00
return err
}
2020-08-21 15:21:41 -07:00
if err := supervisor . Run ( ctx , "ethwatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * ethRPC , ethContractAddr , "eth" , common . ReadinessEthSyncing , vaa . ChainIDEthereum , lockC , setC , 1 , chainObsvReqC [ vaa . ChainIDEthereum ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2020-08-21 02:57:04 -07:00
return err
}
2020-08-16 08:05:58 -07:00
2021-07-28 06:32:49 -07:00
if err := supervisor . Run ( ctx , "bscwatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * bscRPC , bscContractAddr , "bsc" , common . ReadinessBSCSyncing , vaa . ChainIDBSC , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDBSC ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2021-07-28 06:32:49 -07:00
return err
}
2022-05-25 23:53:47 -07:00
{
var extraParams [ ] string
var minConfirmations uint64 = 512
if * polygonCheckpoint != "" {
extraParams = [ ] string { * polygonCheckpoint }
minConfirmations = 1
} else if * testnetMode {
minConfirmations = 64
}
if err := supervisor . Run ( ctx , "polygonwatch" ,
ethereum . NewEthWatcher ( * polygonRPC , polygonContractAddr , "polygon" , common . ReadinessPolygonSyncing , vaa . ChainIDPolygon , lockC , nil , minConfirmations , chainObsvReqC [ vaa . ChainIDPolygon ] ,
* unsafeDevMode , extraParams ) . Run ) ; err != nil {
// Special case: Polygon can fork like PoW Ethereum, and it's not clear what the safe number of blocks is
//
// If we are not querying the checkpoint server, we should hardcode the minimum number of confirmations to 512 regardless of what the smart contract specifies to protect
// developers from accidentally specifying an unsafe number of confirmations. We can remove this restriction as soon
// as specific public guidance exists for Polygon developers.
return err
}
2022-06-06 08:13:14 -07:00
}
2021-12-14 14:27:17 -08:00
if err := supervisor . Run ( ctx , "avalanchewatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * avalancheRPC , avalancheContractAddr , "avalanche" , common . ReadinessAvalancheSyncing , vaa . ChainIDAvalanche , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDAvalanche ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2021-12-14 14:27:17 -08:00
return err
}
2021-12-21 12:55:31 -08:00
if err := supervisor . Run ( ctx , "oasiswatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * oasisRPC , oasisContractAddr , "oasis" , common . ReadinessOasisSyncing , vaa . ChainIDOasis , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDOasis ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2021-12-21 12:55:31 -08:00
return err
}
2022-04-09 05:06:10 -07:00
if err := supervisor . Run ( ctx , "aurorawatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * auroraRPC , auroraContractAddr , "aurora" , common . ReadinessAuroraSyncing , vaa . ChainIDAurora , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDAurora ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2022-04-09 05:06:10 -07:00
return err
}
2022-02-28 13:32:22 -08:00
if err := supervisor . Run ( ctx , "fantomwatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * fantomRPC , fantomContractAddr , "fantom" , common . ReadinessFantomSyncing , vaa . ChainIDFantom , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDFantom ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2022-02-28 13:32:22 -08:00
return err
}
2022-05-02 11:28:17 -07:00
if err := supervisor . Run ( ctx , "karurawatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * karuraRPC , karuraContractAddr , "karura" , common . ReadinessKaruraSyncing , vaa . ChainIDKarura , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDKarura ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2022-05-02 11:28:17 -07:00
return err
}
2022-06-02 09:18:44 -07:00
if err := supervisor . Run ( ctx , "acalawatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * acalaRPC , acalaContractAddr , "acala" , common . ReadinessAcalaSyncing , vaa . ChainIDAcala , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDAcala ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2022-06-02 09:18:44 -07:00
return err
}
2022-05-16 07:06:17 -07:00
if err := supervisor . Run ( ctx , "klaytnwatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * klaytnRPC , klaytnContractAddr , "klaytn" , common . ReadinessKlaytnSyncing , vaa . ChainIDKlaytn , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDKlaytn ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2022-05-16 07:06:17 -07:00
return err
}
2022-05-12 09:12:40 -07:00
if err := supervisor . Run ( ctx , "celowatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * celoRPC , celoContractAddr , "celo" , common . ReadinessCeloSyncing , vaa . ChainIDCelo , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDCelo ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2022-05-12 09:12:40 -07:00
return err
}
2022-03-03 13:40:32 -08:00
2021-11-22 07:49:41 -08:00
if * testnetMode {
if err := supervisor . Run ( ctx , "ethropstenwatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * ethRopstenRPC , ethRopstenContractAddr , "ethropsten" , common . ReadinessEthRopstenSyncing , vaa . ChainIDEthereumRopsten , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDEthereumRopsten ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2022-03-03 13:40:32 -08:00
return err
}
2022-05-10 08:23:07 -07:00
if err := supervisor . Run ( ctx , "moonbeamwatch" ,
2022-05-25 23:53:47 -07:00
ethereum . NewEthWatcher ( * moonbeamRPC , moonbeamContractAddr , "moonbeam" , common . ReadinessMoonbeamSyncing , vaa . ChainIDMoonbeam , lockC , nil , 1 , chainObsvReqC [ vaa . ChainIDMoonbeam ] , * unsafeDevMode , nil ) . Run ) ; err != nil {
2022-05-10 08:23:07 -07:00
return err
}
2021-11-22 07:49:41 -08:00
}
2020-11-16 04:28:07 -08:00
// Start Terra watcher only if configured
2021-07-20 13:07:51 -07:00
logger . Info ( "Starting Terra watcher" )
if err := supervisor . Run ( ctx , "terrawatch" ,
2022-02-09 09:54:33 -08:00
terra . NewWatcher ( * terraWS , * terraLCD , * terraContract , lockC , setC , chainObsvReqC [ vaa . ChainIDTerra ] ) . Run ) ; err != nil {
2021-07-20 13:07:51 -07:00
return err
2020-11-16 04:28:07 -08:00
}
2022-04-29 12:56:08 -07:00
if * testnetMode || * unsafeDevMode {
2021-12-22 08:22:04 -08:00
if err := supervisor . Run ( ctx , "algorandwatch" ,
2022-05-10 04:41:59 -07:00
algorand . NewWatcher ( * algorandIndexerRPC , * algorandIndexerToken , * algorandAlgodRPC , * algorandAlgodToken , * algorandAppID , lockC , setC , chainObsvReqC [ vaa . ChainIDAlgorand ] ) . Run ) ; err != nil {
2021-12-22 08:22:04 -08:00
return err
}
}
2021-07-29 05:24:35 -07:00
if err := supervisor . Run ( ctx , "solwatch-confirmed" ,
2021-12-20 13:23:45 -08:00
solana . NewSolanaWatcher ( * solanaWsRPC , * solanaRPC , solAddress , lockC , nil , rpc . CommitmentConfirmed ) . Run ) ; err != nil {
2021-07-29 05:24:35 -07:00
return err
}
if err := supervisor . Run ( ctx , "solwatch-finalized" ,
2022-02-08 14:16:43 -08:00
solana . NewSolanaWatcher ( * solanaWsRPC , * solanaRPC , solAddress , lockC , chainObsvReqC [ vaa . ChainIDSolana ] , rpc . CommitmentFinalized ) . Run ) ; err != nil {
2020-08-20 12:48:58 -07:00
return err
}
2020-11-30 08:13:48 -08:00
p := processor . NewProcessor ( ctx ,
2021-07-30 13:40:01 -07:00
db ,
2020-11-30 08:13:48 -08:00
lockC ,
setC ,
sendC ,
obsvC ,
injectC ,
2021-09-13 06:03:26 -07:00
signedInC ,
2020-11-30 08:13:48 -08:00
gk ,
2021-07-31 09:51:38 -07:00
gst ,
2020-11-30 08:13:48 -08:00
* unsafeDevMode ,
* devNumGuardians ,
* ethRPC ,
* terraLCD ,
* terraContract ,
2021-08-09 22:29:21 -07:00
attestationEvents ,
2021-10-05 11:13:07 -07:00
notifier ,
2020-11-30 08:13:48 -08:00
)
2020-10-28 14:41:36 -07:00
if err := supervisor . Run ( ctx , "processor" , p . Run ) ; err != nil {
2020-08-21 15:21:41 -07:00
return err
}
2020-11-19 03:53:19 -08:00
if err := supervisor . Run ( ctx , "admin" , adminService ) ; err != nil {
return err
}
2021-05-12 22:57:08 -07:00
if * publicRPC != "" {
2021-07-22 04:26:19 -07:00
if err := supervisor . Run ( ctx , "publicrpc" , publicrpcService ) ; err != nil {
2021-05-12 22:57:08 -07:00
return err
}
}
2021-08-20 16:52:07 -07:00
if * publicWeb != "" {
if err := supervisor . Run ( ctx , "publicweb" , publicwebService ) ; err != nil {
2021-07-30 16:18:53 -07:00
return err
}
}
2020-11-19 03:53:19 -08:00
2021-08-09 22:29:21 -07:00
if * bigTablePersistenceEnabled {
bigTableConnection := & reporter . BigTableConnectionConfig {
GcpProjectID : * bigTableGCPProject ,
GcpInstanceName : * bigTableInstanceName ,
TableName : * bigTableTableName ,
2021-11-04 02:00:52 -07:00
TopicName : * bigTableTopicName ,
2021-08-09 22:29:21 -07:00
GcpKeyFilePath : * bigTableKeyPath ,
}
if err := supervisor . Run ( ctx , "bigtable" , reporter . BigTableWriter ( attestationEvents , bigTableConnection ) ) ; err != nil {
return err
}
}
2020-08-17 05:55:51 -07:00
logger . Info ( "Started internal services" )
2020-08-02 14:12:58 -07:00
2021-08-30 11:40:38 -07:00
<- ctx . Done ( )
return nil
2020-10-22 03:20:11 -07:00
} ,
// It's safer to crash and restart the process in case we encounter a panic,
// rather than attempting to reschedule the runnable.
supervisor . WithPropagatePanic )
2020-08-02 14:12:58 -07:00
2021-08-30 11:40:38 -07:00
<- rootCtx . Done ( )
logger . Info ( "root context cancelled, exiting..." )
// TODO: wait for things to shut down gracefully
2020-08-02 14:12:58 -07:00
}
2022-01-09 12:56:59 -08:00
func decryptTelemetryServiceAccount ( ) ( [ ] byte , error ) {
// Decrypt service account credentials
key , err := base64 . StdEncoding . DecodeString ( * telemetryKey )
if err != nil {
return nil , fmt . Errorf ( "failed to decode: %w" , err )
}
ciphertext , err := base64 . StdEncoding . DecodeString ( telemetryServiceAccount )
if err != nil {
panic ( err )
}
creds , err := common . DecryptAESGCM ( ciphertext , key )
if err != nil {
return nil , fmt . Errorf ( "failed to decrypt: %w" , err )
}
return creds , err
}