Browse Source

Relayer: Generic Relayer Guardian Changes for Merging into Main (#3041)

* gRelayer: surrounding files

* modification to get compilation

* restore devnet

* remove generic relayer docker

* remove wait for relayer engine

* keep build time 20

* sh -> bash

* sh -> bash

* Remove comment

* bash -> sh

* Revert "bash -> sh"

This reverts commit 5c37e92fa19bbdbefc79c8ee0dbceeb127c53373.

* bash->sh

* gRelayer: ethereum folder changes for generic-relayer-merge

* add eth-devnet

* Adds .github because workflow needs to install forge

* sdk-ci-tests need to install forge

* don't wait for nonexistent relayer engine

* update package.json and package-lock.json

* Remove unnecessary types from package.json

* ts-node

* gRelayer: ethereum folder changes for generic-relayer-merge

* sdk-ci-tests need to install forge

* don't wait for nonexistent relayer engine

* update package.json and package-lock.json

* remove these changes

* Relayer: Natspec documentation in IWormholeRelayer (#3032)

* WIP

* Fixes

* Updated interfaces

* remove bash

* Forward uses same refund chain id and refund address (#3034)

* WIP

* Fixes

* Forward uses same refund chain id and refund address

* Updated interfaces

* Adds .github because workflow needs to install forge

* sdk-ci-tests need to install forge

* don't wait for nonexistent relayer engine

* SDK minus payload tests

* Rename sdk relayer folder and file

* modify index.ts

* modify path

* sdk-ci-tests need to install forge

* don't wait for nonexistent relayer engine

* Add three governance VAA actions for generic relayers

* demandOption and const

* Remove forge build warnings

* Add note to interface for resend

* Verify additional VAAs in SDK

* via-ir on unless in Tilt

* Correct IWormholeReceiver interface

* Wormhole message fee now part of quoteDeliveryPrice (#3043)

* Fix to PR 3043

* Remove compiler warning

* Remove files

* remove generic relayer docker

* Fix typo

* Relayer/address drew review (#3060)

* Fix typo in Create2Factory

* Add event for contract upgrades

* Prevent registering contract if it is already registered

* Prevent allowing unset chainId for default delivery provider governance VAA

* memory to calldata for external functions in WormholeRelayerSend

* continue memory to calldata for external functions

* Fix pricing in delivery provider

* Sanity check new default delivery provider isn't 0 address

* Don't save vaaKey as local variable

* cache the length of array rather than iterate every time for vaaKeys

* Replacing memory with calldata in few locations

* Remove stale file DeliveryProviderMessages

* Remove batch VAA sender script

* Remove batch VAA from WormholeSimulator

* Wait for a confirmation in deploy scripts

* remove unnecessary comments

* Fix Delivery Provider Pricing and add a test

* remove console logs

* Revert "continue memory to calldata for external functions"

This reverts commit f322afb6c0bbd09e3d04ab42a90e592ff752f6bf.

* Revert "memory to calldata for external functions in WormholeRelayerSend"

This reverts commit 42fcaad8842d0c81506c9586d8d0fd98f6bb6ae1.

* Revert "Don't save vaaKey as local variable"

This reverts commit a9172379c564fd430a083645c1c42c78e014d68d.

* Revert "cache the length of array rather than iterate every time for vaaKeys"

This reverts commit d61380a9b0c0671e67e3bd5d874ae339e180dd34.

* Revert "Replacing memory with calldata in few locations"

This reverts commit 94e47b6e72eaaa52ac0ba2980c439180401fafd7.

* Revert "Fix typo in Create2Factory"

This reverts commit a9f7bdf461945c8abf020007d16bbc6b4301d051.

* Update contract addresses for via-ir

* Update register chain test to only do one registration

* Slight improvements to delivery provider implementation

* typed errors for delivery provider

* Update SDK to have via-ir devnet address

* Fix test

* enable VIA-IR in CI and not in Tilt

* Fix chain id

* get register chain test to work

* correct contract address for via ir

* update sdk consts for via ir address

* base 32 address

* merge

* -f to -r

* relay provider -> delivery provider

* fix await

* Readme changes
derpy-duck 2 years ago
parent
commit
3c0fecc3fa

+ 16 - 0
clients/js/README.md

@@ -240,6 +240,8 @@ Commands:
   worm generate upgrade                     Generate contract upgrade VAA
   worm generate upgrade                     Generate contract upgrade VAA
   worm generate attestation                 Generate a token attestation VAA
   worm generate attestation                 Generate a token attestation VAA
   worm generate recover-chain-id            Generate a recover chain ID VAA
   worm generate recover-chain-id            Generate a recover chain ID VAA
+  worm generate                             Sets the default delivery provider
+  set-default-delivery-provider             for the Wormhole Relayer contract
 
 
 Options:
 Options:
       --help                       Show help                           [boolean]
       --help                       Show help                           [boolean]
@@ -309,6 +311,8 @@ Commands:
   worm info upgrade                         Generate contract upgrade VAA
   worm info upgrade                         Generate contract upgrade VAA
   worm info attestation                     Generate a token attestation VAA
   worm info attestation                     Generate a token attestation VAA
   worm info recover-chain-id                Generate a recover chain ID VAA
   worm info recover-chain-id                Generate a recover chain ID VAA
+  worm info set-default-delivery-provider   Sets the default delivery provider
+                                            for the Wormhole Relayer contract
   worm info chain-id <chain>                Print the wormhole chain ID integer
   worm info chain-id <chain>                Print the wormhole chain ID integer
                                             associated with the specified chain
                                             associated with the specified chain
                                             name
                                             name
@@ -395,6 +399,8 @@ Commands:
   worm near upgrade                         Generate contract upgrade VAA
   worm near upgrade                         Generate contract upgrade VAA
   worm near attestation                     Generate a token attestation VAA
   worm near attestation                     Generate a token attestation VAA
   worm near recover-chain-id                Generate a recover chain ID VAA
   worm near recover-chain-id                Generate a recover chain ID VAA
+  worm near set-default-delivery-provider   Sets the default delivery provider
+                                            for the Wormhole Relayer contract
   worm near chain-id <chain>                Print the wormhole chain ID integer
   worm near chain-id <chain>                Print the wormhole chain ID integer
                                             associated with the specified chain
                                             associated with the specified chain
                                             name
                                             name
@@ -495,6 +501,8 @@ Commands:
   worm parse <vaa> upgrade                  Generate contract upgrade VAA
   worm parse <vaa> upgrade                  Generate contract upgrade VAA
   worm parse <vaa> attestation              Generate a token attestation VAA
   worm parse <vaa> attestation              Generate a token attestation VAA
   worm parse <vaa> recover-chain-id         Generate a recover chain ID VAA
   worm parse <vaa> recover-chain-id         Generate a recover chain ID VAA
+  worm parse <vaa>                          Sets the default delivery provider
+  set-default-delivery-provider             for the Wormhole Relayer contract
   worm parse <vaa> chain-id <chain>         Print the wormhole chain ID integer
   worm parse <vaa> chain-id <chain>         Print the wormhole chain ID integer
                                             associated with the specified chain
                                             associated with the specified chain
                                             name
                                             name
@@ -607,6 +615,8 @@ Commands:
   attestation
   attestation
   worm recover <digest> <signature>         Generate a recover chain ID VAA
   worm recover <digest> <signature>         Generate a recover chain ID VAA
   recover-chain-id
   recover-chain-id
+  worm recover <digest> <signature>         Sets the default delivery provider
+  set-default-delivery-provider             for the Wormhole Relayer contract
   worm recover <digest> <signature>         Print the wormhole chain ID integer
   worm recover <digest> <signature>         Print the wormhole chain ID integer
   chain-id <chain>                          associated with the specified chain
   chain-id <chain>                          associated with the specified chain
                                             name
                                             name
@@ -712,6 +722,8 @@ Commands:
   worm submit <vaa> upgrade                 Generate contract upgrade VAA
   worm submit <vaa> upgrade                 Generate contract upgrade VAA
   worm submit <vaa> attestation             Generate a token attestation VAA
   worm submit <vaa> attestation             Generate a token attestation VAA
   worm submit <vaa> recover-chain-id        Generate a recover chain ID VAA
   worm submit <vaa> recover-chain-id        Generate a recover chain ID VAA
+  worm submit <vaa>                         Sets the default delivery provider
+  set-default-delivery-provider             for the Wormhole Relayer contract
   worm submit <vaa> chain-id <chain>        Print the wormhole chain ID integer
   worm submit <vaa> chain-id <chain>        Print the wormhole chain ID integer
                                             associated with the specified chain
                                             associated with the specified chain
                                             name
                                             name
@@ -825,6 +837,8 @@ Commands:
   worm sui upgrade                          Generate contract upgrade VAA
   worm sui upgrade                          Generate contract upgrade VAA
   worm sui attestation                      Generate a token attestation VAA
   worm sui attestation                      Generate a token attestation VAA
   worm sui recover-chain-id                 Generate a recover chain ID VAA
   worm sui recover-chain-id                 Generate a recover chain ID VAA
+  worm sui set-default-delivery-provider    Sets the default delivery provider
+                                            for the Wormhole Relayer contract
   worm sui chain-id <chain>                 Print the wormhole chain ID integer
   worm sui chain-id <chain>                 Print the wormhole chain ID integer
                                             associated with the specified chain
                                             associated with the specified chain
                                             name
                                             name
@@ -959,6 +973,8 @@ Commands:
   worm verify-vaa upgrade                   Generate contract upgrade VAA
   worm verify-vaa upgrade                   Generate contract upgrade VAA
   worm verify-vaa attestation               Generate a token attestation VAA
   worm verify-vaa attestation               Generate a token attestation VAA
   worm verify-vaa recover-chain-id          Generate a recover chain ID VAA
   worm verify-vaa recover-chain-id          Generate a recover chain ID VAA
+  worm verify-vaa                           Sets the default delivery provider
+  set-default-delivery-provider             for the Wormhole Relayer contract
   worm verify-vaa chain-id <chain>          Print the wormhole chain ID integer
   worm verify-vaa chain-id <chain>          Print the wormhole chain ID integer
                                             associated with the specified chain
                                             associated with the specified chain
                                             name
                                             name

+ 2 - 0
clients/js/src/algorand.ts

@@ -119,6 +119,8 @@ export async function execute_algorand(
 
 
       break;
       break;
     }
     }
+    case "WormholeRelayer":
+        throw Error("Wormhole Relayer not supported on Algorand");
     default:
     default:
       target_contract = impossible(payload);
       target_contract = impossible(payload);
   }
   }

+ 2 - 0
clients/js/src/aptos.ts

@@ -229,6 +229,8 @@ export async function execute_aptos(
 
 
       break;
       break;
     }
     }
+    case "WormholeRelayer":
+      throw Error("Wormhole Relayer not supported on Aptos");
     default:
     default:
       impossible(payload);
       impossible(payload);
   }
   }

