Skip to content

Commit bce4fa0

Browse files
committed
cloud_functions: add alarming guardian heartbeats
1 parent 358dab0 commit bce4fa0

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

cloud_functions/scripts/deploy.sh

+6-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ if [ -z "$CLOUD_FUNCTIONS_BLOCK_INCREMENT" ]; then
6868
exit 1
6969
fi
7070

71+
if [ -z "$FIRESTORE_GUARDIAN_HEARTBEAT_COLLECTION" ]; then
72+
echo "FIRESTORE_GUARDIAN_HEARTBEAT_COLLECTION must be specified"
73+
exit 1
74+
fi
75+
7176
if [ -z "$FIRESTORE_LATEST_COLLECTION" ]; then
7277
echo "FIRESTORE_LATEST_COLLECTION must be specified"
7378
exit 1
@@ -121,7 +126,7 @@ fi
121126
# Context: Of all the cloud functions, there are some that only go into MAINNET and some that go into both MAINNET and TESTNET.
122127
# There are no cloud functions that only go into TESTNET.
123128
# First, deploy the functions that are common to both MAINNET and TESTNET
124-
gcloud functions --project "$GCP_PROJECT" deploy alarm-missing-vaas --entry-point alarmMissingVaas --gen2 --runtime nodejs18 --trigger-http --no-allow-unauthenticated --timeout 300 --memory 1GB --region europe-west3 --set-env-vars MISSING_VAA_SLACK_CHANNEL_ID=$MISSING_VAA_SLACK_CHANNEL_ID,MISSING_VAA_SLACK_POST_URL=$MISSING_VAA_SLACK_POST_URL,MISSING_VAA_SLACK_BOT_TOKEN=$MISSING_VAA_SLACK_BOT_TOKEN,FIRESTORE_ALARM_MISSING_VAAS_COLLECTION=$FIRESTORE_ALARM_MISSING_VAAS_COLLECTION,FIRESTORE_GOVERNOR_STATUS_COLLECTION=$FIRESTORE_GOVERNOR_STATUS_COLLECTION,FIRESTORE_LATEST_COLLECTION=$FIRESTORE_LATEST_COLLECTION,NETWORK=$NETWORK,FUNCTION=alarmMissingVaas
129+
gcloud functions --project "$GCP_PROJECT" deploy alarm-missing-vaas --entry-point alarmMissingVaas --gen2 --runtime nodejs18 --trigger-http --no-allow-unauthenticated --timeout 300 --memory 1GB --region europe-west3 --set-env-vars MISSING_VAA_SLACK_CHANNEL_ID=$MISSING_VAA_SLACK_CHANNEL_ID,MISSING_VAA_SLACK_POST_URL=$MISSING_VAA_SLACK_POST_URL,MISSING_VAA_SLACK_BOT_TOKEN=$MISSING_VAA_SLACK_BOT_TOKEN,FIRESTORE_ALARM_MISSING_VAAS_COLLECTION=$FIRESTORE_ALARM_MISSING_VAAS_COLLECTION,FIRESTORE_GOVERNOR_STATUS_COLLECTION=$FIRESTORE_GOVERNOR_STATUS_COLLECTION,FIRESTORE_LATEST_COLLECTION=$FIRESTORE_LATEST_COLLECTION,FIRESTORE_GUARDIAN_HEARTBEAT_COLLECTION=$FIRESTORE_GUARDIAN_HEARTBEAT_COLLECTION,NETWORK=$NETWORK,FUNCTION=alarmMissingVaas
125130
gcloud functions --project "$GCP_PROJECT" deploy compute-message-count-history --entry-point computeMessageCountHistory --gen2 --runtime nodejs18 --trigger-http --no-allow-unauthenticated --timeout 300 --memory 1GB --region europe-west3 --set-env-vars BIGTABLE_INSTANCE_ID=$BIGTABLE_INSTANCE_ID,BIGTABLE_SIGNED_VAAS_TABLE_ID=$BIGTABLE_SIGNED_VAAS_TABLE_ID,FIRESTORE_MESSAGE_COUNT_HISTORY_COLLECTION=$FIRESTORE_MESSAGE_COUNT_HISTORY_COLLECTION,NETWORK=$NETWORK,FUNCTION=computeMessageCountHistory
126131
gcloud functions --project "$GCP_PROJECT" deploy compute-message-counts --entry-point computeMessageCounts --gen2 --runtime nodejs18 --trigger-http --allow-unauthenticated --timeout 300 --memory 4GB --region europe-west3 --set-env-vars BIGTABLE_TABLE_ID=$BIGTABLE_TABLE_ID,BIGTABLE_INSTANCE_ID=$BIGTABLE_INSTANCE_ID,CLOUD_FUNCTIONS_REFRESH_TIME_INTERVAL=$CLOUD_FUNCTIONS_REFRESH_TIME_INTERVAL,NETWORK=$NETWORK,FUNCTION=computeMessageCounts
127132
gcloud functions --project "$GCP_PROJECT" deploy compute-missing-vaas --entry-point computeMissingVaas --gen2 --runtime nodejs18 --trigger-http --allow-unauthenticated --timeout 300 --memory 4GB --region europe-west3 --set-env-vars BIGTABLE_TABLE_ID=$BIGTABLE_TABLE_ID,BIGTABLE_INSTANCE_ID=$BIGTABLE_INSTANCE_ID,CLOUD_FUNCTIONS_REFRESH_TIME_INTERVAL=$CLOUD_FUNCTIONS_REFRESH_TIME_INTERVAL,NETWORK=$NETWORK,FUNCTION=computeMissingVaas

