Skip to content

Commit

Permalink
watcher: break out the network
Browse files Browse the repository at this point in the history
  • Loading branch information
panoel committed Jan 9, 2024
1 parent 6861b0e commit 2571991
Show file tree
Hide file tree
Showing 42 changed files with 509 additions and 274 deletions.
88 changes: 61 additions & 27 deletions common/src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,34 +31,68 @@ import {
coalesceChainName,
} from '@certusone/wormhole-sdk';

export const INITIAL_DEPLOYMENT_BLOCK_BY_CHAIN: {
[key in ChainName]?: string;
export enum NETWORK {
MAINNET,
TESTNET,
}

export const INITIAL_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN: {
[key in NETWORK]: { [key in ChainName]?: string };
} = {
ethereum: '12959638',
terra: '4810000', // not sure exactly but this should be before the first known message
bsc: '9745450',
polygon: '20629146',
avalanche: '8237163',
oasis: '1757',
algorand: '22931277',
fantom: '31817467',
karura: '1824665',
acala: '1144161',
klaytn: '90563824',
celo: '12947144',
moonbeam: '1486591',
terra2: '399813',
injective: '20908376',
arbitrum: '18128584',
optimism: '69401779',
aptos: '0', // block is 1094390 but AptosWatcher uses sequence number instead
near: '72767136',
xpla: '777549',
solana: '94401321', // https://explorer.solana.com/tx/KhLy688yDxbP7xbXVXK7TGpZU5DAFHbYiaoX16zZArxvVySz8i8g7N7Ss2noQYoq9XRbg6HDzrQBjUfmNcSWwhe
sui: '1485552', // https://explorer.sui.io/txblock/671SoTvVUvBZQWKXeameDvAwzHQvnr8Nj7dR9MUwm3CV?network=https%3A%2F%2Frpc.mainnet.sui.io
base: '1422314',
sei: '238594',
wormchain: '4510119', // https://bigdipper.live/wormhole/transactions/4D861F1BE86325D227FA006CA2745BBC6748AF5B5E0811DE536D02792928472A
[NETWORK.MAINNET]: {
ethereum: '12959638',
terra: '4810000', // not sure exactly but this should be before the first known message
bsc: '9745450',
polygon: '20629146',
avalanche: '8237163',
oasis: '1757',
algorand: '22931277',
fantom: '31817467',
karura: '1824665',
acala: '1144161',
klaytn: '90563824',
celo: '12947144',
moonbeam: '1486591',
terra2: '399813',
injective: '20908376',
arbitrum: '18128584',
optimism: '69401779',
aptos: '0', // block is 1094390 but AptosWatcher uses sequence number instead
near: '72767136',
xpla: '777549',
solana: '94401321', // https://explorer.solana.com/tx/KhLy688yDxbP7xbXVXK7TGpZU5DAFHbYiaoX16zZArxvVySz8i8g7N7Ss2noQYoq9XRbg6HDzrQBjUfmNcSWwhe
sui: '1485552', // https://explorer.sui.io/txblock/671SoTvVUvBZQWKXeameDvAwzHQvnr8Nj7dR9MUwm3CV?network=https%3A%2F%2Frpc.mainnet.sui.io
base: '1422314',
sei: '238594',
wormchain: '4510119', // https://bigdipper.live/wormhole/transactions/4D861F1BE86325D227FA006CA2745BBC6748AF5B5E0811DE536D02792928472A },
},
[NETWORK.TESTNET]: {
ethereum: '0',
terra: '0',
bsc: '0',
polygon: '0',
avalanche: '0',
oasis: '0',
algorand: '0',
fantom: '0',
karura: '0',
acala: '0',
klaytn: '0',
celo: '0',
moonbeam: '0',
terra2: '0',
injective: '0',
arbitrum: '0',
optimism: '0',
aptos: '0',
near: '0',
xpla: '0',
solana: '0',
sui: '0',
base: '0',
sei: '0',
wormchain: '0',
},
};

export const TOKEN_BRIDGE_EMITTERS: { [key in ChainName]?: string } = {
Expand Down
2 changes: 1 addition & 1 deletion fly/cmd/fly/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ func main() {
case <-rootCtx.Done():
return
case hb := <-heartbeatC:
id := hb.GuardianAddr
id := hb.NodeName
now := time.Now()
networks := make([]*map[string]interface{}, 0, len(hb.Networks))
for _, network := range hb.Networks {
Expand Down
4 changes: 3 additions & 1 deletion watcher/scripts/backfillArbitrum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { initDb } from '../src/databases/utils';
import { AXIOS_CONFIG_JSON } from '../src/consts';
import { ArbitrumWatcher } from '../src/watchers/ArbitrumWatcher';
import { LOG_MESSAGE_PUBLISHED_TOPIC } from '../src/watchers/EVMWatcher';
import { NETWORK } from '@wormhole-foundation/wormhole-monitor-common';

// This script exists because the Arbitrum RPC node only supports a 10 block range which is super slow
// This script only applies to Arbitrum mainnet

(async () => {
const db = initDb();
Expand All @@ -23,7 +25,7 @@ import { LOG_MESSAGE_PUBLISHED_TOPIC } from '../src/watchers/EVMWatcher';
log.succeed(`Fetched ${blockNumbers.length} logs from Arbiscan`);
// use the watcher to fetch corresponding blocks
log = ora('Fetching blocks...').start();
const watcher = new ArbitrumWatcher();
const watcher = new ArbitrumWatcher(NETWORK.MAINNET);
for (const blockNumber of blockNumbers) {
log.text = `Fetching block ${blockNumber}`;
const vaasByBlock = await watcher.getMessagesForBlocks(blockNumber, blockNumber);
Expand Down
10 changes: 7 additions & 3 deletions watcher/scripts/backfillNear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as dotenv from 'dotenv';
dotenv.config();
import { ChainName, CONTRACTS } from '@certusone/wormhole-sdk/lib/cjs/utils/consts';
import {
INITIAL_DEPLOYMENT_BLOCK_BY_CHAIN,
INITIAL_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN,
sleep,
} from '@wormhole-foundation/wormhole-monitor-common';
import { BlockResult, Provider } from 'near-api-js/lib/providers/provider';
Expand All @@ -17,6 +17,7 @@ import {
import { getMessagesFromBlockResults } from '../src/watchers/NearWatcher';
import { Transaction } from '../src/types/near';
import { VaasByBlock } from '../src/databases/types';
import { getNetworkFromEnv } from '../src/utils/environment';

// This script exists because NEAR RPC nodes do not support querying blocks older than 5 epochs
// (~2.5 days): https://docs.near.org/api/rpc/setup#querying-historical-data. This script fetches
Expand All @@ -30,10 +31,13 @@ const BATCH_SIZE = 100;

(async () => {
const db = initDb(false); // Don't start watching
const network = getNetworkFromEnv();
const chain: ChainName = 'near';
const provider = await getNearProvider(NEAR_ARCHIVE_RPC);
const provider = await getNearProvider(network, NEAR_ARCHIVE_RPC);
const fromBlock = Number(
(await db.getLastBlockByChain(chain)) ?? INITIAL_DEPLOYMENT_BLOCK_BY_CHAIN[chain] ?? 0
(await db.getLastBlockByChain(chain)) ??
INITIAL_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN[network][chain] ??
0
);
const fromBlockTimestamp: number = await getTimestampByBlock(provider, fromBlock);
console.log(`Last block seen: ${fromBlock} at ${fromBlockTimestamp}`);
Expand Down
4 changes: 3 additions & 1 deletion watcher/scripts/checkSolana.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import * as dotenv from 'dotenv';
dotenv.config();

import { SolanaWatcher } from '../src/watchers/SolanaWatcher';
import { getNetworkFromEnv } from '../src/utils/environment';

// Temporary script to test SolanaWatcher for lookup addresses
(async () => {
const sw = new SolanaWatcher();
const network = getNetworkFromEnv();
const sw = new SolanaWatcher(network);
const msgs = await sw.getMessagesForBlocks(245230133, 245230333);
console.log(msgs);
})();
4 changes: 3 additions & 1 deletion watcher/scripts/locateMessageGaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import { BigtableDatabase } from '../src/databases/BigtableDatabase';
import { parseMessageId } from '../src/databases/utils';
import { makeFinalizedWatcher } from '../src/watchers/utils';
import { Watcher } from '../src/watchers/Watcher';
import { getNetworkFromEnv } from '../src/utils/environment';

// This script checks for gaps in the message sequences for an emitter.
// Ideally this shouldn't happen, but there seems to be an issue with Oasis, Karura, and Celo

(async () => {
const network = getNetworkFromEnv();
const bt = new BigtableDatabase();
if (!bt.bigtable) {
throw new Error('bigtable is undefined');
Expand Down Expand Up @@ -72,7 +74,7 @@ import { Watcher } from '../src/watchers/Watcher';
const chainName = coalesceChainName(Number(chain) as ChainId);
let watcher: Watcher;
try {
watcher = makeFinalizedWatcher(chainName);
watcher = makeFinalizedWatcher(network, chainName);
} catch (e) {
console.error('skipping gap for unsupported chain', chainName);
continue;
Expand Down
149 changes: 108 additions & 41 deletions watcher/src/consts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ChainName, CONTRACTS } from '@certusone/wormhole-sdk/lib/cjs/utils/consts';
import { ChainName, CONTRACTS, Network } from '@certusone/wormhole-sdk/lib/cjs/utils/consts';
import { NETWORK } from '@wormhole-foundation/wormhole-monitor-common';
import { AxiosRequestConfig } from 'axios';

export const TIMEOUT = 0.5 * 1000;
Expand All @@ -24,50 +25,101 @@ export const TIMEOUT = 0.5 * 1000;
// Arbitrum
// This node didn't work: 'https://arb1.arbitrum.io/rpc',

export const RPCS_BY_CHAIN: { [key in ChainName]?: string } = {
ethereum: process.env.ETH_RPC,
bsc: process.env.BSC_RPC || 'https://rpc.ankr.com/bsc',
polygon: process.env.POLYGON_RPC || 'https://rpc.ankr.com/polygon',
avalanche: process.env.AVALANCHE_RPC || 'https://rpc.ankr.com/avalanche',
oasis: process.env.OASIS_RPC || 'https://emerald.oasis.dev',
algorand: process.env.ALGORAND_RPC || 'https://mainnet-api.algonode.cloud',
fantom: process.env.FANTOM_RPC || 'https://rpc.ankr.com/fantom',
karura: process.env.KARURA_RPC || 'https://eth-rpc-karura.aca-api.network',
acala: process.env.ACALA_RPC || 'https://eth-rpc-acala.aca-api.network',
klaytn: process.env.KLAYTN_RPC || 'https://klaytn-mainnet-rpc.allthatnode.com:8551',
celo: process.env.CELO_RPC || 'https://forno.celo.org',
moonbeam: process.env.MOONBEAM_RPC || 'https://rpc.ankr.com/moonbeam',
arbitrum: process.env.ARBITRUM_RPC || 'https://arb1.arbitrum.io/rpc',
optimism: process.env.OPTIMISM_RPC || 'https://rpc.ankr.com/optimism',
aptos: process.env.APTOS_RPC || 'https://fullnode.mainnet.aptoslabs.com/',
near: process.env.NEAR_RPC || 'https://rpc.mainnet.near.org',
xpla: process.env.XPLA_RPC || 'https://dimension-lcd.xpla.dev',
terra2: process.env.TERRA2_RPC || 'https://phoenix-lcd.terra.dev',
// terra: 'https://columbus-fcd.terra.dev',
terra: process.env.TERRA_RPC || 'https://terra-classic-fcd.publicnode.com',
injective: process.env.INJECTIVE_RPC || 'https://api.injective.network',
solana: process.env.SOLANA_RPC || 'https://api.mainnet-beta.solana.com',
sui: process.env.SUI_RPC || 'https://rpc.mainnet.sui.io',
base: process.env.BASE_RPC || 'https://developer-access-mainnet.base.org',
sei: process.env.SEI_RPC || 'https://sei-rest.brocha.in', // https://docs.sei.io/develop/resources
wormchain: process.env.WORMCHAIN_RPC || 'https://wormchain-rpc.quickapi.com',
export const RPCS_BY_CHAIN: { [key in NETWORK]: { [key in ChainName]?: string } } = {
[NETWORK.MAINNET]: {
ethereum: process.env.ETH_RPC,
bsc: process.env.BSC_RPC || 'https://rpc.ankr.com/bsc',
polygon: process.env.POLYGON_RPC || 'https://rpc.ankr.com/polygon',
avalanche: process.env.AVALANCHE_RPC || 'https://rpc.ankr.com/avalanche',
oasis: process.env.OASIS_RPC || 'https://emerald.oasis.dev',
algorand: process.env.ALGORAND_RPC || 'https://mainnet-api.algonode.cloud',
fantom: process.env.FANTOM_RPC || 'https://rpc.ankr.com/fantom',
karura: process.env.KARURA_RPC || 'https://eth-rpc-karura.aca-api.network',
acala: process.env.ACALA_RPC || 'https://eth-rpc-acala.aca-api.network',
klaytn: process.env.KLAYTN_RPC || 'https://klaytn-mainnet-rpc.allthatnode.com:8551',
celo: process.env.CELO_RPC || 'https://forno.celo.org',
moonbeam: process.env.MOONBEAM_RPC || 'https://rpc.ankr.com/moonbeam',
arbitrum: process.env.ARBITRUM_RPC || 'https://arb1.arbitrum.io/rpc',
optimism: process.env.OPTIMISM_RPC || 'https://rpc.ankr.com/optimism',
aptos: process.env.APTOS_RPC || 'https://fullnode.mainnet.aptoslabs.com/',
near: process.env.NEAR_RPC || 'https://rpc.mainnet.near.org',
xpla: process.env.XPLA_RPC || 'https://dimension-lcd.xpla.dev',
terra2: process.env.TERRA2_RPC || 'https://phoenix-lcd.terra.dev',
// terra: 'https://columbus-fcd.terra.dev',
terra: process.env.TERRA_RPC || 'https://terra-classic-fcd.publicnode.com',
injective: process.env.INJECTIVE_RPC || 'https://api.injective.network',
solana: process.env.SOLANA_RPC || 'https://api.mainnet-beta.solana.com',
sui: process.env.SUI_RPC || 'https://rpc.mainnet.sui.io',
base: process.env.BASE_RPC || 'https://developer-access-mainnet.base.org',
sei: process.env.SEI_RPC || 'https://sei-rest.brocha.in', // https://docs.sei.io/develop/resources
wormchain: process.env.WORMCHAIN_RPC || 'https://wormchain-rpc.quickapi.com',
},
[NETWORK.TESTNET]: {
ethereum: process.env.ETH_RPC,
bsc: process.env.BSC_RPC,
polygon: process.env.POLYGON_RPC || 'https://rpc.ankr.com/polygon_mumbai',
avalanche: process.env.AVALANCHE_RPC || 'https://rpc.ankr.com/avalanche_fuji',
oasis: process.env.OASIS_RPC || 'https://testnet.emerald.oasis.dev',
algorand: process.env.ALGORAND_RPC || 'https://testnet-api.algonode.cloud',
fantom: process.env.FANTOM_RPC,
karura: process.env.KARURA_RPC,
acala: process.env.ACALA_RPC || 'https://eth-rpc-acala-testnet.aca-staging.network',
klaytn: process.env.KLAYTN_RPC || 'https://rpc.ankr.com/klaytn_testnet',
celo: process.env.CELO_RPC || 'https://alfajores-forno.celo-testnet.org',
moonbeam: process.env.MOONBEAM_RPC,
arbitrum: process.env.ARBITRUM_RPC || 'https://sepolia-rollup.arbitrum.io/rpc',
optimism: process.env.OPTIMISM_RPC || 'https://optimism-goerli.publicnode.com',
aptos: process.env.APTOS_RPC,
near: process.env.NEAR_RPC,
xpla: process.env.XPLA_RPC || 'https://cube-lcd.xpla.dev',
terra2: process.env.TERRA2_RPC || 'https://pisco-lcd.terra.dev',
terra: process.env.TERRA_RPC,
injective: process.env.INJECTIVE_RPC,
solana: process.env.SOLANA_RPC,
sui: process.env.SUI_RPC,
base: process.env.BASE_RPC,
sei: process.env.SEI_RPC,
wormchain: process.env.WORMCHAIN_RPC,
},
};

// The following is obsolete, but I'm leaving it here for now in case we need it later.
// Separating for now so if we max out infura we can keep Polygon going
export const POLYGON_ROOT_CHAIN_RPC = 'https://rpc.ankr.com/eth';
export const POLYGON_ROOT_CHAIN_ADDRESS = '0x86E4Dc95c7FBdBf52e33D563BbDB00823894C287';
// Optimism watcher relies on finalized calls which don't work right on Ankr
export const OPTIMISM_CTC_CHAIN_RPC = process.env.ETH_RPC;
export const OPTIMISM_CTC_CHAIN_ADDRESS = '0x5E4e65926BA27467555EB562121fac00D24E9dD2';
export const POLYGON_ROOT_CHAIN_INFO: { [key in NETWORK]: PolygonRootChainInfo } = {
[NETWORK.MAINNET]: {
address: '0x86E4Dc95c7FBdBf52e33D563BbDB00823894C287',
rpc: 'https://rpc.ankr.com/eth',
},
[NETWORK.TESTNET]: {
address: '0x2890ba17efe978480615e330ecb65333b880928e',
rpc: 'https://rpc.ankr.com/eth', // TODO: Put testnet info here
},
};

export const ALGORAND_INFO = {
appid: Number(CONTRACTS.MAINNET.algorand.core),
algodToken: '',
algodServer: RPCS_BY_CHAIN.algorand,
algodPort: 443,
server: 'https://mainnet-idx.algonode.cloud',
port: 443,
token: '',
export const ALGORAND_INFO: { [key in NETWORK]: AlgorandInfo } = {
[NETWORK.MAINNET]: {
appid: Number(CONTRACTS.MAINNET.algorand.core),
algodToken: '',
algodServer: RPCS_BY_CHAIN[NETWORK.MAINNET].algorand
? RPCS_BY_CHAIN[NETWORK.MAINNET].algorand
: '',
algodPort: 443,
server: 'https://mainnet-idx.algonode.cloud',
port: 443,
token: '',
},
[NETWORK.TESTNET]: {
appid: Number(CONTRACTS.TESTNET.algorand.core),
algodToken: '',
algodServer: RPCS_BY_CHAIN[NETWORK.TESTNET].algorand
? RPCS_BY_CHAIN[NETWORK.TESTNET].algorand
: '',
algodPort: 443,
// TODO: Change to testnet info here;
server: 'https://testnet-idx.algonode.cloud',
port: 443,
token: '',
},
};

export const SEI_EXPLORER_GRAPHQL = 'https://pacific-1-graphql.alleslabs.dev/v1/graphql';
Expand All @@ -89,3 +141,18 @@ export const GUARDIAN_RPC_HOSTS = [
'https://wormhole-v2-mainnet-api.chainlayer.network',
'https://wormhole-v2-mainnet-api.staking.fund',
];

export type AlgorandInfo = {
appid: number;
algodToken: string;
algodServer: string;
algodPort: number;
server: string;
port: number;
token: string;
};

export type PolygonRootChainInfo = {
address: string;
rpc: string;
};
17 changes: 10 additions & 7 deletions watcher/src/databases/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { CHAIN_ID_SOLANA } from '@certusone/wormhole-sdk/lib/cjs/utils/consts';
import { expect, test } from '@jest/globals';
import { INITIAL_DEPLOYMENT_BLOCK_BY_CHAIN } from '@wormhole-foundation/wormhole-monitor-common';
import {
INITIAL_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN,
NETWORK,
} from '@wormhole-foundation/wormhole-monitor-common';
import { JsonDatabase } from '../JsonDatabase';
import { getResumeBlockByChain, initDb, makeBlockKey } from '../utils';

Expand All @@ -11,13 +14,13 @@ test('getResumeBlockByChain', async () => {
db.lastBlockByChain = { [CHAIN_ID_SOLANA]: blockKey };
// if a chain is in the database, that number should be returned
expect(await db.getLastBlockByChain('solana')).toEqual(fauxBlock);
expect(await getResumeBlockByChain('solana')).toEqual(Number(fauxBlock) + 1);
expect(await getResumeBlockByChain(NETWORK.MAINNET, 'solana')).toEqual(Number(fauxBlock) + 1);
// if a chain is not in the database, the initial deployment block should be returned
expect(INITIAL_DEPLOYMENT_BLOCK_BY_CHAIN.moonbeam).toBeDefined();
expect(await getResumeBlockByChain('moonbeam')).toEqual(
Number(INITIAL_DEPLOYMENT_BLOCK_BY_CHAIN.moonbeam)
expect(INITIAL_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN[NETWORK.MAINNET].moonbeam).toBeDefined();
expect(await getResumeBlockByChain(NETWORK.MAINNET, 'moonbeam')).toEqual(
Number(INITIAL_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN[NETWORK.MAINNET].moonbeam)
);
// if neither, null should be returned
expect(INITIAL_DEPLOYMENT_BLOCK_BY_CHAIN.unset).toBeUndefined();
expect(await getResumeBlockByChain('unset')).toEqual(null);
expect(INITIAL_DEPLOYMENT_BLOCK_BY_NETWORK_AND_CHAIN[NETWORK.MAINNET].unset).toBeUndefined();
expect(await getResumeBlockByChain(NETWORK.MAINNET, 'unset')).toEqual(null);
});
Loading

0 comments on commit 2571991

Please sign in to comment.