+ 2 - 0
clients/js/src/chains/sei/submit.ts

@@ -119,6 +119,8 @@ export const submit = async (
 
 
       break;
       break;
     }
     }
+    case "WormholeRelayer":
+        throw Error("Wormhole Relayer not supported on Sei");
     default:
     default:
       target_contract = impossible(payload);
       target_contract = impossible(payload);
       execute_msg = impossible(payload);
       execute_msg = impossible(payload);

+ 2 - 0
clients/js/src/chains/sui/submit.ts

@@ -198,6 +198,8 @@ export const submit = async (
 
 
       break;
       break;
     }
     }
+    case "WormholeRelayer":
+        throw Error("Wormhole Relayer not supported on Sui");
     default:
     default:
       impossible(payload);
       impossible(payload);
   }
   }

+ 1 - 1
clients/js/src/cmds/evm.ts

@@ -194,7 +194,7 @@ export const builder = function (y: typeof yargs) {
       "Start a local EVM validator",
       "Start a local EVM validator",
       (yargs) => yargs.option("validator-args", VALIDATOR_OPTIONS),
       (yargs) => yargs.option("validator-args", VALIDATOR_OPTIONS),
       (argv) => {
       (argv) => {
-        const cmd = `cd ${homedir()} && npx ganache-cli -e 10000 --deterministic --time="1970-01-01T00:00:00+00:00"`;
+        const cmd = `cd ${homedir()} && npx ganache-cli --wallet.defaultBalance 10000 --wallet.deterministic --chain.time="1970-01-01T00:00:00+00:00"`;
         runCommand(cmd, argv["validator-args"]);
         runCommand(cmd, argv["validator-args"]);
       }
       }
     )
     )