cloud_functions/src/alarmMissingVaas.ts

+37
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ export async function alarmMissingVaas(req: any, res: any) {
8888
// Alarm any watchers that are behind by more than 24 hours
8989
await alarmOldBlockTimes(refTimes);
9090

91+
// Alarm any guardians that have not sent a heartbeat in more than 1 hour
92+
await alarmOldHeartbeats();
93+
9194
// attempting to retrieve missing VAAs...
9295
const messages: MissingVaasByChain = await commonGetMissingVaas();
9396
if (messages) {
@@ -399,6 +402,40 @@ async function storeAlarmedChains(alarms: AlarmedChainTime[]): Promise<void> {
399402
await alarmedChains.set({ times: alarms });
400403
}
401404

405+
async function alarmOldHeartbeats(): Promise<void> {
406+
// Get Guardian Heartbeats from firestore
407+
const now: Date = new Date();
408+
const firestore = new Firestore();
409+
const collectionRef = firestore.collection(
410+
assertEnvironmentVariable('FIRESTORE_GUARDIAN_HEARTBEAT_COLLECTION')
411+
);
412+
const snapshot = await collectionRef.get();
413+
// Walk all the documents in the collection
414+
const documents = snapshot.docs;
415+
for (const doc of documents) {
416+
const data = doc.data();
417+
if (data) {
418+
// Only need to look at the timestamp field, which is in nanoseconds
419+
const timestamp: string = data.timestamp;
420+
// Convert the timestamp to a milliseconds
421+
const timestampMs: number = Math.floor(Number(timestamp) / 1_000_000);
422+
const heartbeatTime: Date = new Date(timestampMs);
423+
const deltaTime: number = (now.getTime() - heartbeatTime.getTime()) / (1000 * 60 * 60); // hours
424+
if (deltaTime >= 1) {
425+
// Send a message to slack
426+
const alarmSlackInfo: SlackInfo = {
427+
channelId: assertEnvironmentVariable('MISSING_VAA_SLACK_CHANNEL_ID'),
428+
postUrl: assertEnvironmentVariable('MISSING_VAA_SLACK_POST_URL'),
429+
botToken: assertEnvironmentVariable('MISSING_VAA_SLACK_BOT_TOKEN'),
430+
bannerTxt: 'Wormhole Missing VAA Alarm',
431+
msg: `The guardian ${doc.id} has not sent a heartbeat in ${deltaTime} hours.`,
432+
};
433+
await formatAndSendToSlack(alarmSlackInfo);
434+
}
435+
}
436+
}
437+
}
438+
402439
type FirestoreVAA = {
403440
chain: string;
404441
txHash: string;

0 commit comments

Comments
 (0)