wormhole/relayer/spy_relayer
Jeff Schroeder bb4d2ac206
Modular relayer support (#1266)
* Add the default backend for the relayer

Start to slowly split things out.

* Configure the backends when configuring the env

* First stab at the pluggable listener backend

* Update relayer example (and test) config

* relayer: JIT backend

* relayer: walletMonitor remove useless function

* relayer: update worker init() funcs

It is silly to accept a boolean in thing.init() vs just not running init
if you don't want to run thing.

* relayer: remove env property from Listener

It is verified in init() in spy_listener.ts and rest_listen.ts, so it can
be deferred to not require the import.

* relayer: clean up the main bits

Only try to init() something when it is actually supposed to run
per the cli flags.

* spy_relayer: more descriptive var name in main

* spy_relayer: Update relay worker with more docs

* spy_relayer: add targetChainName to WorkerInfo

This makes it easier to pretty print the chain name in the logs without
having to look the name up.

* spy_relayer: update logs and use the backend

* Use the Relayer interface's process() method in place of processVaa()
* Update the logs to include the chain name in the worker and auditor threads

* spy_relayer: remove processRequest()

It has been moved to the process() method of the default Relayer backend.

* spy_relayer: start fleshing out the Relayer default

* spy_relayer: fix a logic bug in checkQueue()

Co-authored-by: @swimricky

* spy_relayer: update TokenBridgeRelayer.process()

* Remove some extra logic
* Actually use the ChainId type since the id of 0 is in the sdk now

* spy_signature: add Relayer.runAuditor()

The auditor code is payload specific and needs to be with the backend.

* spy_relayer: move Relayer.runAuditor()

Make it part of the backend since the backend has all of the payload
specific logic into it.

* spy_relayer: move relay() --> Relayer.relay()

The actual relaying is part of the backend, so make it so.

* spy_relayer: add Relayer.runAuditor()

* spy_relayer: no more deprecated hexToNativeString

* spy_relayer: implement Relayer.targetChainId()

This is used for finding workable items in the incoming queue to toss
into the working queue.

* spy_relayer: remove relay.ts

The relay() function was moved to Relayer.relay()

* spy_relayer: more uses of deprecated hexToNativeString()

* spy_relayer: remove unused import

* spy_relayer: review feedback from @bruce-riley

* Fix some spelling tyops
* Simplify some logging
* Simplify a conditional for the payload version check

* spy_relayer: misc fixes and code clean up

* Fixed integration tests
* Added launch.json file for debugging in VS Code
* Updated to latest wormhole SDK
* Backup queue uses same key as redis
* Added Terra Classic flag
* Throttle potential infinite loop in audit thread
* Fixed spy service connection leak

Co-authored-by: Evan Gray <battledingo@gmail.com>
Co-authored-by: Kevin Peters <kpeters@jumptrading.com>
2022-08-05 10:20:36 -04:00
..
.vscode Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00
config/mainnet Add new emitter addresses to relayer config 2022-06-22 11:12:30 -04:00
src Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00
.env.sample Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00
.env.tilt.listener Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00
.env.tilt.relayer Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00
.env.tilt.wallet-monitor Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00
.gitignore Spy relayer cleanup (#1015) 2022-03-28 23:39:08 -04:00
Dockerfile Add the opencontainers source label to the relayer Dockerfile 2022-07-19 21:15:49 -04:00
README.md relayer/spy_relayer: update README 2022-07-18 09:39:58 -04:00
design.md Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00
jestconfig.json Spy relayer cleanup (#1015) 2022-03-28 23:39:08 -04:00
package-lock.json Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00
package.json Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00
tsconfig.json Modular relayer support (#1266) 2022-08-05 10:20:36 -04:00

README.md

Relayer

The wormhole relayer is designed to answer one main question:

Q: How do you transfer to a new wallet in a destination chain when you lack native tokens for paying gas fees?
A: You pay a little bit more on the source chain and use that to pay gas fees on the destination chain.

It was originally designed for payload version 1 token transfers, but should be extensible to other payload types as well.

Architecture

Component Description
Guardian Spy Connects to the wormhole p2p network and publishes all VAAs to a websocket
Spy Listener Filters VAAs from the Spy and adds them to the incoming queue in Redis
REST Listener Accepts HTTP requests to relay VAAs and writes them to the incoming queue in Redis
Redis A durable queue for storing VAAs before they are relayed
Relayer Scans the Redis incoming queue and moves acceptable VAAs to the working queue. It then completes the transfer and pays gas fees on the destination chain.
Wallet Monitor Presents a prometheus endpoint for monitoring wallet balances of native tokens (for paying gas fees) and non-native tokens as relayer profit

If Redis is temporarily down, the Listener will queue outstanding transactions in memory. When Redis comes back online, the Listener writes them all to Redis.

Architecture Diagram

This is a rough diagram of how the components fit together:

┌────────────────────────────────────────┐
│ Wormhole Guardian Peer to Peer Network │
└───────────────────┬────────────────────┘
                    │
             ┌──────▼───────┐
             │ Guardian Spy │
             └──────┬───────┘
                    │
             ┌──────▼───────┐
             │ Spy Listener │
             └──────┬───────┘
                    │
                ┌───▼───┐    ┌───────────────┐
                │ Redis │◄───┤ REST Listener │
                └───┬───┘    └───────────────┘
                    │
               ┌────▼────┐
               │ Relayer │
               └─────────┘
                    │
           ┌────────▼───────┐
           │ Wallet Monitor │
           └────────────────┘

Environment Variables

Listener

These are for configuring the spy and rest listener. See .env.tilt.listener for examples:

Name Description
SPY_SERVICE_HOST host & port string to connect to the spy
SPY_SERVICE_FILTERS Addresses to monitor (Wormhole core bridge contract addresses) array of ["chainId","emitterAddress"]. Emitter addresses are native strings.
REDIS_HOST Redis host / ip to connect to
REDIS_PORT Redis port
REST_PORT Rest listener port to listen on.
READINESS_PORT Kubernetes readiness probe port to listen on.
LOG_LEVEL log level, such as debug
SUPPORTED_TOKENS Origin assets that will attempt to be relayed. Array of ["chainId","address"], address should be a native string.

Relayer

These are for configuring the actual relayer. See .env.tilt.relayer for examples:

Name Description
SUPPORTED_CHAINS The configuration for each chain which will be relayed. See chainConfigs.example.json for the format. Of note, walletPrivateKey is an array, and a separate worker will be spun up for every private key provided.
REDIS_HOST host of the redis service, should be the same as in the spy_listener
REDIS_PORT port for redis to connect to
PROM_PORT port where prometheus monitoring will listen
READINESS_PORT port for kubernetes readiness probe
CLEAR_REDIS_ON_INIT boolean, if true the relayer will clear the INCOMING and WORKING Redis tables before it starts up.
DEMOTE_WORKING_ON_INIT boolean, if true the relayer will move everything from the WORKING Redis table to the INCOMING one.
LOG_LEVEL log level, debug or info

Building

Building the Spy

To build the guardiand / spy container from source:

cd node
docker build -f Dockerfile -t guardian .

Building the Relayer application

Build the relayer for non-containerized testing:

cd relayer/spy_relayer
npm ci
npm run build

Running the Whole Stack For Testing

This config is mostly for development.

Run Redis

Start a redis container:

docker run --rm -p6379:6379 --name redis-docker -d redis

Run the Guardian Spy

The spy connects to the wormhole guardian peer to peer network and listens for new VAAs. It publishes those via a socket and websocket that the listener subscribes to. If you want to run the spy built from source, change ghcr.io/certusone/guardiand:latest to guardian after building the guardian image.

Start the spy against the testnet wormhole guardian:

docker run \
    --platform=linux/amd64 \
    -p 7073:7073 \
    --entrypoint /guardiand \
    ghcr.io/certusone/guardiand:latest \
spy --nodeKey /node.key --spyRPC "[::]:7073" --network /wormhole/testnet/2/1 --bootstrap /dns4/wormhole-testnet-v2-bootstrap.certus.one/udp/8999/quic/p2p/12D3KooWBY9ty9CXLBXGQzMuqkziLntsVcyz4pk1zWaJRvJn6Mmt

Run The Apps

This runs the Spy Listener, REST Listener, Relayer, and Wallet Monitor all in a single process for development and testing purposes:

Start the application:

npm ci
npm run spy_relay