+ 42 - 5
clients/js/src/cmds/generate.ts

@@ -23,6 +23,7 @@ import {
   sign,
   sign,
   TokenBridgeAttestMeta,
   TokenBridgeAttestMeta,
   VAA,
   VAA,
+  WormholeRelayerSetDefaultDeliveryProvider,
 } from "../vaa";
 } from "../vaa";
 
 
 function makeVAA(
 function makeVAA(
@@ -78,10 +79,11 @@ export const builder = function (y: typeof yargs) {
             })
             })
             .option("module", {
             .option("module", {
               alias: "m",
               alias: "m",
-              describe: "Module to upgrade",
-              choices: ["NFTBridge", "TokenBridge"],
+              describe: "Module to register",
+              choices: ["NFTBridge", "TokenBridge", "WormholeRelayer"],
               demandOption: true,
               demandOption: true,
-            } as const),
+            } as const)
+        ,
         (argv) => {
         (argv) => {
           const module = argv["module"];
           const module = argv["module"];
           assertChain(argv.chain);
           assertChain(argv.chain);
@@ -122,7 +124,7 @@ export const builder = function (y: typeof yargs) {
             .option("module", {
             .option("module", {
               alias: "m",
               alias: "m",
               describe: "Module to upgrade",
               describe: "Module to upgrade",
-              choices: ["Core", "NFTBridge", "TokenBridge"],
+              choices: ["Core", "NFTBridge", "TokenBridge", "WormholeRelayer"],
               demandOption: true,
               demandOption: true,
             } as const),
             } as const),
         (argv) => {
         (argv) => {
@@ -221,7 +223,7 @@ export const builder = function (y: typeof yargs) {
           yargs
           yargs
             .option("module", {
             .option("module", {
               alias: "m",
               alias: "m",
-              describe: "Module to upgrade",
+              describe: "Module to recover",
               choices: ["Core", "NFTBridge", "TokenBridge"],
               choices: ["Core", "NFTBridge", "TokenBridge"],
               demandOption: true,
               demandOption: true,
             } as const)
             } as const)
@@ -254,6 +256,41 @@ export const builder = function (y: typeof yargs) {
           console.log(serialiseVAA(vaa));
           console.log(serialiseVAA(vaa));
         }
         }
       )
       )
+      .command(
+        "set-default-delivery-provider",
+        "Sets the default delivery provider for the Wormhole Relayer contract",
+        (yargs) => {
+          return yargs
+            .option("chain", {
+              alias: "c",
+              describe: "Chain of Wormhole Relayer contract",
+              choices: Object.keys(CHAINS),
+              demandOption: true,
+            } as const)
+            .option("delivery-provider-address", {
+              alias: "p",
+              describe: "Address of the delivery provider contract",
+              type: "string",
+              demandOption: true,
+            })
+        },
+        (argv) => {
+          assertChain(argv.chain);
+          const payload: WormholeRelayerSetDefaultDeliveryProvider = {
+            module: "WormholeRelayer",
+            type: "SetDefaultDeliveryProvider",
+            chain: toChainId(argv["chain"]),
+            relayProviderAddress: parseAddress(argv["chain"], argv["delivery-provider-address"])
+          };
+          let v = makeVAA(
+            GOVERNANCE_CHAIN,
+            GOVERNANCE_EMITTER,
+            argv["guardian-secret"].split(","),
+            payload
+          );
+          console.log(serialiseVAA(v));
+        }
+      )
   );
   );
 };
 };
 export const handler = () => {};
 export const handler = () => {};

+ 30 - 0
clients/js/src/evm.ts

@@ -429,6 +429,36 @@ export async function execute_evm(
 
 
       break;
       break;
     }
     }
+    case "WormholeRelayer":
+        // TODO: Try to get contract address from SDK if it is undefined
+        // Needs SDK to be published with Wormhole Relayer contract addresses
+        if (contract_address === undefined) {
+          throw Error(`Unknown Wormhole Relayer contract on ${network} for ${chain}`)
+        }
+       // let rb = ethers_contracts.WormholeRelayer__factory.connect(contract_address, signer)
+        switch (payload.type) {
+          case "ContractUpgrade":
+            console.log("Upgrading contract")
+            console.log("Error: The published NPM SDK doesn't have the typechain binding for WormholeRelayer yet")
+            //console.log("Hash: " + (await rb.submitContractUpgrade(vaa, overrides)).hash)
+            console.log("Don't forget to verify the new implementation! See ethereum/VERIFY.md for instructions")
+            break
+          case "RegisterChain":
+            console.log("Registering chain")
+            console.log("Error: The published NPM SDK doesn't have the typechain binding for WormholeRelayer yet")
+            //console.log("Hash: " + (await rb.registerWormholeRelayerContract(vaa, overrides)).hash)
+            break
+          case "SetDefaultDeliveryProvider":
+            console.log("Setting default relay provider")
+            console.log("Error: The published NPM SDK doesn't have the typechain binding for WormholeRelayer yet")
+            //console.log("Hash: " + (await rb.setDefaultDeliveryProvider(vaa, overrides)).hash)
+            break
+          default:
+            impossible(payload)
+            break
+  
+        }
+        break
     default:
     default:
       impossible(payload);
       impossible(payload);
   }
   }

+ 2 - 0
clients/js/src/injective.ts

@@ -136,6 +136,8 @@ export async function execute_injective(
 
 
       break;
       break;
     }
     }
+    case "WormholeRelayer":
+      throw Error("Wormhole Relayer not supported on Injective");
     default:
     default:
       action = impossible(payload);
       action = impossible(payload);
       target_contract = impossible(payload);
       target_contract = impossible(payload);

+ 2 - 0
clients/js/src/near.ts

@@ -99,6 +99,8 @@ export const execute_near = async (
 
 
       break;
       break;
     }
     }
+    case "WormholeRelayer":
+      throw Error("Wormhole Relayer not supported on Near");
     default:
     default:
       impossible(payload);
       impossible(payload);
   }
   }

+ 2 - 0
clients/js/src/solana.ts

@@ -185,6 +185,8 @@ export async function execute_solana(
           break;
           break;
       }
       }
       break;
       break;
+    case "WormholeRelayer":
+      throw Error("Wormhole Relayer not supported on Solana");
     default:
     default:
       ix = impossible(v.payload);
       ix = impossible(v.payload);
   }
   }

+ 2 - 0
clients/js/src/terra.ts

@@ -138,6 +138,8 @@ export async function execute_terra(
 
 
       break;
       break;
     }
     }
+    case "WormholeRelayer":
+        throw Error("Wormhole Relayer not supported on Terra");
     default:
     default:
       target_contract = impossible(payload);
       target_contract = impossible(payload);
       execute_msg = impossible(payload);
       execute_msg = impossible(payload);

+ 77 - 9
clients/js/src/vaa.ts

@@ -64,8 +64,10 @@ export type Payload =
     | CoreContractUpgrade
     | CoreContractUpgrade
     | PortalContractUpgrade<"TokenBridge">
     | PortalContractUpgrade<"TokenBridge">
     | PortalContractUpgrade<"NFTBridge">
     | PortalContractUpgrade<"NFTBridge">
+    | PortalContractUpgrade<"WormholeRelayer">
     | PortalRegisterChain<"TokenBridge">
     | PortalRegisterChain<"TokenBridge">
     | PortalRegisterChain<"NFTBridge">
     | PortalRegisterChain<"NFTBridge">
+    | PortalRegisterChain<"WormholeRelayer">
     | TokenBridgeTransfer
     | TokenBridgeTransfer
     | TokenBridgeTransferWithPayload
     | TokenBridgeTransferWithPayload
     | TokenBridgeAttestMeta
     | TokenBridgeAttestMeta
@@ -73,11 +75,13 @@ export type Payload =
     | CoreContractRecoverChainId
     | CoreContractRecoverChainId
     | PortalContractRecoverChainId<"TokenBridge">
     | PortalContractRecoverChainId<"TokenBridge">
     | PortalContractRecoverChainId<"NFTBridge">
     | PortalContractRecoverChainId<"NFTBridge">
+    | WormholeRelayerSetDefaultDeliveryProvider
 
 
 export type ContractUpgrade =
 export type ContractUpgrade =
     CoreContractUpgrade
     CoreContractUpgrade
     | PortalContractUpgrade<"TokenBridge">
     | PortalContractUpgrade<"TokenBridge">
     | PortalContractUpgrade<"NFTBridge">
     | PortalContractUpgrade<"NFTBridge">
+    | PortalContractUpgrade<"WormholeRelayer">
 
 
 export type RecoverChainId =
 export type RecoverChainId =
     CoreContractRecoverChainId
     CoreContractRecoverChainId
@@ -90,8 +94,10 @@ export function parse(buffer: Buffer): VAA<Payload | Other> {
         .or(coreContractUpgradeParser)
         .or(coreContractUpgradeParser)
         .or(portalContractUpgradeParser("TokenBridge"))
         .or(portalContractUpgradeParser("TokenBridge"))
         .or(portalContractUpgradeParser("NFTBridge"))
         .or(portalContractUpgradeParser("NFTBridge"))
+        .or(portalContractUpgradeParser("WormholeRelayer"))
         .or(portalRegisterChainParser("TokenBridge"))
         .or(portalRegisterChainParser("TokenBridge"))
         .or(portalRegisterChainParser("NFTBridge"))
         .or(portalRegisterChainParser("NFTBridge"))
+        .or(portalRegisterChainParser("WormholeRelayer"))
         .or(tokenBridgeTransferParser())
         .or(tokenBridgeTransferParser())
         .or(tokenBridgeTransferWithPayloadParser())
         .or(tokenBridgeTransferWithPayloadParser())
         .or(tokenBridgeAttestMetaParser())
         .or(tokenBridgeAttestMetaParser())
@@ -99,6 +105,7 @@ export function parse(buffer: Buffer): VAA<Payload | Other> {
         .or(coreContractRecoverChainId())
         .or(coreContractRecoverChainId())
         .or(portalContractRecoverChainId("TokenBridge"))
         .or(portalContractRecoverChainId("TokenBridge"))
         .or(portalContractRecoverChainId("NFTBridge"))
         .or(portalContractRecoverChainId("NFTBridge"))
+        .or(wormholeRelayerSetDefaultDeliveryProvider())
     let payload : Payload | Other | null = parser.parse(vaa.payload)
     let payload : Payload | Other | null = parser.parse(vaa.payload)
     if (payload === null) {
     if (payload === null) {
         payload = {type: "Other", hex: Buffer.from(vaa.payload).toString("hex"), ascii: Buffer.from(vaa.payload).toString('utf8')}
         payload = {type: "Other", hex: Buffer.from(vaa.payload).toString("hex"), ascii: Buffer.from(vaa.payload).toString('utf8')}
@@ -255,6 +262,22 @@ function vaaBody(vaa: VAA<Payload | Other>) {
                         break
                         break
                 }
                 }
                 break
                 break
+            case "WormholeRelayer":
+                switch (payload.type) {
+                    case "ContractUpgrade":
+                        payload_str = serialisePortalContractUpgrade(payload)
+                        break
+                    case "RegisterChain":
+                        payload_str = serialisePortalRegisterChain(payload)
+                        break
+                    case "SetDefaultDeliveryProvider":
+                        payload_str = serialiseWormholeRelayerSetDefaultDeliveryProvider(payload)
+                        break
+                    default:
+                        impossible(payload)
+                        break
+                }
+                break
             default:
             default:
                 impossible(payload)
                 impossible(payload)
                 break
                 break
@@ -395,7 +418,7 @@ function serialiseCoreContractUpgrade(payload: CoreContractUpgrade): string {
     return body.join("")
     return body.join("")
 }
 }
 
 
-export interface PortalContractUpgrade<Module extends "NFTBridge" | "TokenBridge"> {
+export interface PortalContractUpgrade<Module extends "NFTBridge" | "TokenBridge" | "WormholeRelayer"> {
     module: Module
     module: Module
     type: "ContractUpgrade"
     type: "ContractUpgrade"
     chain: number
     chain: number
@@ -403,7 +426,7 @@ export interface PortalContractUpgrade<Module extends "NFTBridge" | "TokenBridge
 }
 }
 
 
 // Parse a portal contract upgrade payload
 // Parse a portal contract upgrade payload
-function portalContractUpgradeParser<Module extends "NFTBridge" | "TokenBridge">(module: Module): P<PortalContractUpgrade<Module>> {
+function portalContractUpgradeParser<Module extends "NFTBridge" | "TokenBridge" | "WormholeRelayer">(module: Module): P<PortalContractUpgrade<Module>> {
     return new P(new Parser()
     return new P(new Parser()
         .endianess("big")
         .endianess("big")
         .string("module", {
         .string("module", {
@@ -428,7 +451,7 @@ function portalContractUpgradeParser<Module extends "NFTBridge" | "TokenBridge">
         }))
         }))
 }
 }
 
 
-function serialisePortalContractUpgrade<Module extends "NFTBridge" | "TokenBridge">(payload: PortalContractUpgrade<Module>): string {
+function serialisePortalContractUpgrade<Module extends "NFTBridge" | "TokenBridge" | "WormholeRelayer">(payload: PortalContractUpgrade<Module>): string {
     const body = [
     const body = [
         encode("bytes32", encodeString(payload.module)),
         encode("bytes32", encodeString(payload.module)),
         encode("uint8", 2),
         encode("uint8", 2),
@@ -441,7 +464,7 @@ function serialisePortalContractUpgrade<Module extends "NFTBridge" | "TokenBridg
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 // Registrations
 // Registrations
 
 
-export interface PortalRegisterChain<Module extends "NFTBridge" | "TokenBridge"> {
+export interface PortalRegisterChain<Module extends "NFTBridge" | "TokenBridge" | "WormholeRelayer"> {
     module: Module
     module: Module
     type: "RegisterChain"
     type: "RegisterChain"
     chain: number
     chain: number
@@ -450,7 +473,7 @@ export interface PortalRegisterChain<Module extends "NFTBridge" | "TokenBridge">
 }
 }
 
 
 // Parse a portal chain registration payload
 // Parse a portal chain registration payload
-function portalRegisterChainParser<Module extends "NFTBridge" | "TokenBridge">(module: Module): P<PortalRegisterChain<Module>> {
+function portalRegisterChainParser<Module extends "NFTBridge" | "TokenBridge" | "WormholeRelayer">(module: Module): P<PortalRegisterChain<Module>> {
     return new P(new Parser()
     return new P(new Parser()
         .endianess("big")
         .endianess("big")
         .string("module", {
         .string("module", {
@@ -477,7 +500,7 @@ function portalRegisterChainParser<Module extends "NFTBridge" | "TokenBridge">(m
     )
     )
 }
 }
 
 
-function serialisePortalRegisterChain<Module extends "NFTBridge" | "TokenBridge">(payload: PortalRegisterChain<Module>): string {
+function serialisePortalRegisterChain<Module extends "NFTBridge" | "TokenBridge" | "WormholeRelayer">(payload: PortalRegisterChain<Module>): string {
     const body = [
     const body = [
         encode("bytes32", encodeString(payload.module)),
         encode("bytes32", encodeString(payload.module)),
         encode("uint8", 1),
         encode("uint8", 1),
@@ -534,7 +557,7 @@ function serialiseCoreContractRecoverChainId(payload: CoreContractRecoverChainId
     return body.join("")
     return body.join("")
 }
 }
 
 
-export interface PortalContractRecoverChainId<Module extends "NFTBridge" | "TokenBridge"> {
+export interface PortalContractRecoverChainId<Module extends "NFTBridge" | "TokenBridge" | "WormholeRelayer"> {
     module: Module
     module: Module
     type: "RecoverChainId"
     type: "RecoverChainId"
     evmChainId: bigint
     evmChainId: bigint
@@ -542,7 +565,7 @@ export interface PortalContractRecoverChainId<Module extends "NFTBridge" | "Toke
 }
 }
 
 
 // Parse a portal contract recoverChainId payload
 // Parse a portal contract recoverChainId payload
-function portalContractRecoverChainId<Module extends "NFTBridge" | "TokenBridge">(module: Module): P<PortalContractRecoverChainId<Module>> {
+function portalContractRecoverChainId<Module extends "NFTBridge" | "TokenBridge" | "WormholeRelayer">(module: Module): P<PortalContractRecoverChainId<Module>> {
     return new P(new Parser()
     return new P(new Parser()
         .endianess("big")
         .endianess("big")
         .string("module", {
         .string("module", {
@@ -567,7 +590,7 @@ function portalContractRecoverChainId<Module extends "NFTBridge" | "TokenBridge"
         }))
         }))
 }
 }
 
 
-function serialisePortalContractRecoverChainId<Module extends "NFTBridge" | "TokenBridge">(payload: PortalContractRecoverChainId<Module>): string {
+function serialisePortalContractRecoverChainId<Module extends "NFTBridge" | "TokenBridge" | "WormholeRelayer">(payload: PortalContractRecoverChainId<Module>): string {
     const body = [
     const body = [
         encode("bytes32", encodeString(payload.module)),
         encode("bytes32", encodeString(payload.module)),
         encode("uint8", 3),
         encode("uint8", 3),
@@ -862,6 +885,51 @@ function serialiseNFTBridgeTransfer(payload: NFTBridgeTransfer): string {
     return body.join("")
     return body.join("")
 }
 }
 
 
+////////////////////////////////////////////////////////////////////////////////
+// WormholeRelayer
+export interface WormholeRelayerSetDefaultDeliveryProvider {
+    module: "WormholeRelayer"
+    type: "SetDefaultDeliveryProvider"
+    relayProviderAddress: string
+    chain: number
+}
+
+function wormholeRelayerSetDefaultDeliveryProvider(): P<WormholeRelayerSetDefaultDeliveryProvider> {
+    return new P(new Parser()
+        .endianess("big")
+        .string("module", {
+            length: 32,
+            encoding: "hex",
+            assert: Buffer.from("WormholeRelayer").toString("hex").padStart(64, "0"),
+            formatter: (_str: string) => "WormholeRelayer"
+        })
+        .uint8("type", {
+            assert: 3,
+            formatter: (_action) => "SetDefaultDeliveryProvider"
+        })
+        .uint16("chain")
+        .array("relayProviderAddress", {
+            type: "uint8",
+            lengthInBytes: 32,
+            formatter: (arr) => "0x" + Buffer.from(arr).toString("hex")
+        })
+        .string("end", {
+            greedy: true,
+            assert: str => str === ""
+        })
+    )
+}
+
+function serialiseWormholeRelayerSetDefaultDeliveryProvider(payload: WormholeRelayerSetDefaultDeliveryProvider): string {
+    const body = [
+        encode("bytes32", encodeString(payload.module)),
+        encode("uint8", 3),
+        encode("uint16", payload.chain),
+        encode("bytes32", hex(payload.relayProviderAddress)),
+    ]
+    return body.join("")
+}
+
 // This function should be called after pattern matching on all possible options
 // This function should be called after pattern matching on all possible options
 // of an enum (union) type, so that typescript can derive that no other options
 // of an enum (union) type, so that typescript can derive that no other options
 // are possible.  If (from JavaScript land) an unsupported argument is passed
 // are possible.  If (from JavaScript land) an unsupported argument is passed

+ 2 - 0
clients/js/src/xpla.ts

@@ -132,6 +132,8 @@ export async function execute_xpla(
 
 
       break;
       break;
     }
     }
+    case "WormholeRelayer":
+        throw Error("Wormhole Relayer not supported on Xpla");
     default:
     default:
       target_contract = impossible(payload);
       target_contract = impossible(payload);
       execute_msg = impossible(payload);
       execute_msg = impossible(payload);

+ 43 - 0
node/cmd/guardiand/admintemplate.go

@@ -73,6 +73,9 @@ func init() {
 	AdminClientTokenBridgeUpgradeContractCmd.Flags().AddFlagSet(moduleFlagSet)
 	AdminClientTokenBridgeUpgradeContractCmd.Flags().AddFlagSet(moduleFlagSet)
 	TemplateCmd.AddCommand(AdminClientTokenBridgeUpgradeContractCmd)
 	TemplateCmd.AddCommand(AdminClientTokenBridgeUpgradeContractCmd)
 
 
+	AdminClientWormholeRelayerSetDefaultDeliveryProviderCmd.Flags().AddFlagSet(governanceFlagSet)
+	TemplateCmd.AddCommand(AdminClientWormholeRelayerSetDefaultDeliveryProviderCmd)
+
 	circleIntegrationChainIDFlagSet := pflag.NewFlagSet("circle-integ", pflag.ExitOnError)
 	circleIntegrationChainIDFlagSet := pflag.NewFlagSet("circle-integ", pflag.ExitOnError)
 	circleIntegrationChainID = circleIntegrationChainIDFlagSet.String("chain-id", "", "Target chain ID")
 	circleIntegrationChainID = circleIntegrationChainIDFlagSet.String("chain-id", "", "Target chain ID")
 
 
@@ -195,6 +198,12 @@ var AdminClientIbcReceiverUpdateChannelChainCmd = &cobra.Command{
 	Run:   runIbcReceiverUpdateChannelChainTemplate,
 	Run:   runIbcReceiverUpdateChannelChainTemplate,
 }
 }
 
 
+var AdminClientWormholeRelayerSetDefaultDeliveryProviderCmd = &cobra.Command{
+	Use:   "wormhole-relayer-set-default-relay-provider",
+	Short: "Generate a 'set default relay provider' template for specified chain and address",
+	Run:   runWormholeRelayerSetDefaultDeliveryProviderTemplate,
+}
+
 func runGuardianSetTemplate(cmd *cobra.Command, args []string) {
 func runGuardianSetTemplate(cmd *cobra.Command, args []string) {
 	// Use deterministic devnet addresses as examples in the template, such that this doubles as a test fixture.
 	// Use deterministic devnet addresses as examples in the template, such that this doubles as a test fixture.
 	guardians := make([]*nodev1.GuardianSetUpdate_Guardian, *setUpdateNumGuardians)
 	guardians := make([]*nodev1.GuardianSetUpdate_Guardian, *setUpdateNumGuardians)
@@ -616,6 +625,40 @@ func runIbcReceiverUpdateChannelChainTemplate(cmd *cobra.Command, args []string)
 		},
 		},
 	}
 	}
 
 
+	b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
+	if err != nil {
+		panic(err)
+	}
+	fmt.Print(string(b))
+
+}
+
+func runWormholeRelayerSetDefaultDeliveryProviderTemplate(cmd *cobra.Command, args []string) {
+	address, err := parseAddress(*address)
+	if err != nil {
+		log.Fatal(err)
+	}
+	chainID, err := parseChainID(*chainID)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	m := &nodev1.InjectGovernanceVAARequest{
+		CurrentSetIndex: uint32(*templateGuardianIndex),
+		Messages: []*nodev1.GovernanceMessage{
+			{
+				Sequence: rand.Uint64(),
+				Nonce:    rand.Uint32(),
+				Payload: &nodev1.GovernanceMessage_WormholeRelayerSetDefaultDeliveryProvider{
+					WormholeRelayerSetDefaultDeliveryProvider: &nodev1.WormholeRelayerSetDefaultDeliveryProvider{
+						ChainId:                           uint32(chainID),
+						NewDefaultDeliveryProviderAddress: address,
+					},
+				},
+			},
+		},
+	}
+
 	b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
 	b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
 	if err != nil {
 	if err != nil {
 		panic(err)
 		panic(err)

+ 30 - 0
node/pkg/adminrpc/adminserver.go

@@ -413,6 +413,34 @@ func ibcReceiverUpdateChannelChain(
 	return v, nil
 	return v, nil
 }
 }
 
 
+// wormholeRelayerSetDefaultDeliveryProvider converts a nodev1.WormholeRelayerSetDefaultDeliveryProvider message to its canonical VAA representation.
+// Returns an error if the data is invalid.
+func wormholeRelayerSetDefaultDeliveryProvider(req *nodev1.WormholeRelayerSetDefaultDeliveryProvider, timestamp time.Time, guardianSetIndex uint32, nonce uint32, sequence uint64) (*vaa.VAA, error) {
+	if req.ChainId > math.MaxUint16 {
+		return nil, errors.New("invalid target_chain_id")
+	}
+
+	b, err := hex.DecodeString(req.NewDefaultDeliveryProviderAddress)
+	if err != nil {
+		return nil, errors.New("invalid new default relay provider address (expected hex)")
+	}
+
+	if len(b) != 32 {
+		return nil, errors.New("invalid new default relay provider address (expected 32 bytes)")
+	}
+
+	NewDefaultDeliveryProviderAddress := vaa.Address{}
+	copy(NewDefaultDeliveryProviderAddress[:], b)
+
+	v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
+		vaa.BodyWormholeRelayerSetDefaultDeliveryProvider{
+			ChainID:                           vaa.ChainID(req.ChainId),
+			NewDefaultDeliveryProviderAddress: NewDefaultDeliveryProviderAddress,
+		}.Serialize())
+
+	return v, nil
+}
+
 func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, timestamp time.Time) (*vaa.VAA, error) {
 func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, timestamp time.Time) (*vaa.VAA, error) {
 	var (
 	var (
 		v   *vaa.VAA
 		v   *vaa.VAA
@@ -444,6 +472,8 @@ func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, time
 		v, err = circleIntegrationUpgradeContractImplementation(payload.CircleIntegrationUpgradeContractImplementation, timestamp, currentSetIndex, message.Nonce, message.Sequence)
 		v, err = circleIntegrationUpgradeContractImplementation(payload.CircleIntegrationUpgradeContractImplementation, timestamp, currentSetIndex, message.Nonce, message.Sequence)
 	case *nodev1.GovernanceMessage_IbcReceiverUpdateChannelChain:
 	case *nodev1.GovernanceMessage_IbcReceiverUpdateChannelChain:
 		v, err = ibcReceiverUpdateChannelChain(payload.IbcReceiverUpdateChannelChain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
 		v, err = ibcReceiverUpdateChannelChain(payload.IbcReceiverUpdateChannelChain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
+	case *nodev1.GovernanceMessage_WormholeRelayerSetDefaultDeliveryProvider:
+		v, err = wormholeRelayerSetDefaultDeliveryProvider(payload.WormholeRelayerSetDefaultDeliveryProvider, timestamp, currentSetIndex, message.Nonce, message.Sequence)
 	default:
 	default:
 		panic(fmt.Sprintf("unsupported VAA type: %T", payload))
 		panic(fmt.Sprintf("unsupported VAA type: %T", payload))
 	}
 	}

File diff suppressed because it is too large
+ 440 - 349
node/pkg/proto/node/v1/node.pb.go


+ 11 - 1
proto/node/v1/node.proto

@@ -82,7 +82,7 @@ message GovernanceMessage {
     GuardianSetUpdate guardian_set = 10;
     GuardianSetUpdate guardian_set = 10;
     ContractUpgrade contract_upgrade = 11;
     ContractUpgrade contract_upgrade = 11;
 
 
-    // Token bridge and NFT module
+    // Token bridge, NFT module, and Wormhole Relayer module (for the first two) 
 
 
     BridgeRegisterChain bridge_register_chain = 12;
     BridgeRegisterChain bridge_register_chain = 12;
     BridgeUpgradeContract bridge_contract_upgrade = 13;
     BridgeUpgradeContract bridge_contract_upgrade = 13;
@@ -103,6 +103,8 @@ message GovernanceMessage {
 
 
     // IBC Receiver Integration
     // IBC Receiver Integration
     IbcReceiverUpdateChannelChain ibc_receiver_update_channel_chain = 21;
     IbcReceiverUpdateChannelChain ibc_receiver_update_channel_chain = 21;
+    // Wormhole Relayer module
+    WormholeRelayerSetDefaultDeliveryProvider wormhole_relayer_set_default_delivery_provider = 22;
   }
   }
 }
 }
 
 
@@ -248,6 +250,14 @@ message IbcReceiverUpdateChannelChain {
   uint32 chain_id = 3;
   uint32 chain_id = 3;
 }
 }
 
 
+message WormholeRelayerSetDefaultDeliveryProvider {
+  // ID of the chain of the Wormhole Relayer contract where the default delivery provider should be updated (uint16).
+  uint32 chain_id = 1;
+
+  // Hex-encoded address (without leading 0x) of the new default delivery provider contract address.
+  string new_default_delivery_provider_address = 2;
+}
+
 message FindMissingMessagesRequest {
 message FindMissingMessagesRequest {
   // Emitter chain ID to iterate.
   // Emitter chain ID to iterate.
   uint32 emitter_chain = 1;
   uint32 emitter_chain = 1;

+ 6 - 0
scripts/contract-upgrade-governance.sh

@@ -232,6 +232,12 @@ guardiand template token-bridge-upgrade-contract \\
     echo "\
     echo "\
 guardiand template token-bridge-upgrade-contract \\
 guardiand template token-bridge-upgrade-contract \\
   --chain-id $chain --module \"NFTBridge\" \\
   --chain-id $chain --module \"NFTBridge\" \\
+  --new-address $address"
+    ;;
+  wormhole_relayer)
+    echo "\
+guardiand template token-bridge-upgrade-contract \\
+  --chain-id $chain --module \"WormholeRelayer\" \\
   --new-address $address"
   --new-address $address"
     ;;
     ;;
   *) echo "unknown module $module" >&2
   *) echo "unknown module $module" >&2

+ 7 - 1
scripts/register-chain-governance.sh

@@ -36,7 +36,7 @@ Usage:
 
 
   where:
   where:
     -h  show this help text
     -h  show this help text
-    -m  module (TokenBridge, NFTBridge)
+    -m  module (TokenBridge, NFTBridge, WormholeRelayer)
     -c  chain name
     -c  chain name
     -a  emitter address (optional, derived by worm CLI by default)
     -a  emitter address (optional, derived by worm CLI by default)
     -o  multi-mode output directory
     -o  multi-mode output directory
@@ -122,6 +122,12 @@ guardiand template token-bridge-register-chain \\
     echo "\
     echo "\
 guardiand template token-bridge-register-chain \\
 guardiand template token-bridge-register-chain \\
   --chain-id $chain --module \"NFTBridge\" \\
   --chain-id $chain --module \"NFTBridge\" \\
+  --new-address $address"
+    ;;
+  WormholeRelayer)
+    echo "\
+guardiand template token-bridge-register-chain \\
+  --chain-id $chain --module \"WormholeRelayer\" \\
   --new-address $address"
   --new-address $address"
     ;;
     ;;
   *) echo "unknown module $module" >&2
   *) echo "unknown module $module" >&2

+ 23 - 0
sdk/vaa/payloads.go

@@ -32,6 +32,14 @@ var IbcReceiverModule = [32]byte{
 }
 }
 var IbcReceiverModuleStr = string(IbcReceiverModule[:])
 var IbcReceiverModuleStr = string(IbcReceiverModule[:])
 
 
+// WormholeRelayerModule is the identifier of the Wormhole Relayer module (which is used for governance messages).
+// It is the hex representation of "WormholeRelayer" left padded with zeroes.
+var WormholeRelayerModule = [32]byte{
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x57, 0x6f, 0x72, 0x6d, 0x68, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72,
+}
+var WormholeRelayerModuleStr = string(WormholeRelayerModule[:])
+
 type GovernanceAction uint8
 type GovernanceAction uint8
 
 
 var (
 var (
@@ -63,6 +71,9 @@ var (
 
 
 	// Ibc Receiver governance actions
 	// Ibc Receiver governance actions
 	IbcReceiverActionUpdateChannelChain GovernanceAction = 1
 	IbcReceiverActionUpdateChannelChain GovernanceAction = 1
+
+	// Wormhole relayer governance actions
+	WormholeRelayerSetDefaultDeliveryProvider GovernanceAction = 3
 )
 )
 
 
 type (
 type (
@@ -150,6 +161,12 @@ type (
 		ChannelId [64]byte
 		ChannelId [64]byte
 		ChainId   ChainID
 		ChainId   ChainID
 	}
 	}
+
+	// BodyWormholeRelayerSetDefaultDeliveryProvider is a governance message to set the default relay provider for the Wormhole Relayer.
+	BodyWormholeRelayerSetDefaultDeliveryProvider struct {
+		ChainID                           ChainID
+		NewDefaultDeliveryProviderAddress Address
+	}
 )
 )
 
 
 func (b BodyContractUpgrade) Serialize() []byte {
 func (b BodyContractUpgrade) Serialize() []byte {
@@ -258,6 +275,12 @@ func (r BodyIbcReceiverUpdateChannelChain) Serialize() []byte {
 	return serializeBridgeGovernanceVaa(IbcReceiverModuleStr, IbcReceiverActionUpdateChannelChain, r.TargetChainId, payload.Bytes())
 	return serializeBridgeGovernanceVaa(IbcReceiverModuleStr, IbcReceiverActionUpdateChannelChain, r.TargetChainId, payload.Bytes())
 }
 }
 
 
+func (r BodyWormholeRelayerSetDefaultDeliveryProvider) Serialize() []byte {
+	payload := &bytes.Buffer{}
+	payload.Write(r.NewDefaultDeliveryProviderAddress[:])
+	return serializeBridgeGovernanceVaa(WormholeRelayerModuleStr, WormholeRelayerSetDefaultDeliveryProvider, r.ChainID, payload.Bytes())
+}
+
 func serializeBridgeGovernanceVaa(module string, actionId GovernanceAction, chainId ChainID, payload []byte) []byte {
 func serializeBridgeGovernanceVaa(module string, actionId GovernanceAction, chainId ChainID, payload []byte) []byte {
 	buf := LeftPadBytes(module, 32)
 	buf := LeftPadBytes(module, 32)
 	// Write action ID
 	// Write action ID

+ 9 - 0
sdk/vaa/payloads_test.go

@@ -200,3 +200,12 @@ func FuzzLeftPadBytes(f *testing.F) {
 		assert.Equal(t, paddedPayload.Len(), length)
 		assert.Equal(t, paddedPayload.Len(), length)
 	})
 	})
 }
 }
+
+func TestBodyWormholeRelayerSetDefaultDeliveryProviderSerialize(t *testing.T) {
+	expected := "0000000000000000000000000000000000576f726d686f6c6552656c617965720300040000000000000000000000000000000000000000000000000000000000000004"
+	bodyWormholeRelayerSetDefaultDeliveryProvider := BodyWormholeRelayerSetDefaultDeliveryProvider{
+		ChainID:                           4,
+		NewDefaultDeliveryProviderAddress: addr,
+	}
+	assert.Equal(t, expected, hex.EncodeToString(bodyWormholeRelayerSetDefaultDeliveryProvider.Serialize()))
+}

Some files were not shown because too many files changed in this diff