Compare commits

...

29 Commits

Author SHA1 Message Date
Jeff Schroeder d8d02aefe9
Merge b9976092c5 into a566c3d3bf 2024-04-24 18:51:16 -04:00
Dirk Brink a566c3d3bf docs: Update security.md with Cantina NTT audit report 2024-04-24 18:50:49 -04:00
Jeff Schroeder b9976092c5
docs: cspell updates 2024-04-24 17:13:34 -04:00
Jeff Schroeder 819af0cb92
docs: add section on ccq 2024-04-24 17:13:34 -04:00
Jeff Schroeder abb33f000e
docs: minor updates and ntt accountant enablement
* high level overview of how to enable the NTT Accountant
* emphasize all guardians need to run wormchain validators
* remove the reference to checking out a v2.x branch as the main branch
  is for wormholev2 now and has been for some time.
2024-04-24 17:13:34 -04:00
Jeff Schroeder cfabda4ee8
docs: adding wormchain useful commands 2024-04-24 17:13:34 -04:00
Jeff Schroeder e298af4392
docs: clarify guardiand wormchain URL and ports
Also mention threshold signing via horcrux and using the sentry node
architecture to protect the validator from volumetric attacks.
2024-04-24 17:12:53 -04:00
Jeff Schroeder 24d2702d71
docs: split out the per-chain bits for terra
* Since wormhole supports 30+ chains now and not just 5 chains, the
  solana, eth, terra, bsc bits were removed
* The solana and terra content had the urls updated to reflect reality
  and moved into their own sections.
* Made a reference to docs.wormhole.com's constants reference for chains
2024-04-24 17:12:53 -04:00
Jeff Schroeder 75ca4510e7
docs: section on cosmos / ibc connected chains
So that guardians know which nodes they need to run and which they can
rely on wormchain for.
2024-04-24 17:12:53 -04:00
Jeff Schroeder cf7cb55882
docs: evm node requirements for archive nodes 2024-04-24 17:12:53 -04:00
Jeff Schroeder 86795348d5
docs: wh dashboard and the fly healthcheck
* mention the wormhole-dashboard github hosted instance
* mention how to run the fly healthcheck to verify a guardian
2024-04-24 17:12:53 -04:00
Jeff Schroeder 3cbf3103ca
docs: remove terra light client daemon comment
The lcd was built directly into the terra binary a long time ago and no
longer requires a separate service for the lcd. This happened more than
a year ago.
2024-04-24 17:12:53 -04:00
Jeff Schroeder e800a38487
docs: update wording on bootstrap peers 2024-04-24 17:12:53 -04:00
Jeff Schroeder 1ca4220551
docs: add section to the ops docs on telemetry
This shows new guardians how to enable telemetry.
2024-04-24 17:12:53 -04:00
Jeff Schroeder ba12866ea5
doc: how to run the guardian node behind a NAT
Shoutout to @0xshipthecode and the RockawayX Infra team for helping test
and develop the patch for this in #3786.
2024-04-24 17:12:53 -04:00
Jeff Schroeder 37bb8597f9
docs: always pull latest guardian image to run a spy 2024-04-24 17:12:53 -04:00
Csongor Kiss 9620fca895
node: generalised governance (#3895)
* node/admin: add generalised EVM call governance handler

Handles governance requests of the form:

```
current_set_index: 4
messages: {
  sequence: 4513077582118919631
  nonce: 2809988562
  evm_call: {
    chain_id: 3
    governance_contract: "0xD8E4C2DbDd2e2bd8F1336EA691dBFF6952B1a6eB"
    target_contract: "0xF890982f9310df57d00f659cf4fd87e65adEd8d7"
    abi_encoded_call: "6497f75a000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000f890982f9310df57d00f659cf4fd87e65aded8d70000000000000000000000000000000000000000000000000000000000000140bebebebebebebebebebebebebebebebebebebebebebebebebebebebebebebebe000000000000000000000000000000000000000000000000000000000000000268690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004beefface00000000000000000000000000000000000000000000000000000000"
  }
}
```

* node/admin: add admin template for evm governance call

* node/admin: add generalised Solana call governance handler

handles governance requests of the form

```
current_set_index: 4
messages: {
  sequence: 4513077582118919631
  nonce: 2809988562
  solana_call: {
    chain_id: 3
    governance_contract: "3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5"
    encoded_instruction: "BEEFFACE"
  }
}
```

* node/admin: check address lengths and fix typo in governance handler

* node/admin: better error handling and fix comments

* sdk/vaa: add constants for general purpose governance actions
2024-04-23 11:28:02 -04:00
Bruce Riley 35f0b343ed Client/js: Add new chains 2024-04-22 17:14:23 -04:00
Jeff Schroeder bda43b2ac7 wormchain: update cosmos ledger bindings
Ran automatically via:

    go get github.com/cosmos/cosmos-sdk/crypto/ledger@v0.45.11

Fixes:

	 => ERROR [15/16] RUN make client                                                                                                                                                                                                                                           0.7s
	------
	 > [15/16] RUN make client:
	0.202 building wormchaind-v0.0.1
	0.202 go build -v -ldflags '-X github.com/cosmos/cosmos-sdk/version.Name=wormchain -X github.com/cosmos/cosmos-sdk/version.ServerName=wormchaind -X github.com/cosmos/cosmos-sdk/version.Version=v0.0.1 -X github.com/cosmos/cosmos-sdk/version.Commit=abc123 -X "github.com/cosmos/cosmos-sdk/version.BuildTags=ledger"' -tags ledger -o build/wormchaind cmd/wormchaind/main.go
	0.649 /go/pkg/mod/github.com/wormhole-foundation/cosmos-sdk@v0.45.9-wormhole-2/crypto/ledger/ledger_real.go:6:8: missing go.sum entry for module providing package github.com/cosmos/ledger-cosmos-go (imported by github.com/cosmos/cosmos-sdk/crypto/ledger); to add:
	0.649 	go get github.com/cosmos/cosmos-sdk/crypto/ledger@v0.45.11
	0.650 make: *** [Makefile:26: build/wormchaind] Error 1
	------
	Dockerfile:37
	--------------------
	  35 |     RUN /bin/bash /app/devnet/create-genesis.sh
	  36 |
	  37 | >>> RUN make client
	  38 |     RUN chmod +x /app/build/wormchaind
	  39 |
	--------------------
	ERROR: failed to solve: process "/bin/sh -c make client" did not complete successfully: exit code: 2
2024-04-22 16:31:18 -04:00
Jeff Schroeder 14d73dafe0 node: run go mod tidy
Necessary when updating the go ledger dependencies.
2024-04-22 16:31:18 -04:00
Michael Nguyen ddf5ba159c Fixes transactions when using a Ledger 2024-04-22 16:31:18 -04:00
bruce-riley 9af1fac9e1
Node/EVM: Linea poller (#3872)
* Node/EVM: Linea poller

* Explicitly check finality type in watcher
2024-04-22 10:11:45 -05:00
Jeff Schroeder 2712dd3f3f
node: upgrade to go 1.21.9 (#3855)
* node: update quic-go

Ran via:

    go get github.com/quic-go/quic-go@v0.42.0

* node: update mongo-drive dependency

Ran via:

    go get go.mongodb.org/mongo-driver@latest

* node: upgrade libp2p-go

Ran via:

    go get github.com/libp2p/go-libp2p@v0.33.1

Refs: #3863

* node: fallout from the go upgrade in the go.sum

Run via:

    go mod tidy

This updates the go.sum and removes unnecessary indirect references.

* docs: use go1.21.8

* github: use go1.21.8

Except for wormchain.

* node: update dockerfiles to use go 1.21.8

This was done with scripts/update-go-version.sh

* scripts: update linter dockerfile to use go 1.21.8

This was done with scripts/update-go-version.sh

* wormchain: update ibc-relayer to use go 1.21.8

This was done with scripts/update-go-version.sh

* scripts: add update-go-version.sh

This is a little helper to make updating the version of go a bit nicer.

* scripts: update-go-version.sh fixes

* set the default docker command to "dokcer"
* update the comment for the humongous sed command for dockerfiles

* github: fix go linting

* Upgrade golangci-lint to a version built with go 1.21.x. The older
  version was a binary version built with go 1.20.x and it was failing
  against the newer code built with go 1.21.x
* print the golangci-lint version in each run to see what version of go
  it was built with in case there are incompatibilties during the next
  upgrade
* remove the linter config skipping over pkg/supervisor entirely and
  instead put in an override to ignore the `unused` linter for the
  pkg/supervisor testhelpers bits for unsed test functions necessary
  to satisfy the test interface.

* scripts: update golang linter cli invocation

* github: use the latest version of golangci-lint

Because 1.52.2 is built with go 1.20.x which has issues with this project
now that it is upgraded to 1.21.8.

* node: remove implicit memory aliasing in a loop

Caught by an upgraded golangci-lint with the gosec linter:

    ::medium file=node/pkg/watchers/evm/connectors/batch_poller.go,line=226,col=8::G601: Implicit memory aliasing in for loop. (gosec)
    ::medium file=node/pkg/watchers/evm/connectors/batch_poller.go,line=285,col=8::G601: Implicit memory aliasing in for loop. (gosec)
    ::medium file=node/pkg/watchers/evm/connectors/batch_poller_test.go,line=128,col=37::G601: Implicit memory aliasing in for loop. (gosec)

See also: https://husni.dev/beware-of-implicit-memory-aliasing-in-go-foor-loop/

* node: update logging

* Update go to 1.21.9

Automated via:

    scripts/update-go-version.sh 1.21.9

* node: update test root context teardown time

Otherwise things get really sad.

* scripts: additions to update-go-versions.sh

* Standardized on prefacing functions with `function` for consistency
* Added a few more comments to explain how things work
* Automatically increment the go version and toolchain in go.mod
* Standardized on prefacing functions with `function` for consistency
* Make the go image debian version a variable for ease of maintenance

* node: update go.mod to specify 1.21.9

* node: update node tests

Review feedback from @pires

* scripts: run go mod tidy in update-go-version.sh

Required after running go mod edit or it refuses to build.

* node: update go.mod

Running `go mod tidy` removes the toolchain so the build works.

* node: update node tests

---------

Co-authored-by: Ryan Hamphrey <hamphreyryan26@gmail.com>
2024-04-19 14:43:36 -04:00
bruce-riley 04a13542d1
Node: Logging cleanup (#3888)
* Node: Logging cleanup

* Code review rework

---------

Co-authored-by: Bruce Riley <bruce@wormhole.labs.xyz>
2024-04-19 13:22:56 -05:00
bruce-riley c797acb7e9
Deploy SeiEVM Read Only to Testnet (#3889)
* Deploy SeiEVM Read Only

* Should be testnet, not mainnet
2024-04-19 11:01:58 -05:00
bruce-riley db9f33a816
Tilt : Deploy with forge instead of truffle (#3877)
* Tilt: Deploy with Forge instead of Truffle

* Move shell scripts
2024-04-19 10:44:04 -04:00
bruce-riley b0f1bd06ea
Deploy EVM Read Only (#3886) 2024-04-17 15:22:06 -05:00
Csongor Kiss 8b7495a7c6 clients/js: fix sui guardian set upgrade handler 2024-04-17 09:59:45 -04:00
Nikhil Suri 8ed75c9bfe
node: add emitters to ntt allowlist (#3884)
* node: add emitters to ntt allowlist

* node: tests: update TestNttVerifyMainnetEmitters
2024-04-16 17:40:43 -04:00
77 changed files with 8192 additions and 6405 deletions

View File

@ -48,7 +48,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "1.20.10"
go-version: "1.21.9"
- run: make node
algorand:
@ -286,7 +286,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "1.20.10"
go-version: "1.21.9"
- run: cd sdk/vaa && go test && go test -v -fuzz FuzzCalculateQuorum -run FuzzCalculateQuorum -fuzztime 15s
# Run Go linters
@ -303,15 +303,15 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "1.20.10"
go-version: "1.21.9"
- name: Install formatter
run: go install golang.org/x/tools/cmd/goimports@v0.8.0
- name: Formatting checks
run: ./scripts/lint.sh -l -g format
- name: Install linters
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.52.2
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.57.2
- name: Run linters
run: make generate && ./scripts/lint.sh -g lint
run: make generate && golangci-lint --version && ./scripts/lint.sh -g lint
- name: Ensure generated proto matches
run: |
rm -rf node/pkg/proto
@ -345,7 +345,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "1.20.10"
go-version: "1.21.9"
# The go-ethereum and celo-blockchain packages both implement secp256k1 using the exact same header, but that causes duplicate symbols.
- name: Run golang tests
run: cd node && go test -v -timeout 5m -race -ldflags '-extldflags "-Wl,--allow-multiple-definition" ' ./...

View File

@ -22,3 +22,9 @@ linters:
# - unconvert # disable because extra conversion typically don't hurt but can make code more clear
- unparam
- prealloc
issues:
exclude-rules:
- path: pkg/supervisor/supervisor_testhelpers.go
text: "^func.*supervisor.*(waitSettle|waitSettleError).*$"
linters:
- unused

View File

@ -4,7 +4,7 @@
The following dependencies are required for local development:
- [Go](https://golang.org/dl/) >= 1.20.x (latest minor release is recommended)
- [Go](https://golang.org/dl/) >= 1.21.9 (latest minor release is recommended)
- [Tilt](http://tilt.dev/) >= 0.20.8
- Any of the local Kubernetes clusters supported by Tilt.
We strongly recommend [minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/) >=

View File

@ -1,5 +1,5 @@
# syntax=docker.io/docker/dockerfile:1.3@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2
FROM docker.io/golang:1.20.10-bullseye@sha256:082569b3303b164cc4a7c88ac59b19b69c1a5d662041ac0dca046ac239632442 AS go-tools
FROM docker.io/golang:1.21.9-bullseye@sha256:311468bffa9fa4747a334b94e6ce3681b564126d653675a6adc46698b2b88d35 AS go-tools
RUN mkdir /app
@ -10,7 +10,7 @@ RUN --mount=type=cache,target=/root/.cache --mount=type=cache,target=/go \
cd /app/tools && CGO_ENABLED=0 ./build.sh
# syntax=docker.io/docker/dockerfile:1.3@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2
FROM docker.io/golang:1.20.10-bullseye@sha256:082569b3303b164cc4a7c88ac59b19b69c1a5d662041ac0dca046ac239632442 AS go-build
FROM docker.io/golang:1.21.9-bullseye@sha256:311468bffa9fa4747a334b94e6ce3681b564126d653675a6adc46698b2b88d35 AS go-build
COPY --from=go-tools /app /app

View File

@ -44,6 +44,7 @@ As these 3rd party audits are completed and issues are sufficiently addressed, w
- **[Jan 2024 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-01-ottersec-terra.pdf)**: _Terra Classic Contract Upgrades_
- **[Feb 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-09-cyfrin-wormhole-evm-cctp-v2-1.pdf)**: _CCTP EVM Contracts_
- **[Mar 2024 - Cyfrin](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-11-cyfrin-wormhole-evm-ntt.pdf)**: _NTT EVM Contracts_
- **[Mar 2024 - Cantina](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-cantina-wormhole-evm-ntt.pdf)**: _NTT EVM Contracts_
- **[Mar 2024 - OtterSec](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-03-28-ottersec-solana-ntt.pdf)**: _NTT Solana Contracts_
- **[Mar 2024 - Neodyme](https://github.com/wormhole-foundation/wormhole-audits/blob/main/2024-04-12-neodyme-solana-ntt.pdf)**: _NTT Solana Contracts_

View File

@ -253,9 +253,10 @@ Options:
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "wormchain",
"cosmoshub", "evmos", "kujira", "neutron", "celestia", "stargaze", "seda",
"dymension", "sepolia", "arbitrum_sepolia", "base_sepolia",
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
"optimism_sepolia", "holesky", "polygon_sepolia"]
-n, --network Network
[required] [choices: "mainnet", "testnet", "devnet"]
@ -311,18 +312,20 @@ Options:
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "wormchain",
"cosmoshub", "evmos", "kujira", "neutron", "celestia", "stargaze", "seda",
"dymension", "sepolia", "arbitrum_sepolia", "base_sepolia",
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
"optimism_sepolia", "holesky", "polygon_sepolia"]
--dst-chain destination chain
[required] [choices: "solana", "ethereum", "terra", "bsc", "polygon",
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "wormchain",
"cosmoshub", "evmos", "kujira", "neutron", "celestia", "stargaze", "seda",
"dymension", "sepolia", "arbitrum_sepolia", "base_sepolia",
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
"optimism_sepolia", "holesky", "polygon_sepolia"]
--dst-addr destination address [string] [required]
--token-addr token address [string] [default: native token]
@ -355,9 +358,10 @@ Positionals:
"avalanche", "oasis", "algorand", "aurora", "fantom", "karura", "acala",
"klaytn", "celo", "near", "moonbeam", "neon", "terra2", "injective",
"osmosis", "sui", "aptos", "arbitrum", "optimism", "gnosis", "pythnet",
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "wormchain",
"cosmoshub", "evmos", "kujira", "neutron", "celestia", "stargaze", "seda",
"dymension", "sepolia", "arbitrum_sepolia", "base_sepolia",
"xpla", "btc", "base", "sei", "rootstock", "scroll", "mantle", "blast",
"xlayer", "linea", "berachain", "seievm", "wormchain", "cosmoshub", "evmos",
"kujira", "neutron", "celestia", "stargaze", "seda", "dymension",
"provenance", "sepolia", "arbitrum_sepolia", "base_sepolia",
"optimism_sepolia", "holesky", "polygon_sepolia"]
tx Source transaction hash [string]

View File

@ -10,7 +10,7 @@
"license": "Apache-2.0",
"dependencies": {
"@celo-tools/celo-ethers-wrapper": "^0.1.0",
"@certusone/wormhole-sdk": "^0.10.13",
"@certusone/wormhole-sdk": "^0.10.14",
"@cosmjs/encoding": "^0.26.2",
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
"@injectivelabs/networks": "^1.10.7",
@ -683,9 +683,9 @@
}
},
"node_modules/@certusone/wormhole-sdk": {
"version": "0.10.13",
"resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.13.tgz",
"integrity": "sha512-04OCGoJUylTFNu4+g96Ax7jvn3M7FwVbTTcPNIjgta8QcC046kZBYAEd/yrK5hkDGqejQyJwO0ieaJfxL/kv1w==",
"version": "0.10.14",
"resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.14.tgz",
"integrity": "sha512-36pEcLZbG+DLFKL2N7khLLnSYBMPoMpJrUs7IFqps3i+PhCZ6e8xb2ohNcIKX58G9Ibj+xRmc5ilo+D37WodVg==",
"dependencies": {
"@certusone/wormhole-sdk-proto-web": "0.0.7",
"@certusone/wormhole-sdk-wasm": "^0.0.1",
@ -11917,9 +11917,9 @@
"requires": {}
},
"@certusone/wormhole-sdk": {
"version": "0.10.13",
"resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.13.tgz",
"integrity": "sha512-04OCGoJUylTFNu4+g96Ax7jvn3M7FwVbTTcPNIjgta8QcC046kZBYAEd/yrK5hkDGqejQyJwO0ieaJfxL/kv1w==",
"version": "0.10.14",
"resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.10.14.tgz",
"integrity": "sha512-36pEcLZbG+DLFKL2N7khLLnSYBMPoMpJrUs7IFqps3i+PhCZ6e8xb2ohNcIKX58G9Ibj+xRmc5ilo+D37WodVg==",
"requires": {
"@certusone/wormhole-sdk-proto-web": "0.0.7",
"@certusone/wormhole-sdk-wasm": "^0.0.1",

View File

@ -30,7 +30,7 @@
],
"dependencies": {
"@celo-tools/celo-ethers-wrapper": "^0.1.0",
"@certusone/wormhole-sdk": "^0.10.13",
"@certusone/wormhole-sdk": "^0.10.14",
"@cosmjs/encoding": "^0.26.2",
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
"@injectivelabs/networks": "^1.10.7",

View File

@ -62,6 +62,11 @@ export const getOriginalAsset = async (
// case "rootstock":
case "scroll":
case "mantle":
case "blast":
case "xlayer":
case "linea":
case "berachain":
case "seievm":
case "sepolia":
case "arbitrum_sepolia":
case "base_sepolia":
@ -125,6 +130,7 @@ export const getOriginalAsset = async (
case "stargaze":
case "seda":
case "dymension":
case "provenance":
case "rootstock":
throw new Error(`${chainName} not supported`);
default:

View File

@ -72,6 +72,11 @@ export const getWrappedAssetAddress = async (
// case "rootstock":
case "scroll":
case "mantle":
case "blast":
case "xlayer":
case "linea":
case "berachain":
case "seievm":
case "sepolia":
case "arbitrum_sepolia":
case "base_sepolia":
@ -172,6 +177,7 @@ export const getWrappedAssetAddress = async (
case "stargaze":
case "seda":
case "dymension":
case "provenance":
throw new Error(`${chainName} not supported`);
default:
impossible(chainName);

View File

@ -99,6 +99,11 @@ export const getProviderForChain = <T extends ChainId | ChainName>(
// case "rootstock":
case "scroll":
case "mantle":
case "blast":
case "xlayer":
case "linea":
case "berachain":
case "seievm":
case "sepolia":
case "arbitrum_sepolia":
case "base_sepolia":
@ -169,6 +174,7 @@ export const getProviderForChain = <T extends ChainId | ChainName>(
case "stargaze":
case "seda":
case "dymension":
case "provenance":
case "rootstock":
throw new Error(`${chainName} not supported`);
default:

View File

@ -1,4 +1,7 @@
import { getWrappedCoinType } from "@certusone/wormhole-sdk/lib/esm/sui";
import {
getWrappedCoinType,
uint8ArrayToBCS,
} from "@certusone/wormhole-sdk/lib/esm/sui";
import {
createWrappedOnSui,
createWrappedOnSuiPrepare,
@ -52,14 +55,36 @@ export const submit = async (
case "ContractUpgrade":
throw new Error("ContractUpgrade not supported on Sui");
case "GuardianSetUpgrade": {
console.log("Submitting new guardian set");
const tx = new TransactionBlock();
setMaxGasBudgetDevnet(network, tx);
tx.moveCall({
target: `${corePackageId}::wormhole::update_guardian_set`,
const [verifiedVaa] = tx.moveCall({
target: `${corePackageId}::vaa::parse_and_verify`,
arguments: [
tx.object(coreObjectId),
tx.pure([...vaa]),
tx.pure(uint8ArrayToBCS(vaa)),
tx.object(SUI_CLOCK_OBJECT_ID),
],
});
const [decreeTicket] = tx.moveCall({
target: `${corePackageId}::update_guardian_set::authorize_governance`,
arguments: [tx.object(coreObjectId)],
});
const [decreeReceipt] = tx.moveCall({
target: `${corePackageId}::governance_message::verify_vaa`,
arguments: [tx.object(coreObjectId), verifiedVaa, decreeTicket],
typeArguments: [
`${corePackageId}::update_guardian_set::GovernanceWitness`,
],
});
console.log("Submitting new guardian set");
setMaxGasBudgetDevnet(network, tx);
tx.moveCall({
target: `${corePackageId}::update_guardian_set::update_guardian_set`,
arguments: [
tx.object(coreObjectId),
decreeReceipt,
tx.object(SUI_CLOCK_OBJECT_ID),
],
});

View File

@ -200,6 +200,8 @@ async function executeSubmit(
throw Error("seda is not supported yet");
} else if (chain === "dymension") {
throw Error("dymension is not supported yet");
} else if (chain === "provenance") {
throw Error("provenance is not supported yet");
} else if (chain === "rootstock") {
throw Error("rootstock is not supported yet");
} else {

View File

@ -154,6 +154,8 @@ export const handler = async (
throw Error("seda is not supported yet");
} else if (srcChain === "dymension") {
throw Error("dymension is not supported yet");
} else if (srcChain === "provenance") {
throw Error("provenance is not supported yet");
} else if (srcChain === "rootstock") {
throw Error("rootstock is not supported yet");
} else {

View File

@ -171,6 +171,41 @@ const MAINNET = {
key: getEnvVar("ETH_KEY"),
chain_id: 30,
},
scroll: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
mantle: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
blast: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
xlayer: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
linea: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
berachain: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
seievm: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
sepolia: {
rpc: undefined,
key: undefined,
@ -206,16 +241,6 @@ const MAINNET = {
key: undefined,
chain_id: undefined,
},
scroll: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
mantle: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
arbitrum_sepolia: {
rpc: undefined,
key: undefined,
@ -251,6 +276,11 @@ const MAINNET = {
key: undefined,
chain_id: undefined,
},
provenance: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
};
const TESTNET = {
@ -362,6 +392,41 @@ const TESTNET = {
rpc: "https://rpc.atlantic-2.seinetwork.io",
key: getEnvVar("SEI_KEY_TESTNET"),
},
scroll: {
rpc: "https://rpc.ankr.com/scroll_sepolia_testnet",
key: getEnvVar("ETH_KEY_TESTNET"),
chain_id: 534353,
},
mantle: {
rpc: "https://mantle-sepolia.drpc.org",
key: getEnvVar("ETH_KEY_TESTNET"),
chain_id: 5003,
},
blast: {
rpc: "https://blast-sepolia.drpc.org",
key: getEnvVar("ETH_KEY_TESTNET"),
chain_id: 168587773,
},
xlayer: {
rpc: "https://testrpc.xlayer.tech/",
key: getEnvVar("ETH_KEY_TESTNET"),
chain_id: 195,
},
linea: {
rpc: "https://rpc.sepolia.linea.build",
key: getEnvVar("ETH_KEY_TESTNET"),
chain_id: 59141,
},
berachain: {
rpc: "https://artio.rpc.berachain.com/",
key: getEnvVar("ETH_KEY_TESTNET"),
chain_id: 80085,
},
seievm: {
rpc: "https://evm-rpc-arctic-1.sei-apis.com/",
key: getEnvVar("ETH_KEY_TESTNET"),
chain_id: 713715,
},
sepolia: {
rpc: "https://rpc.ankr.com/eth_sepolia",
key: getEnvVar("ETH_KEY_TESTNET"),
@ -445,16 +510,6 @@ const TESTNET = {
key: undefined,
chain_id: undefined,
},
scroll: {
rpc: "https://rpc.ankr.com/scroll_sepolia_testnet",
key: getEnvVar("ETH_KEY_TESTNET"),
chain_id: 534353,
},
mantle: {
rpc: "https://mantle-sepolia.drpc.org",
key: getEnvVar("ETH_KEY_TESTNET"),
chain_id: 5003,
},
arbitrum_sepolia: {
rpc: "https://arbitrum-sepolia.publicnode.com",
key: getEnvVar("ETH_KEY_TESTNET"),
@ -490,6 +545,11 @@ const TESTNET = {
key: undefined,
chain_id: undefined,
},
provenance: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
};
const DEVNET = {
@ -584,6 +644,41 @@ const DEVNET = {
rpc: undefined,
key: undefined,
},
scroll: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
mantle: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
blast: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
xlayer: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
linea: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
berachain: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
seievm: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
sepolia: {
rpc: undefined,
key: undefined,
@ -660,16 +755,6 @@ const DEVNET = {
key: undefined,
chain_id: undefined,
},
scroll: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
mantle: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
arbitrum_sepolia: {
rpc: undefined,
key: undefined,
@ -705,6 +790,11 @@ const DEVNET = {
key: undefined,
chain_id: undefined,
},
provenance: {
rpc: undefined,
key: undefined,
chain_id: undefined,
},
};
/**

View File

@ -3,8 +3,8 @@ import {
BridgeImplementation__factory,
Implementation__factory,
NFTBridgeImplementation__factory,
WormholeRelayer__factory,
} from "@certusone/wormhole-sdk/lib/esm/ethers-contracts";
import { WormholeRelayer__factory } from "@certusone/wormhole-sdk/lib/esm/ethers-relayer-contracts";
import { getWormholeRelayerAddress } from "@certusone/wormhole-sdk/lib/esm/relayer";
import {
CHAINS,

View File

@ -7,6 +7,7 @@ Algorand
algosdk
alist
Aptos
arbitrum
authorisation
authorise
authorised
@ -22,9 +23,11 @@ bscscan
BUILDKIT
bytecodes
callstack
ccqlistener
CCTP
celestia
Celestia
celo
certusone
Chainlink
Coinspect
@ -61,9 +64,12 @@ GUARDIAND
guardiand's
Hacken
hashdump
healthcheck
Healthcheck
hexdump
holesky
Holesky
horcrux
ICCO
incentivized
incentivizing
@ -138,11 +144,13 @@ readyz
regen
reinit
reobservation
reobserved
repoint
rustup
satoshi
secp
seda
seievm
Sepolia
serde
setcap
@ -192,6 +200,7 @@ wormchaind
Wormholescan
wormscan
wormscanurl
xlayer
xpla
XPLA
Zellic

View File

@ -54,7 +54,7 @@ spec:
command:
- /bin/sh
- -c
- "cd ../../ethereum && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_all_chains.js && cd ../relayer/ethereum && npm run deploy-relayers-evm1 && nc -lkn 2000"
- "cd ../../ethereum && CHAIN_ID=2 NETWORK=devnet ./sh/devnetInitialization.sh && cd ../relayer/ethereum && npm run deploy-relayers-evm1 && nc -lkn 2000"
readinessProbe:
periodSeconds: 1
failureThreshold: 300

View File

@ -55,7 +55,7 @@ spec:
command:
- /bin/sh
- -c
- "cd ../../ethereum && sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g;s/EVM_CHAIN_ID=1337/EVM_CHAIN_ID=1397/g' .env && npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_all_chains.js && cd ../relayer/ethereum && sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g;s/EVM_CHAIN_ID=1337/EVM_CHAIN_ID=1397/g' .env && npm run deploy-relayers-evm2 && nc -lkn 2000"
- "cd ../../ethereum && sed -i 's/CHAIN_ID=0x2/CHAIN_ID=0x4/g;s/EVM_CHAIN_ID=1337/EVM_CHAIN_ID=1397/g' .env && NETWORK=devnet ./sh/devnetInitialization.sh && cd ../relayer/ethereum && npm run deploy-relayers-evm2 && nc -lkn 2000"
readinessProbe:
periodSeconds: 1
failureThreshold: 300

View File

@ -1,29 +1,12 @@
# Running a Wormhole node
# Running a Wormhole Guardian Node
![](images/nodearchitecture.svg)
## Connected chains
In addition to Wormhole itself, you need to run your own verifying node for every chain that Wormhole connects to:
- **Solana**. There is no light client for Solana yet, so you'll have to run a full solana-validator node. It does not
have to actually be a validator - you can run solana-validator in non-validating mode if you are not a validator.
Refer to the [Solana documentation](https://docs.solana.com/running-validator) on how to run a validator. The validator
requirements as stated in their docs are excessive - for the current iteration for mainnet-beta, the "low end" config
with no GPU is perfectly adequate, and will have enough spare capacity.
[Solana's Discord server](https://solana.com/community) is a great resource for questions regarding validator ops.
- **Ethereum**. See below - you need at least a light client. For stability reasons, a full node is recommended.
- **Terra** requires a full node and an [LCD server](https://docs.terra.money/terracli/lcd.html#light-client-daemon)
pointing to your full node. Refer to the [Terra documentation](https://docs.terra.money/node/join-network.html)
on how to run a full node. From a security point of view, running only an LCD server with `--trust-node=false` pointed
to somebody else's full node would be sufficient, but you'd then depend on that single node for availability unless
you set up a load balancer pointing to a set of nodes.
- **Binance Smart Chain**: Same requirements as Ethereum. Note that BSC has higher throughput than Ethereum and
roughly requires twice as many compute resources.
In addition to Wormhole itself, you need to run your own verifying node for every chain that Wormhole connects to except
for newer IBC connected chains that integrate through wormhole gateway. Please refer to the [constants reference](https://docs.wormhole.com/wormhole/reference/constants)
for all chains wormhole connects to.
**Do NOT use third-party RPC service providers** for any of the chains! You'd fully trust them, and they could lie to
you on whether an event has actually been observed. The whole point of Wormhole is not to rely on centralized nodes!
@ -33,6 +16,12 @@ so you can test changes for your mainnet full nodes and gain operational experie
### Solana node requirements
Refer to the [Solana documentation](https://docs.solanalabs.com/operations/setup-an-rpc-node) on how to run an rpc
(full) node. [Solana's Discord server](https://solana.com/community) is a great resource for questions regarding
operations.
The `#rpc-server-operators` channel is especially useful for setting up Solana rpc nodes.
Your Solana RPC node needs the following parameters enabled:
```
@ -102,18 +91,154 @@ since only very few nodes support the light client protocol.
Running a full node typically requires ~500G of SSD storage, 8G of RAM and 4-8 CPU threads (depending on clock
frequency). Light clients have much lower hardware requirements.
### Terra
Refer to the [Terra documentation](https://docs.terra.money/full-node/run-a-full-terra-node/set-up-production/) on how to run a full node.
#### Terra Classic
Refer to the [Terra Classic documentation](https://classic-docs.terra.money/docs/full-node/run-a-full-terra-node/README.html) on how to run a full node.
### Wormchain
All guardians **must run validators for wormchain**, the codename of [Wormhole Gateway](https://wormhole.com/gateway/).
The ``--wormchainURL` argument to the guardian node should point to `<validator address>:9090` which is the `grpc` port
in the app.toml.
Example port setup:
<!-- cspell:disable -->
config.toml:
```toml
[rpc]
laddr = "tcp://0.0.0.0:26657"
grpc_laddr = ""
pprof_laddr = "localhost:6060"
[p2p]
laddr = "tcp://0.0.0.0:26656"
external_address = ""
```
app.toml:
```toml
[grpc]
address = "0.0.0.0:9090"
[grpc-web]
address = "0.0.0.0:9091"
```
<!-- cspell:enable -->
For signing, consider setting up a remote threshold signer such as
[horcrux](https://github.com/strangelove-ventures/horcrux) and adopting the sentry node architecture with sentry nodes
in front of your wormchain validator.
#### Wormchain Useful Commands
Check latest guardian set:
<!-- cspell:disable -->
```shell
$ wormchaind query wormhole latest-guardian-set-index
latestGuardianSetIndex: 4
```
<!-- cspell:enable -->
Upgrade the guardian set (with a valid governance vaa):
<!-- cspell:disable -->
```shell
wormchaind tx wormhole execute-governance-vaa <guardian_set_upgrade_VAA_in_hex_format>
```
<!-- cspell:disable -->
View Validator Information:
<!-- cspell:disable -->
```shell
$ wormchaind q staking validators
... snip ...
- commission:
commission_rates:
max_change_rate: "0.020000000000000000"
max_rate: "0.200000000000000000"
rate: "0.000000000000000000"
update_time: "2024-04-16T19:13:45.210176030Z"
consensus_pubkey:
'@type': /cosmos.crypto.ed25519.PubKey
key: T+hsVX52EarrsL+mOwv3mL0byWa2EctsG6XmikUMFiQ=
delegator_shares: "0.000000000000000000"
description:
details: ""
identity: 11A4103C4BCBD2B4
moniker: RockawayX
security_contact: ""
website: https://rockawayx.com/infrastructure
jailed: false
min_self_delegation: "0"
operator_address: wormholevaloper1thl5syhmscgnj7whdyrydw3w6vy80044278fxp
status: BOND_STATUS_BONDED
tokens: "0"
unbonding_height: "0"
unbonding_time: "1970-01-01T00:00:00Z"
```
<!-- cspell:enable -->
### EVM node requirements
Some non-ethereum EVM compatible blockchains need to run in archive mode for [queries](https://wormhole.com/queries)
to function correctly. By default in geth, [historical state is only kept in memory for the previous 128 blocks](https://github.com/ethereum/go-ethereum/blob/4458905f261d5d9ba5fda3d664f9bb80346ab404/core/state/statedb.go#L1259-L1265).
After 128 blocks, older states are garbage collected. Many of these chains are forks of geth that maintain this
historical limitation.
* Arbitrum
* Base
* Optimism
Newer execution clients such as [reth](https://github.com/paradigmxyz/reth) lack this limitation and are worth
investigating once they are stable.
Additionally, if there is ever a scenario where the network fails to come to consensus on an EVM compatible chain due to
a hard fork or some unforeseen scenario, it might be required to run archive nodes for those chains temporarily to ensure
the transactions can be reobserved.
### Cosmos / IBC Connected nodes
All modern cosmos integrations happen by wormhole observing IBC transactions on gateway (wormchain). Guardian node operators do not need to run full nodes for these networks. For cosmos based chains that were added before this functionality, a full node is still necessary.
The following cosmos based nodes were added prior to gateway and guardians need to run full nodes:
* Injective
* Terra
* Terra Classic
* XPLA
**NOTE**: All guardians must run validators for wormchain.
## Building guardiand
For security reasons, we do not provide a pre-built binary. You need to check out the repo and build the
guardiand binary from source. A Git repo is much harder to tamper with than release binaries.
To build the Wormhole node, you need [Go](https://golang.org/dl/) >= 1.19.0
To build the Wormhole node, you need [Go](https://golang.org/dl/) >= 1.21.9
First, check out the version of the Wormhole repo that you want to deploy:
```bash
git clone https://github.com/wormhole-foundation/wormhole && cd wormhole
git checkout v2.0.x
```
Then, compile the release binary as an unprivileged build user:
@ -157,7 +282,8 @@ We strongly recommend a separate user and systemd services for the Wormhole serv
See the separate [wormhole-networks](https://github.com/wormhole-foundation/wormhole-networks) repository for examples
on how to set up the guardiand unit for a specific network.
You need to open port 8999/udp in your firewall for the P2P network. Nothing else has to be exposed externally.
You need to open port 8999/udp in your firewall for the P2P network and 8996/udp for
[cross chain queries](../whitepapers/0013_ccq.md). Nothing else has to be exposed externally if you don't run public rpc.
journalctl can show guardiand's colored output using the `-a` flag for binary output, i.e.: `journalctl -a -f -u guardiand`.
@ -169,11 +295,18 @@ Refer to [devnet/](../devnet) for example k8s deployments as a starting point fo
have to build your own containers. Unless you already run Kubernetes in production, we strongly recommend a traditional
deployment on a dedicated instance - it's easier to understand and troubleshoot.
When running in kubernetes, or behind any kind of NAT, pass `--gossipAdvertiseAddress=external.ip.address` to the
guardiand node process to ensure the external address is advertized in p2p. If this is not done, reobservation
requests and [ccq](https://wormhole.com/queries) will not function as intended.
### Monitoring
Wormhole exposes a status server for readiness and metrics. By default, it listens on port 6060 on localhost.
You can use a command line argument to expose it publicly: `--statusAddr=[::]:6060`.
**NOTE:** Parsing the log output for monitoring is NOT recommended. Log output is meant for human consumption and is
not considered a stable API. Log messages may be added, modified or removed without notice. Use the metrics :-)
#### `/readyz`
This endpoint returns a 200 OK status code once the Wormhole node is ready to serve requests. A node is
@ -193,9 +326,93 @@ alerting will be documented here.
See [Wormhole.json](../dashboards/Wormhole.json) for an example Grafana dashboard.
#### Wormhole Dashboard
There is a [dashboard](https://wormhole-foundation.github.io/wormhole-dashboard) which shows the overall health of the
network and has metrics on individual guardians.
**NOTE:** Parsing the log output for monitoring is NOT recommended. Log output is meant for human consumption and is
not considered a stable API. Log messages may be added, modified or removed without notice. Use the metrics :-)
#### Wormhole Fly Healthcheck
In the [wormhole-dashboard](https://github.com/wormhole-foundation/wormhole-dashboard) repository, there is a small
[healthcheck application](https://github.com/wormhole-foundation/wormhole-dashboard/tree/main/fly/cmd/healthcheck)
which verifies that the guardian is gossiping out heartbeats, is submitting chain observations, and has a working
heartbeats api available. This is a very good way to verify a specific guardian is functioning as intended.
You can clone the repo and run the check against the [MCF Guardian](https://github.com/wormhole-foundation/wormhole-networks/blob/649dcc48f29d462fe6cb0062cb6530021d36a417/mainnetv2/guardianset/v3.prototxt#L58):
```shell
git clone https://github.com/wormhole-foundation/wormhole-dashboard
cd wormhole-dashboard/fly/cmd/healthcheck
# Run the fly
$ go run main.go --pubKey 0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811 --url https://wormhole-v2-mainnet-api.mcf.rocks
✅ guardian heartbeat received {12D3KooWDZVv7BhZ8yFLkarNdaSWaB43D6UbQwExJ8nnGAEmfHcU: [/ip4/185.188.42.109/udp/8999/quic-v1]}
✅ 44 observations received
✅ /v1/heartbeats
```
If the guardian public rpc is not exposed, the `--url` flag can be omitted:
```shell
$ go run main.go --pubKey 0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811
✅ guardian heartbeat received {12D3KooWDZVv7BhZ8yFLkarNdaSWaB43D6UbQwExJ8nnGAEmfHcU: [/ip4/185.188.42.109/udp/8999/quic-v1]}
✅ 41 observations received
--url not defined, skipping web checks
```
The bootstrap nodes and network defaults to mainnet and the values can be found in the [network constants](../node/pkg/p2p/network_consts.go).
It can also be used to test a specific bootstrap node/s:
```shell
$ go run main.go --pubKey 0xDA798F6896A3331F64b48c12D1D57Fd9cbe70811 --bootstrap /dns4/wormhole.mcf.rocks/udp/8999/quic/p2p/12D3KooWDZVv7BhZ8yFLkarNdaSWaB43D6UbQwExJ8nnGAEmfHcU
✅ guardian heartbeat received {12D3KooWDZVv7BhZ8yFLkarNdaSWaB43D6UbQwExJ8nnGAEmfHcU: [/ip4/185.188.42.109/udp/8999/quic-v1]}
✅ 44 observations received
--url not defined, skipping web checks
```
## Native Token Transfers
[NTT](https://github.com/wormhole-foundation/example-native-token-transfers) is an exciting feature of wormhole that builds upon the core bridge to allow mint/burn style transfers. Ensuring it runs correctly requires integrating it with the NTT Accountant. To enable this feature, create a **new** wormchain key. Do not reuse an existing global accountant key and add the following parameters:
<!-- cspell:disable -->
```shell
# You may already have these.
--wormchainURL URL_TO_YOUR_WORMCHAIN_NODE
--accountantWS HTTP_URL_OF_YOUR_WORMCHAIN_NODE
# This is the mainnet contract.
--accountantNttContract wormhole1mc23vtzxh46e63vq22e8cnv23an06akvkqws04kghkrxrauzpgwq2hmwm7
--accountantNttKeyPath PATH_TO_YOUR_NTT_ACCOUNTANT_KEY_FILE
--accountantNttKeyPassPhrase YOUR_NTT_ACCOUNTANT_KEY_PASS_PHRASE
```
<!-- cspell:enable -->
Please remember to allowlist the new NTT Accountant key for use with Wormchain! For instructions on how to do that, speak with someone from the Wormhole Foundation.
## Cross Chain Queries
[CCQ](https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0013_ccq.md) also known as [Wormhole Queries](https://wormhole.com/queries) is a feature to allow pulling attestations in a cross chain manner. To run ccq, a few additional flags need to be enabled on the guardian node:
<!-- cspell:disable -->
```shell
--ccqEnabled=true \
--ccqP2pPort 8996 \
--ccqAllowedPeers="[ALLOWED,PEERS,GO,HERE]" \
--ccqAllowedRequesters="[ALLOWED,REQUESTORS,GO,HERE" \
```
<!-- cspell:enable -->
To test query functionality, follow the instructions in [node/hack/query/ccqlistener/ccqlistener.go](../node/hack/query/ccqlistener/ccqlistener.go).
## Running a public API endpoint
Wormhole v2 no longer uses Solana as a data availability layer (see [design document](../whitepapers/0005_data_availability.md)).
@ -223,6 +440,17 @@ It is safe to expose the publicWeb port on signing nodes. For better resiliency
future guardiand releases will include listen-only mode such that multiple guardiand instances without guardian keys
can be operated behind a load balancer.
## Enabling Telemetry
Optionally, the guardian can send telemetry to [grafana cloud logs](https://grafana.com/products/cloud/logs/) aka "loki".
To enable this functionality, add the following flag:
```bash
--telemetryLokiURL=$PER_GUARDIAN_LOKI_URL_WITH_TOKEN
```
New guardians should talk to the wormhole foundation to get a loki url.
### Binding to privileged ports
If you want to bind `--publicWeb` to a port <1024, you need to assign the CAP_NET_BIND_SERVICE capability.
@ -265,8 +493,9 @@ may include support for remote signing.
## Bootstrap Peers
The list of supported bootstrap peers is defined in `node/pkg/p2p/network_consts.go`. That file also provides golang functions
for obtaining the network parameters (network ID and bootstrap peers) based on the environment (mainnet or testnet).
The list of supported bootstrap peers is defined in [node/pkg/p2p/network_consts.go](../node/pkg/p2p/network_consts.go).
That file also provides golang functions for obtaining the network parameters (network ID and bootstrap peers) based on
the environment (mainnet or testnet).
The common Wormhole applications (guardiand, spy and query proxy server) use those functions, so it is not necessary to specify
the actual bootstrap parameters in their configs. Developers of any new applications are strongly urged to do the same, and not
@ -282,6 +511,7 @@ Start the spy against the testnet wormhole guardian:
```bash
docker run \
--pull=always \
--platform=linux/amd64 \
-p 7073:7073 \
--entrypoint /guardiand \
@ -297,6 +527,7 @@ To run the spy against mainnet:
```bash
docker run \
--pull=always \
--platform=linux/amd64 \
-p 7073:7073 \
--entrypoint /guardiand \

View File

@ -13,6 +13,8 @@ RUN curl -L https://foundry.paradigm.xyz | bash
RUN $HOME/.foundry/bin/foundryup
RUN ls $HOME/.foundry/bin
RUN apt-get -y install jq
# Run as user, otherwise, npx explodes.
RUN mv /root/.foundry/bin/anvil /bin/anvil
RUN mv /root/.foundry/bin/forge /bin/forge

View File

@ -49,11 +49,7 @@ build: forge_dependencies node_modules ${SOURCE_FILES}
flattened/%.sol: contracts/%.sol node_modules
@mkdir -p $(dir $@)
# We remove the license (SPDX) lines and ABIEncoderV2 lines because they
# break compilation in the flattened file if there are multiple conflicting
# declarations.
npx truffle-flattener $< | grep -v SPDX | grep -v ABIEncoderV2 > $@
./sh/flatten.sh
.PHONY: flattened
flattened: $(patsubst contracts/%, flattened/%, $(FLATTEN_FILES))

View File

@ -30,25 +30,25 @@ ethereum$ ln -s env/.env.blast.testnet .env
#### Deploy the Core contract
```shell
ethereum$ MNEMONIC=<redacted> ./forge-scripts/deployCoreBridge.sh
ethereum$ MNEMONIC=<redacted> ./sh/deployCoreBridge.sh
```
#### Deploy the TokenBridge contract
```shell
ethereum$ MNEMONIC=<redacted> WORMHOLE_ADDRESS=<from_the_previous_command> ./forge-scripts/deployTokenBridge.sh
ethereum$ MNEMONIC=<redacted> WORMHOLE_ADDRESS=<from_the_previous_command> ./sh/deployTokenBridge.sh
```
#### Deploy the Core Shutdown contract
```shell
ethereum$ MNEMONIC=<redacted> ./forge-scripts/deployCoreShutdown.sh
ethereum$ MNEMONIC=<redacted> ./sh/deployCoreShutdown.sh
```
#### Deploy the TokenBridge Shutdown contract
```shell
ethereum$ MNEMONIC=<redacted> ./forge-scripts/deployTokenBridgeShutdown.sh
ethereum$ MNEMONIC=<redacted> ./sh/deployTokenBridgeShutdown.sh
```
#### Generate Flattened Source
@ -56,7 +56,7 @@ ethereum$ MNEMONIC=<redacted> ./forge-scripts/deployTokenBridgeShutdown.sh
To generated the flattened source files to verify the contracts using the explorer UI
```shell
ethereum$ ./forge-scripts/flatten.sh
ethereum$ ./sh/flatten.sh
```
This will put the flattened files in `ethereum/flattened`.
@ -64,14 +64,14 @@ This will put the flattened files in `ethereum/flattened`.
#### Upgrade the Core or TokenBridge Implementation
```shell
ethereum$ MNEMONIC= ./forge-scripts/upgrade.sh testnet Core blast
ethereum$ MNEMONIC= ./forge-scripts/upgrade.sh testnet TokenBridge blast
ethereum$ MNEMONIC= ./sh/upgrade.sh testnet Core blast
ethereum$ MNEMONIC= ./sh/upgrade.sh testnet TokenBridge blast
```
#### Registering Other Chains on a New TokenBridge
```shell
ethereum$ MNEMONIC= ./forge-scripts/registerAllChainsOnTokenBridge.sh.sh testnet blast
ethereum$ MNEMONIC= ./sh/registerAllChainsOnTokenBridge.sh.sh testnet blast
```
### Deploying using Truffle (deprecated)

13
ethereum/env/.env.seievm.testnet vendored Normal file
View File

@ -0,0 +1,13 @@
# Sei EVM testnet read only env. Use to deploy the core contract with forge.
# ethereum$ ln -s env/.env.seievm.testnet .env
RPC_URL="https://evm-rpc-arctic-1.sei-apis.com/"
FORGE_ARGS="--legacy --with-gas-price 3000000000" # 3 gwei
# Wormhole Core
INIT_SIGNERS=["0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5"]
INIT_CHAIN_ID=40
INIT_GOV_CHAIN_ID=0x1
INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
INIT_EVM_CHAIN_ID=713715

View File

@ -0,0 +1,20 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import {Implementation} from "../contracts/Implementation.sol";
import {Setup} from "../contracts/Setup.sol";
import "forge-std/Script.sol";
contract DeployDummyContract is Script {
function run(uint256 num) public {
vm.startBroadcast();
for(uint256 i=0; i<num; i++) {
deploy();
}
vm.stopBroadcast();
}
function deploy() internal {
Setup setup = new Setup();
}
}

View File

@ -0,0 +1,107 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import {NFTBridgeImplementation} from "../contracts/nft/NFTBridgeImplementation.sol";
import {NFTBridgeSetup} from "../contracts/nft/NFTBridgeSetup.sol";
import {NFTImplementation} from "../contracts/nft/token/NFTImplementation.sol";
import {NFTBridgeEntrypoint} from "../contracts/nft/NFTBridgeEntrypoint.sol";
import "forge-std/Script.sol";
contract DeployNFTBridge is Script {
NFTImplementation nftImpl;
NFTBridgeSetup nftBridgeSetup;
NFTBridgeImplementation nftBridgeImpl;
function dryRun(
uint16 chainId,
uint16 governanceChainId,
bytes32 governanceContract,
uint8 finality,
uint256 evmChainId,
address wormhole
) public {
_deploy(
chainId,
governanceChainId,
governanceContract,
finality,
evmChainId,
wormhole
);
}
function run(
uint16 chainId,
uint16 governanceChainId,
bytes32 governanceContract,
uint8 finality,
uint256 evmChainId,
address wormhole
)
public
returns (
address deployedAddress,
address nftImplementationAddress,
address setupAddress,
address implementationAddress
)
{
vm.startBroadcast();
(
deployedAddress,
nftImplementationAddress,
setupAddress,
implementationAddress
) = _deploy(
chainId,
governanceChainId,
governanceContract,
finality,
evmChainId,
wormhole
);
vm.stopBroadcast();
}
function _deploy(
uint16 chainId,
uint16 governanceChainId,
bytes32 governanceContract,
uint8 finality,
uint256 evmChainId,
address wormhole
)
internal
returns (
address deployedAddress,
address nftImplementationAddress,
address setupAddress,
address implementationAddress
)
{
nftImpl = new NFTImplementation();
nftBridgeSetup = new NFTBridgeSetup();
nftBridgeImpl = new NFTBridgeImplementation();
NFTBridgeEntrypoint nftBridge = new NFTBridgeEntrypoint(
address(nftBridgeSetup),
abi.encodeWithSignature(
"setup(address,uint16,address,uint16,bytes32,address,uint8,uint256)",
address(nftBridgeImpl),
chainId,
wormhole,
governanceChainId,
governanceContract,
address(nftImpl),
finality,
evmChainId
)
);
return (
address(nftBridge),
address(nftImpl),
address(nftBridgeSetup),
address(nftBridgeImpl)
);
}
}

View File

@ -0,0 +1,105 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import {ERC20PresetMinterPauser} from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol";
import {ERC721PresetMinterPauserAutoId} from "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol";
import {MockWETH9} from "../contracts/bridge/mock/MockWETH9.sol";
import {TokenImplementation} from "../contracts/bridge/token/TokenImplementation.sol";
import "forge-std/Script.sol";
contract DeployTestToken is Script {
function dryRun() public {
_deploy();
}
function run()
public
returns (
address deployedTokenAddress,
address deployedNFTaddress,
address deployedWETHaddress,
address deployedAccountantTokenAddress
)
{
vm.startBroadcast();
(
deployedTokenAddress,
deployedNFTaddress,
deployedWETHaddress,
deployedAccountantTokenAddress
) = _deploy();
vm.stopBroadcast();
}
function _deploy()
internal
returns (
address deployedTokenAddress,
address deployedNFTaddress,
address deployedWETHaddress,
address deployedAccountantTokenAddress
)
{
address[] memory accounts = new address[](13);
accounts[0] = 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1;
accounts[1] = 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0;
accounts[2] = 0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b;
accounts[3] = 0xE11BA2b4D45Eaed5996Cd0823791E0C93114882d;
accounts[4] = 0xd03ea8624C8C5987235048901fB614fDcA89b117;
accounts[5] = 0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC;
accounts[6] = 0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9;
accounts[7] = 0x28a8746e75304c0780E011BEd21C72cD78cd535E;
accounts[8] = 0xACa94ef8bD5ffEE41947b4585a84BdA5a3d3DA6E;
accounts[9] = 0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e;
accounts[10] = 0x610Bb1573d1046FCb8A70Bbbd395754cD57C2b60;
accounts[11] = 0x855FA758c77D68a04990E992aA4dcdeF899F654A;
accounts[12] = 0xfA2435Eacf10Ca62ae6787ba2fB044f8733Ee843;
ERC20PresetMinterPauser token = new ERC20PresetMinterPauser(
"Ethereum Test Token",
"TKN"
);
console.log("Token deployed at: ", address(token));
// mint 1000 units
token.mint(accounts[0], 1_000_000_000_000_000_000_000);
ERC721PresetMinterPauserAutoId nft = new ERC721PresetMinterPauserAutoId(
unicode"Not an APE🐒",
unicode"APE🐒",
"https://cloudflare-ipfs.com/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/"
);
nft.mint(accounts[0]);
nft.mint(accounts[0]);
console.log("NFT deployed at: ", address(nft));
MockWETH9 mockWeth = new MockWETH9();
console.log("WETH token deployed at: ", address(mockWeth));
for(uint16 i=2; i<11; i++) {
token.mint(accounts[i], 1_000_000_000_000_000_000_000);
}
ERC20PresetMinterPauser accountantToken = new ERC20PresetMinterPauser(
"Accountant Test Token",
"GA"
);
console.log(
"Accountant test token deployed at: ",
address(accountantToken)
);
// mint 1000 units
accountantToken.mint(accounts[9], 1_000_000_000_000_000_000_000);
return (
address(token),
address(nft),
address(mockWeth),
address(accountantToken)
);
}
}

View File

@ -0,0 +1,29 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import {INFTBridge} from "../contracts/nft/interfaces/INFTBridge.sol";
import "forge-std/Script.sol";
contract RegisterChainsNFTBridge is Script {
// DryRun - Register chains
// dry run: forge script RegisterChainsNFTBridge --sig "dryRun(address,bytes[])" --rpc-url $RPC
function dryRun(address nftBridge, bytes[] memory registrationVaas) public {
_registerChains(nftBridge, registrationVaas);
}
// Register chains
// forge script RegisterChainsNFTBridge --sig "run(address,bytes[])" --rpc-url $RPC --private-key $RAW_PRIVATE_KEY --broadcast
function run(address nftBridge, bytes[] memory registrationVaas) public {
vm.startBroadcast();
_registerChains(nftBridge, registrationVaas);
vm.stopBroadcast();
}
function _registerChains(address nftBridge, bytes[] memory registrationVaas) internal {
INFTBridge nftBridgeContract = INFTBridge(nftBridge);
uint256 len = registrationVaas.length;
for(uint256 i=0; i<len; i++) {
nftBridgeContract.registerChain(registrationVaas[i]);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,6 @@
"author": "",
"license": "ISC",
"dependencies": {
"@certusone/wormhole-sdk": "^0.9.11",
"@typechain/ethers-v5": "^10.2.0",
"dotenv": "^10.0.0",
"elliptic": "^6.5.2",

View File

@ -1,6 +1,6 @@
#!/bin/bash
# MNEMONIC=<redacted> ./forge-scripts/deployCoreBridge.sh
# MNEMONIC=<redacted> ./sh/deployCoreBridge.sh
. .env

View File

@ -1,6 +1,6 @@
#!/bin/bash
# MNEMONIC=<redacted> ./forge-scripts/deployCoreShutdown.sh
# MNEMONIC=<redacted> ./sh/deployCoreShutdown.sh
. .env

View File

@ -0,0 +1,14 @@
#!/bin/bash
[[ -z $MNEMONIC ]] && { echo "Missing MNEMONIC"; exit 1; }
[[ -z $RPC_URL ]] && { echo "Missing RPC_URL"; exit 1; }
[[ -z $NUM_RUNS ]] && { echo "Missing NUM_RUNS"; exit 1; }
# Deploy dummy contract(s) to match devnet addresses in Anvil to what they originally were in Ganache
# (the addresses depend on the number of contracts that have been previously deployed, and the wallet address, I believe!)
forge script ./forge-scripts/DeployDummyContract.s.sol:DeployDummyContract \
--sig "run(uint256)" $NUM_RUNS \
--rpc-url "$RPC_URL" \
--private-key "$MNEMONIC" \
--broadcast

38
ethereum/sh/deployNFTBridge.sh Executable file
View File

@ -0,0 +1,38 @@
#!/bin/bash
# MNEMONIC=<redacted> WORMHOLE_ADDRESS=<from_the_previous_command> ./sh/deployNFTBridge.sh
. .env
[[ -z $INIT_EVM_CHAIN_ID ]] && { echo "Missing INIT_EVM_CHAIN_ID"; exit 1; }
[[ -z $BRIDGE_INIT_CHAIN_ID ]] && { echo "Missing BRIDGE_INIT_CHAIN_ID"; exit 1; }
[[ -z $BRIDGE_INIT_GOV_CHAIN_ID ]] && { echo "Missing BRIDGE_INIT_GOV_CHAIN_ID"; exit 1; }
[[ -z $BRIDGE_INIT_GOV_CONTRACT ]] && { echo "Missing BRIDGE_INIT_GOV_CONTRACT"; exit 1; }
[[ -z $BRIDGE_INIT_WETH ]] && { echo "Missing BRIDGE_INIT_WETH"; exit 1; }
[[ -z $BRIDGE_INIT_FINALITY ]] && { echo "Missing BRIDGE_INIT_FINALITY"; exit 1; }
[[ -z $WORMHOLE_ADDRESS ]] && { echo "Missing WORMHOLE_ADDRESS"; exit 1; }
[[ -z $MNEMONIC ]] && { echo "Missing MNEMONIC"; exit 1; }
[[ -z $RPC_URL ]] && { echo "Missing RPC_URL"; exit 1; }
forge script ./forge-scripts/DeployNFTBridge.s.sol:DeployNFTBridge \
--sig "run(uint16,uint16,bytes32,uint8,uint256,address)" $INIT_CHAIN_ID $INIT_GOV_CHAIN_ID $INIT_GOV_CONTRACT $BRIDGE_INIT_FINALITY $INIT_EVM_CHAIN_ID $WORMHOLE_ADDRESS \
--rpc-url "$RPC_URL" \
--private-key "$MNEMONIC" \
--broadcast
returnInfo=$(cat ./broadcast/DeployNFTBridge.s.sol/$INIT_EVM_CHAIN_ID/run-latest.json)
# Extract the address values from 'returnInfo'
NFT_BRIDGE_ADDRESS=$(jq -r '.returns.deployedAddress.value' <<< "$returnInfo")
NFT_IMPLEMENTATION_ADDRESS=$(jq -r '.returns.nftImplementationAddress.value' <<< "$returnInfo")
NFT_BRIDGE_SETUP_ADDRESS=$(jq -r '.returns.setupAddress.value' <<< "$returnInfo")
NFT_BRIDGE_IMPLEMENTATION_ADDRESS=$(jq -r '.returns.implementationAddress.value' <<< "$returnInfo")
echo "-- NFTBridge Addresses ----------------------------------------------------~~"
echo "| NFT Implementation address | $NFT_IMPLEMENTATION_ADDRESS |"
echo "| NFTBridgeSetup address | $NFT_BRIDGE_SETUP_ADDRESS |"
echo "| NFTBridgeImplementation address | $NFT_BRIDGE_IMPLEMENTATION_ADDRESS |"
echo "| NFTBridge address | $NFT_BRIDGE_ADDRESS |"
echo "-----------------------------------------------------------------------------"

View File

@ -1,6 +1,6 @@
#!/bin/bash
# MNEMONIC=<redacted> WORMHOLE_ADDRESS=<from_the_previous_command> ./forge-scripts/deployTokenBridge.sh
# MNEMONIC=<redacted> WORMHOLE_ADDRESS=<from_the_previous_command> ./sh/deployTokenBridge.sh
. .env

View File

@ -1,6 +1,6 @@
#!/bin/bash
# MNEMONIC=<redacted> ./forge-scripts/deployTokenBridgeShutdown.sh
# MNEMONIC=<redacted> ./sh/deployTokenBridgeShutdown.sh
. .env

View File

@ -0,0 +1,84 @@
#!/bin/bash
if [ "$DEV" != "True" ]; then
if [ $CHAIN_ID -eq 4 ]; then
RPC_URL='http://localhost:8545'
else
RPC_URL='http://localhost:8545'
fi
else
if [ $CHAIN_ID -eq 4 ]; then
RPC_URL='http://localhost:8545'
else
RPC_URL='http://localhost:8545'
fi
fi
# Load the environment variables from .env
if [ -f .env ]; then
source .env
else
echo "The .env file does not exist."
exit 1
fi
MNEMONIC=0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d
NETWORK='devnet'
npm run build:forge
NUM_RUNS=2 source ./sh/deployDummyContract.sh
echo "Deploying WORMHOLE_CORE"
source ./sh/deployCoreBridge.sh
returnInfo=$(cat ./broadcast/DeployCore.s.sol/$INIT_EVM_CHAIN_ID/run-latest.json)
WORMHOLE_ADDRESS=$(jq -r '.returns.deployedAddress.value' <<< "$returnInfo")
echo "WORMHOLE_ADDRESS: ${WORMHOLE_ADDRESS}"
NUM_RUNS=1 source ./sh/deployDummyContract.sh
echo "Deploying TOKEN_BRIDGE"
source ./sh/deployTokenBridge.sh
returnInfo=$(cat ./broadcast/DeployTokenBridge.s.sol/$INIT_EVM_CHAIN_ID/run-latest.json)
TOKEN_BRIDGE_ADDRESS=$(jq -r '.returns.deployedAddress.value' <<< "$returnInfo")
echo "TOKEN_BRIDGE_ADDRESS: $TOKEN_BRIDGE_ADDRESS"
NUM_RUNS=1 source ./sh/deployDummyContract.sh
echo "Deploying NFT_BRIDGE"
source ./sh/deployNFTBridge.sh
returnInfo=$(cat ./broadcast/DeployNFTBridge.s.sol/$INIT_EVM_CHAIN_ID/run-latest.json)
NFT_BRIDGE_ADDRESS=$(jq -r '.returns.deployedAddress.value' <<< "$returnInfo")
echo "NFT_BRIDGE_ADDRESS: $NFT_BRIDGE_ADDRESS"
NUM_RUNS=17 source ./sh/deployDummyContract.sh
echo "Deploying test tokens"
forge script ./forge-scripts/DeployTestToken.s.sol:DeployTestToken --rpc-url $RPC_URL --private-key $MNEMONIC --broadcast
echo "Done deploying test tokens"
# Registration of chains
token_bridge_registration_vaas_arr=()
nft_bridge_registration_vaas_arr=()
while IFS= read -r line; do
# Use a regular expression to match the desired pattern
if [[ "$line" =~ ^REGISTER_.*_TOKEN_BRIDGE_VAA=([^[:space:]]+) ]]; then
token_bridge_registration_vaas_arr+=("0x${BASH_REMATCH[1]}")
fi
if [[ "$line" =~ ^REGISTER_.*_NFT_BRIDGE_VAA=([^[:space:]]+) ]]; then
nft_bridge_registration_vaas_arr+=("0x${BASH_REMATCH[1]}")
fi
done < ".env"
TOKEN_BRIDGE_REGISTRATION_VAAS="[$(IFS=','; echo "${token_bridge_registration_vaas_arr[*]}")]";
NFT_BRIDGE_REGISTRATION_VAAS="[$(IFS=','; echo "${nft_bridge_registration_vaas_arr[*]}")]";
echo "Registering chains on token bridge"
echo "TOKEN_BRIDGE_REGISTRATION_VAAS: $TOKEN_BRIDGE_REGISTRATION_VAAS"
source "./sh/registerChainsTokenBridge.sh"
echo "Done registering chains on token bridge"
echo "Registering chains on nft bridge"
echo "NFT_BRIDGE_REGISTRATION_VAAS: $NFT_BRIDGE_REGISTRATION_VAAS"
source "./sh/registerChainsNFTBridge.sh"
echo "Done registering chains on nft bridge"

View File

@ -6,7 +6,7 @@
# find a VAA for that chain in the CSV file (as a sanity check). Please be sure to generate
# the registation VAA for this chain and add it to the file before running this script.
# MNEMONIC=<redacted> ./forge-scripts/registerAllChainsOnTokenBridge.sh testnet blast
# MNEMONIC=<redacted> ./sh/registerAllChainsOnTokenBridge.sh testnet blast
if [ $# != 2 ]; then
echo "Usage: $0 testnet blast" >&2

View File

@ -0,0 +1,16 @@
#!/bin/bash
# MNEMONIC=<redacted> ./sh/registerChainsNFTBridge.sh
. .env
[[ -z $MNEMONIC ]] && { echo "Missing MNEMONIC"; exit 1; }
[[ -z $RPC_URL ]] && { echo "Missing RPC_URL"; exit 1; }
[[ -z $NFT_BRIDGE_ADDRESS ]] && { echo "Missing NFT_BRIDGE_ADDRESS"; exit 1; }
[[ -z $NFT_BRIDGE_REGISTRATION_VAAS ]] && { echo "Missing NFT_BRIDGE_REGISTRATION_VAAS"; exit 1; }
forge script ./forge-scripts/RegisterChainsNFTBridge.s.sol:RegisterChainsNFTBridge \
--sig "run(address,bytes[])" $NFT_BRIDGE_ADDRESS $NFT_BRIDGE_REGISTRATION_VAAS \
--rpc-url $RPC_URL \
--private-key $MNEMONIC \
--broadcast

View File

@ -0,0 +1,16 @@
#!/bin/bash
# MNEMONIC=<redacted> ./sh/registerChainsTokenBridge.sh
. .env
[[ -z $MNEMONIC ]] && { echo "Missing MNEMONIC"; exit 1; }
[[ -z $RPC_URL ]] && { echo "Missing RPC_URL"; exit 1; }
[[ -z $TOKEN_BRIDGE_ADDRESS ]] && { echo "Missing TOKEN_BRIDGE_ADDRESS"; exit 1; }
[[ -z $TOKEN_BRIDGE_REGISTRATION_VAAS ]] && { echo "Missing TOKEN_BRIDGE_REGISTRATION_VAAS"; exit 1; }
forge script ./forge-scripts/RegisterChainsTokenBridge.s.sol:RegisterChainsTokenBridge \
--sig "run(address,bytes[])" $TOKEN_BRIDGE_ADDRESS $TOKEN_BRIDGE_REGISTRATION_VAAS \
--rpc-url $RPC_URL \
--private-key $MNEMONIC \
--broadcast

View File

@ -1,6 +1,6 @@
#!/bin/bash
#MNEMONIC= ./forge-scripts/upgrade.sh testnet Core blast
#MNEMONIC= ./sh/upgrade.sh testnet Core blast
set -euo pipefail

View File

@ -1,5 +1,5 @@
# syntax=docker.io/docker/dockerfile:1.3@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2
FROM --platform=linux/amd64 docker.io/golang:1.20.10-bullseye@sha256:082569b3303b164cc4a7c88ac59b19b69c1a5d662041ac0dca046ac239632442 AS build
FROM --platform=linux/amd64 docker.io/golang:1.21.9-bullseye@sha256:311468bffa9fa4747a334b94e6ce3681b564126d653675a6adc46698b2b88d35 AS build
# libwasmvm.so is not compatible with arm
WORKDIR /app

View File

@ -60,6 +60,11 @@ var ibcUpdateChannelChainChainId *string
var recoverChainIdEvmChainId *string
var recoverChainIdNewChainId *string
var governanceContractAddress *string
var governanceTargetAddress *string
var governanceTargetChain *string
var governanceCallData *string
func init() {
governanceFlagSet := pflag.NewFlagSet("governance", pflag.ExitOnError)
chainID = governanceFlagSet.String("chain-id", "", "Chain ID")
@ -171,6 +176,19 @@ func init() {
AdminClientRecoverChainIdCmd.Flags().AddFlagSet(recoverChainIdFlagSet)
AdminClientRecoverChainIdCmd.Flags().AddFlagSet(moduleFlagSet)
TemplateCmd.AddCommand(AdminClientRecoverChainIdCmd)
// flags for general-purpose governance call command
generalPurposeGovernanceFlagSet := pflag.NewFlagSet("general-purpose-governance", pflag.ExitOnError)
governanceContractAddress = generalPurposeGovernanceFlagSet.String("governance-contract", "", "Governance contract address")
governanceTargetAddress = generalPurposeGovernanceFlagSet.String("target-address", "", "Address of the governed contract")
governanceCallData = generalPurposeGovernanceFlagSet.String("call-data", "", "calldata")
governanceTargetChain = generalPurposeGovernanceFlagSet.String("chain-id", "", "Chain ID")
// evm call command
AdminClientGeneralPurposeGovernanceEvmCallCmd.Flags().AddFlagSet(generalPurposeGovernanceFlagSet)
TemplateCmd.AddCommand(AdminClientGeneralPurposeGovernanceEvmCallCmd)
// solana call command
AdminClientGeneralPurposeGovernanceSolanaCallCmd.Flags().AddFlagSet(generalPurposeGovernanceFlagSet)
TemplateCmd.AddCommand(AdminClientGeneralPurposeGovernanceSolanaCallCmd)
}
var TemplateCmd = &cobra.Command{
@ -292,6 +310,18 @@ var AdminClientWormholeRelayerSetDefaultDeliveryProviderCmd = &cobra.Command{
Run: runWormholeRelayerSetDefaultDeliveryProviderTemplate,
}
var AdminClientGeneralPurposeGovernanceEvmCallCmd = &cobra.Command{
Use: "governance-evm-call",
Short: "Generate a 'general purpose evm governance call' template for specified chain and address",
Run: runGeneralPurposeGovernanceEvmCallTemplate,
}
var AdminClientGeneralPurposeGovernanceSolanaCallCmd = &cobra.Command{
Use: "governance-solana-call",
Short: "Generate a 'general purpose solana governance call' template for specified chain and address",
Run: runGeneralPurposeGovernanceSolanaCallTemplate,
}
func runGuardianSetTemplate(cmd *cobra.Command, args []string) {
// Use deterministic devnet addresses as examples in the template, such that this doubles as a test fixture.
guardians := make([]*nodev1.GuardianSetUpdate_Guardian, *setUpdateNumGuardians)
@ -932,6 +962,100 @@ func runWormholeRelayerSetDefaultDeliveryProviderTemplate(cmd *cobra.Command, ar
fmt.Print(string(b))
}
func runGeneralPurposeGovernanceEvmCallTemplate(cmd *cobra.Command, args []string) {
if *governanceTargetAddress == "" {
log.Fatal("--target-address must be specified")
}
if !common.IsHexAddress(*governanceTargetAddress) {
log.Fatal("invalid target address")
}
governanceTargetAddress := common.HexToAddress(*governanceTargetAddress).Hex()
if *governanceCallData == "" {
log.Fatal("--call-data must be specified")
}
if *governanceContractAddress == "" {
log.Fatal("--governance-contract must be specified")
}
if !common.IsHexAddress(*governanceContractAddress) {
log.Fatal("invalid governance contract address")
}
governanceContractAddress := common.HexToAddress(*governanceContractAddress).Hex()
if *governanceTargetChain == "" {
log.Fatal("--chain-id must be specified")
}
chainID, err := parseChainID(*governanceTargetChain)
if err != nil {
log.Fatal("failed to parse chain id: ", err)
}
m := &nodev1.InjectGovernanceVAARequest{
CurrentSetIndex: uint32(*templateGuardianIndex),
Messages: []*nodev1.GovernanceMessage{
{
Sequence: rand.Uint64(),
Nonce: rand.Uint32(),
Payload: &nodev1.GovernanceMessage_EvmCall{
EvmCall: &nodev1.EvmCall{
ChainId: uint32(chainID),
GovernanceContract: governanceContractAddress,
TargetContract: governanceTargetAddress,
AbiEncodedCall: *governanceCallData,
},
},
},
},
}
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
if err != nil {
panic(err)
}
fmt.Print(string(b))
}
func runGeneralPurposeGovernanceSolanaCallTemplate(cmd *cobra.Command, args []string) {
if *governanceCallData == "" {
log.Fatal("--call-data must be specified")
}
if *governanceContractAddress == "" {
log.Fatal("--governance-contract must be specified")
}
_, err := base58.Decode(*governanceContractAddress)
if err != nil {
log.Fatal("invalid base58 governance contract address")
}
if *governanceTargetChain == "" {
log.Fatal("--chain-id must be specified")
}
chainID, err := parseChainID(*governanceTargetChain)
if err != nil {
log.Fatal("failed to parse chain id: ", err)
}
m := &nodev1.InjectGovernanceVAARequest{
CurrentSetIndex: uint32(*templateGuardianIndex),
Messages: []*nodev1.GovernanceMessage{
{
Sequence: rand.Uint64(),
Nonce: rand.Uint32(),
Payload: &nodev1.GovernanceMessage_SolanaCall{
SolanaCall: &nodev1.SolanaCall{
ChainId: uint32(chainID),
GovernanceContract: *governanceContractAddress,
EncodedInstruction: *governanceCallData,
},
},
},
},
}
b, err := prototext.MarshalOptions{Multiline: true}.Marshal(m)
if err != nil {
panic(err)
}
fmt.Print(string(b))
}
// parseAddress parses either a hex-encoded address and returns
// a left-padded 32 byte hex string.
func parseAddress(s string) (string, error) {

View File

@ -182,8 +182,10 @@ var (
xlayerRPC *string
xlayerContract *string
lineaRPC *string
lineaContract *string
lineaRPC *string
lineaContract *string
lineaRollUpUrl *string
lineaRollUpContract *string
berachainRPC *string
berachainContract *string
@ -386,6 +388,8 @@ func init() {
lineaRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "lineaRPC", "Linea RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"})
lineaContract = NodeCmd.Flags().String("lineaContract", "", "Linea contract address")
lineaRollUpUrl = NodeCmd.Flags().String("lineaRollUpUrl", "", "Linea roll up URL")
lineaRollUpContract = NodeCmd.Flags().String("lineaRollUpContract", "", "Linea roll up contract address")
berachainRPC = node.RegisterFlagWithValidationOrFail(NodeCmd, "berachainRPC", "Berachain RPC URL", "ws://eth-devnet:8545", []string{"ws", "wss"})
berachainContract = NodeCmd.Flags().String("berachainContract", "", "Berachain contract address")
@ -802,6 +806,9 @@ func runNode(cmd *cobra.Command, args []string) {
if (*lineaRPC == "") != (*lineaContract == "") {
logger.Fatal("Both --lineaContract and --lineaRPC must be set together or both unset")
}
if (*lineaRPC != "") && (*lineaRollUpUrl == "" || *lineaRollUpContract == "") && !*unsafeDevMode {
logger.Fatal("If --lineaRPC is specified, --lineaRollUpUrl and --lineaRollUpContract must also be specified")
}
if *berachainRPC != "" && !*testnetMode && !*unsafeDevMode {
logger.Fatal("berachain is currently only supported in devnet and testnet")
@ -1506,11 +1513,13 @@ func runNode(cmd *cobra.Command, args []string) {
if shouldStart(lineaRPC) {
wc := &evm.WatcherConfig{
NetworkID: "linea",
ChainID: vaa.ChainIDLinea,
Rpc: *lineaRPC,
Contract: *lineaContract,
CcqBackfillCache: *ccqBackfillCache,
NetworkID: "linea",
ChainID: vaa.ChainIDLinea,
Rpc: *lineaRPC,
Contract: *lineaContract,
CcqBackfillCache: *ccqBackfillCache,
LineaRollUpUrl: *lineaRollUpUrl,
LineaRollUpContract: *lineaRollUpContract,
}
watcherConfigs = append(watcherConfigs, wc)

View File

@ -1,6 +1,6 @@
module github.com/certusone/wormhole/node
go 1.20
go 1.21.9
require (
github.com/celo-org/celo-blockchain v1.5.5
@ -11,21 +11,21 @@ require (
github.com/ethereum/go-ethereum v1.10.21
github.com/gagliardetto/solana-go v1.8.4
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2
github.com/improbable-eng/grpc-web v0.15.0
github.com/ipfs/go-log/v2 v2.5.1
github.com/libp2p/go-libp2p v0.32.2
github.com/libp2p/go-libp2p v0.33.1
github.com/libp2p/go-libp2p-kad-dht v0.25.2
github.com/libp2p/go-libp2p-pubsub v0.10.0
github.com/miguelmota/go-ethereum-hdwallet v0.1.0
github.com/mitchellh/go-homedir v1.1.0
github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-multiaddr v0.12.0
github.com/multiformats/go-multiaddr v0.12.2
github.com/near/borsh-go v0.3.0
github.com/prometheus/client_golang v1.16.0
github.com/prometheus/client_golang v1.18.0
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.14.0
@ -33,10 +33,10 @@ require (
github.com/stretchr/testify v1.8.4
github.com/tendermint/tendermint v0.34.24
github.com/tidwall/gjson v1.15.0
go.uber.org/zap v1.26.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.19.0
golang.org/x/sys v0.17.0
golang.org/x/time v0.3.0
golang.org/x/time v0.5.0
google.golang.org/api v0.126.0
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/grpc v1.57.1
@ -52,16 +52,16 @@ require (
github.com/cosmos/cosmos-sdk v0.45.11
github.com/go-kit/kit v0.12.0
github.com/golang/snappy v0.0.4
github.com/google/uuid v1.3.0
github.com/google/uuid v1.4.0
github.com/grafana/dskit v0.0.0-20230201083518-528d8a7d52f2
github.com/grafana/loki v1.6.2-0.20230721141808-0d81144cfee8
github.com/hashicorp/golang-lru v0.6.0
github.com/holiman/uint256 v1.2.1
github.com/prometheus/client_model v0.4.0
github.com/prometheus/common v0.44.0
github.com/prometheus/client_model v0.6.0
github.com/prometheus/common v0.47.0
github.com/wormhole-foundation/wormchain v0.0.0-00010101000000-000000000000
github.com/wormhole-foundation/wormhole/sdk v0.0.0-20220926172624-4b38dc650bb0
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e
gopkg.in/godo.v2 v2.0.9
nhooyr.io/websocket v1.8.7
@ -106,7 +106,7 @@ require (
github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/cosmos/iavl v0.19.4 // indirect
github.com/cosmos/ibc-go/v4 v4.2.2 // indirect
github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect
github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect
github.com/creachadair/taskgroup v0.3.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
@ -126,7 +126,7 @@ require (
github.com/elastic/gosigar v0.14.2 // indirect
github.com/fatih/color v1.14.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/flynn/noise v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gagliardetto/binary v0.7.7 // indirect
@ -163,7 +163,7 @@ require (
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/orderedcode v0.0.1 // indirect
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/gorilla/handlers v1.5.1 // indirect
@ -205,14 +205,14 @@ require (
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/julienschmidt/httprouter v1.3.0 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/klauspost/compress v1.17.6 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/lib/pq v1.10.6 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
github.com/libp2p/go-libp2p-record v0.2.0 // indirect
github.com/libp2p/go-libp2p-routing-helpers v0.7.2 // indirect
@ -228,9 +228,8 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mgutz/str v1.2.0 // indirect
github.com/miekg/dns v1.1.56 // indirect
github.com/miekg/dns v1.1.58 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
@ -254,10 +253,10 @@ require (
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo/v2 v2.13.0 // indirect
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
github.com/onsi/gomega v1.30.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e // indirect
github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
@ -271,12 +270,11 @@ require (
github.com/prometheus/alertmanager v0.25.0 // indirect
github.com/prometheus/common/sigv4 v0.1.0 // indirect
github.com/prometheus/exporter-toolkit v0.8.2 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/prometheus v0.42.0 // indirect
github.com/prometheus/tsdb v0.7.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
github.com/quic-go/quic-go v0.39.4 // indirect
github.com/quic-go/quic-go v0.42.0 // indirect
github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/rakyll/statik v0.1.7 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
@ -316,13 +314,13 @@ require (
github.com/weaveworks/common v0.0.0-20230531151736-e2613bee6b73 // indirect
github.com/weaveworks/promrus v1.2.0 // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
github.com/zondax/hid v0.9.1 // indirect
github.com/zondax/ledger-go v0.14.0 // indirect
github.com/zondax/hid v0.9.2 // indirect
github.com/zondax/ledger-go v0.14.3 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.etcd.io/etcd/api/v3 v3.5.5 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect
go.etcd.io/etcd/client/v3 v3.5.5 // indirect
go.mongodb.org/mongo-driver v1.11.0 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
go.opentelemetry.io/otel v1.21.0 // indirect
@ -331,17 +329,17 @@ require (
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/dig v1.17.1 // indirect
go.uber.org/fx v1.20.1 // indirect
go.uber.org/goleak v1.2.0 // indirect
go.uber.org/mock v0.3.0 // indirect
go.uber.org/goleak v1.3.0 // indirect
go.uber.org/mock v0.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/mod v0.15.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/oauth2 v0.10.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/oauth2 v0.16.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/term v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.14.0 // indirect
golang.org/x/tools v0.18.0 // indirect
gonum.org/v1/gonum v0.13.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect

View File

@ -454,6 +454,7 @@ github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo
github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v42.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible h1:HzKLt3kIwMm4KeJYTdx9EbjRYTySD/t8i1Ee/W5EGXw=
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
@ -477,6 +478,7 @@ github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUd
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM=
github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
@ -486,6 +488,7 @@ github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQW
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.22 h1:/GblQdIudfEM3AWWZ0mrYJQSd7JS4S/Mbzh6F0ov0Xc=
github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk=
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
@ -500,9 +503,11 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935
github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
@ -558,6 +563,7 @@ github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpz
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
@ -580,6 +586,7 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.6 h1:U68crOE3y3MPttCMQGywZOLrTeF5HHJ3/vDBCJn9/bA=
github.com/OneOfOne/xxhash v1.2.6/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
github.com/OpenPeeDeeP/depguard v1.1.0/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@ -842,6 +849,7 @@ github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
@ -1026,9 +1034,10 @@ github.com/cosmos/ibc-go v1.2.2/go.mod h1:XmYjsRFOs6Q9Cz+CSsX21icNoH27vQKb3squgn
github.com/cosmos/ibc-go/v4 v4.2.2 h1:1Tdjj4H6L+iGoDmT/zvJDAysWZpE2kW1twl7u6KKIJY=
github.com/cosmos/ibc-go/v4 v4.2.2/go.mod h1:EFFqkrJHQPHWUlw155QUxGuis4Ett4lvewAT5nvX0yU=
github.com/cosmos/interchain-accounts v0.2.4 h1:7UrroFQsCRSp17980mk6anx4YteveIJVkU+a0wlsHQI=
github.com/cosmos/interchain-accounts v0.2.4/go.mod h1:jeiJEb0zg609G0oCrCG0r6Guhb7YbA1uFiwww/1YgZE=
github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w=
github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g=
github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw=
github.com/cosmos/ledger-cosmos-go v0.12.4/go.mod h1:fjfVWRf++Xkygt9wzCsjEBdjcf7wiiY35fv3ctT+k4M=
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
@ -1068,6 +1077,7 @@ github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vs
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
@ -1100,6 +1110,7 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/digitalocean/godo v1.95.0 h1:S48/byPKui7RHZc1wYEPfRvkcEvToADNb5I3guu95xg=
github.com/digitalocean/godo v1.95.0/go.mod h1:NRpFznZFvhHjBoqZAaOD3khVzsJ3EibzKqFL4R60dmA=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
@ -1129,6 +1140,7 @@ github.com/docker/docker v20.10.3-0.20211208011758-87521affb077+incompatible/go.
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.23+incompatible h1:1ZQUUYAdh+oylOT85aA2ZcfRp22jmLhoaEcVEfK8dyA=
github.com/docker/docker v20.10.23+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
@ -1170,6 +1182,7 @@ github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -1183,12 +1196,14 @@ github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPO
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34=
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA=
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q=
github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo=
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=
github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0=
github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM=
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
@ -1201,10 +1216,12 @@ github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
@ -1225,8 +1242,8 @@ github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
@ -1242,6 +1259,7 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM
github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
@ -1364,8 +1382,10 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 h1:JVrqSeQfdhYRFk24TvhTZWU0q8lfCojxZQFi3Ou7+uY=
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@ -1396,6 +1416,7 @@ github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzz
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
@ -1423,10 +1444,13 @@ github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY9
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk=
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
@ -1457,6 +1481,7 @@ github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
@ -1548,6 +1573,7 @@ github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv
github.com/google/flatbuffers v1.12.0 h1:/PtAHvnBY4Kqnx/xCQ3OIV9uYcSFGScBsWI3Oogeh6w=
github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -1608,8 +1634,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg=
github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
@ -1623,8 +1649,9 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s=
github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
@ -1657,8 +1684,10 @@ github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl
github.com/gookit/color v1.5.1/go.mod h1:wZFzea4X8qN6vHOSP2apMb4/+w/orMznEzYsIHPaqKM=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v1.1.1 h1:MuGyqbSxiuVBqkPZ3+Nhbytk1xZxhmfCB2Rg1cJWFWM=
github.com/gophercloud/gophercloud v1.1.1/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0=
github.com/goreleaser/goreleaser v0.136.0/go.mod h1:wiKrPUeSNh6Wu8nUHxZydSOVQ/OZvOaO7DTtFqie904=
@ -1680,8 +1709,9 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw=
@ -1755,11 +1785,13 @@ github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOj
github.com/hashicorp/consul/sdk v0.13.0 h1:lce3nFlpv8humJL8rNrrGHYSKc3q+Kxfeg3Ii1m6ZWU=
github.com/hashicorp/consul/sdk v0.13.0/go.mod h1:0hs/l5fOVhJy/VdcoaNqUSi2AUs95eF5WKtv+EYIQqE=
github.com/hashicorp/cronexpr v1.1.1 h1:NJZDd87hGXjoZBdvyCF9mX4DCq5Wy7+A/w+A7q0wn6c=
github.com/hashicorp/cronexpr v1.1.1/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
@ -1786,6 +1818,7 @@ github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
@ -1797,6 +1830,7 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
@ -1824,6 +1858,7 @@ github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOn
github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM=
github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
github.com/hashicorp/nomad/api v0.0.0-20230124213148-69fd1a0e4bf7 h1:XOdd3JHyeQnBRxotBo9ibxBFiYGuYhQU25s/YeV2cTU=
github.com/hashicorp/nomad/api v0.0.0-20230124213148-69fd1a0e4bf7/go.mod h1:xYYd4dybIhRhhzDemKx7Ddt8CvCosgrEek8YM7/cF0A=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
@ -1836,6 +1871,7 @@ github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87/go.mod
github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU=
github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo=
github.com/hetznercloud/hcloud-go v1.39.0 h1:RUlzI458nGnPR6dlcZlrsGXYC1hQlFbKdm8tVtEQQB0=
github.com/hetznercloud/hcloud-go v1.39.0/go.mod h1:mepQwR6va27S3UQthaEPGS86jtzSY9xWL1e9dyxXpgA=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
@ -1887,6 +1923,7 @@ github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mq
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po=
github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ=
github.com/ionos-cloud/sdk-go/v6 v6.1.3 h1:vb6yqdpiqaytvreM0bsn2pXw+1YDvEk2RKSmBAQvgDQ=
github.com/ionos-cloud/sdk-go/v6 v6.1.3/go.mod h1:Ox3W0iiEz0GHnfY9e5LmAxwklsxguuNFEUSu0gVRTME=
github.com/ipfs/boxo v0.10.0 h1:tdDAxq8jrsbRkYoF+5Rcqyeb91hgWe2hp7iLu7ORZLY=
github.com/ipfs/boxo v0.10.0/go.mod h1:Fg+BnfxZ0RPzR0nOodzdIq3A7KgoWAOWsEIImrIQdBM=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
@ -1896,6 +1933,7 @@ github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8=
github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
@ -1986,6 +2024,7 @@ github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4=
github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc=
@ -2007,17 +2046,18 @@ github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -2030,6 +2070,7 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
@ -2067,10 +2108,10 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
github.com/libp2p/go-libp2p v0.32.2 h1:s8GYN4YJzgUoyeYNPdW7JZeZ5Ee31iNaIBfGYMAY4FQ=
github.com/libp2p/go-libp2p v0.32.2/go.mod h1:E0LKe+diV/ZVJVnOJby8VC5xzHF0660osg71skcxJvk=
github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
github.com/libp2p/go-libp2p v0.33.1 h1:tvJl9b9M6nSLBtZSXSguq+/lRhRj2oLRkyhBmQNMFLA=
github.com/libp2p/go-libp2p v0.33.1/go.mod h1:zOUTMjG4I7TXwMndNyOBn/CNtVBLlvBlnxfi+8xzx+E=
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
github.com/libp2p/go-libp2p-kad-dht v0.25.2 h1:FOIk9gHoe4YRWXTu8SY9Z1d0RILol0TrtApsMDPjAVQ=
github.com/libp2p/go-libp2p-kad-dht v0.25.2/go.mod h1:6za56ncRHYXX4Nc2vn8z7CZK0P4QiMcrn77acKLM2Oo=
github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
@ -2082,6 +2123,7 @@ github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvN
github.com/libp2p/go-libp2p-routing-helpers v0.7.2 h1:xJMFyhQ3Iuqnk9Q2dYE1eUTzsah7NLw3Qs2zjUV78T0=
github.com/libp2p/go-libp2p-routing-helpers v0.7.2/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
@ -2095,6 +2137,7 @@ github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/linode/linodego v1.12.0 h1:33mOIrZ+gVva14gyJMKPZ85mQGovAvZCEP1ftgmFBjA=
github.com/linode/linodego v1.12.0/go.mod h1:NJlzvlNtdMRRkXb0oN6UWzUkj6t+IBsyveHgZ5Ppjyk=
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
@ -2174,8 +2217,6 @@ github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb44
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc=
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
@ -2189,8 +2230,8 @@ github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKju
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
@ -2240,6 +2281,7 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ=
@ -2296,8 +2338,8 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE=
github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8=
github.com/multiformats/go-multiaddr v0.12.2 h1:9G9sTY/wCYajKa9lyfWPmpZAwe6oV+Wb1zcmMS1HG24=
github.com/multiformats/go-multiaddr v0.12.2/go.mod h1:GKyaTYjZRdcUhyOetrxTk9z0cW+jA/YrnqTOvKgi44M=
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
@ -2389,8 +2431,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
@ -2422,6 +2464,7 @@ github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc10/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@ -2442,8 +2485,8 @@ github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/
github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
@ -2482,6 +2525,7 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9
github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/ovh/go-ovh v1.3.0 h1:mvZaddk4E4kLcXhzb+cxBsMPYp2pHqiQpWYkInsuZPQ=
github.com/ovh/go-ovh v1.3.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
@ -2562,8 +2606,8 @@ github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrb
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@ -2572,8 +2616,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
@ -2592,8 +2636,8 @@ github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k=
github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=
github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI=
github.com/prometheus/exporter-toolkit v0.8.2 h1:sbJAfBXQFkG6sUkbwBun8MNdzW9+wd5YfPYofbmj0YM=
@ -2614,8 +2658,8 @@ github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/prometheus v0.42.0 h1:G769v8covTkOiNckXFIwLx01XE04OE6Fr0JPA0oR2nI=
github.com/prometheus/prometheus v0.42.0/go.mod h1:Pfqb/MLnnR2KK+0vchiaH39jXxvLMBk+3lnIGP4N7Vk=
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
@ -2638,10 +2682,8 @@ github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:r
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.39.4 h1:PelfiuG7wXEffUT2yceiqz5V6Pc0TA5ruOd1LcmFc1s=
github.com/quic-go/quic-go v0.39.4/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
@ -2673,6 +2715,7 @@ github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
@ -2710,6 +2753,7 @@ github.com/sashamelentyev/usestdlibvars v1.8.0/go.mod h1:BFt7b5mSVHaaa26ZupiNRV2
github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.12 h1:Aaz4T7dZp7cB2cv7D/tGtRdSMh48sRaDYr7Jh0HV4qQ=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.12/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
@ -3023,6 +3067,7 @@ github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk=
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y=
github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo=
github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA=
github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY=
@ -3052,6 +3097,7 @@ github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZ
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/weaveworks/common v0.0.0-20230531151736-e2613bee6b73 h1:CMM9+/AgM77vaMXMQedzqPRMuNwjbI0EcdofPqxc9F8=
@ -3086,6 +3132,7 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6Ut
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk=
github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE=
github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA=
@ -3106,10 +3153,10 @@ github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo=
github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
github.com/zondax/ledger-go v0.14.0 h1:dlMC7aO8Wss1CxBq2I96kZ69Nh1ligzbs8UWOtq/AsA=
github.com/zondax/ledger-go v0.14.0/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320=
github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U=
github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw=
github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI=
gitlab.com/bosi/decorder v0.2.1/go.mod h1:6C/nhLSbF6qZbYD8bRmISBwc6vcWdNsiIBkRvjJFrH0=
gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@ -3147,8 +3194,9 @@ go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVd
go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE=
go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o=
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
@ -3233,10 +3281,10 @@ go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
@ -3258,8 +3306,8 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
@ -3337,8 +3385,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
@ -3357,7 +3405,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@ -3377,8 +3424,8 @@ golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -3515,8 +3562,8 @@ golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri
golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -3535,8 +3582,8 @@ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -3760,8 +3807,8 @@ golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -3899,8 +3946,8 @@ golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4
golang.org/x/tools v0.1.12-0.20220628192153-7743d1d949f1/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -4320,6 +4367,7 @@ k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs=
k8s.io/api v0.23.4/go.mod h1:i77F4JfyNNrhOjZF7OwwNJS5Y1S9dpwvb9iYRYRczfI=
k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ=
k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg=
k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apimachinery v0.17.4/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g=
k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
@ -4330,6 +4378,7 @@ k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ
k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U=
k8s.io/apimachinery v0.23.4/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ=
k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74=
k8s.io/apiserver v0.17.4/go.mod h1:5ZDQ6Xr5MNBxyi3iUZXS84QOhZl+W7Oq2us/29c0j9I=
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
@ -4344,6 +4393,7 @@ k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y=
k8s.io/client-go v0.23.4/go.mod h1:PKnIL4pqLuvYUK1WU7RLTMYKPiIh7MYShLshtRY9cj0=
k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU=
k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE=
k8s.io/cloud-provider v0.17.4/go.mod h1:XEjKDzfD+b9MTLXQFlDGkk6Ho8SGMpaU8Uugx/KNK9U=
k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
@ -4375,6 +4425,7 @@ k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
@ -4383,6 +4434,7 @@ k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2R
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715 h1:tBEbstoM+K0FiBV5KGAKQ0kuvf54v/hwpldiJt69w1s=
k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/legacy-cloud-providers v0.17.4/go.mod h1:FikRNoD64ECjkxO36gkDgJeiQWwyZTuBkhu+yxOc1Js=
@ -4394,6 +4446,7 @@ k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y=
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
@ -4421,6 +4474,7 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyz
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
@ -4430,9 +4484,11 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

View File

@ -1,5 +1,5 @@
# syntax=docker.io/docker/dockerfile:1.3@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2
FROM --platform=linux/amd64 docker.io/golang:1.20.10-bullseye@sha256:082569b3303b164cc4a7c88ac59b19b69c1a5d662041ac0dca046ac239632442 AS build
FROM --platform=linux/amd64 docker.io/golang:1.21.9-bullseye@sha256:311468bffa9fa4747a334b94e6ce3681b564126d653675a6adc46698b2b88d35 AS build
# libwasmvm.so is not compatible with arm
WORKDIR /app

View File

@ -21,7 +21,13 @@ func nttGetEmitters(env common.Environment) (validEmitters, validEmitters, error
var directEmitterConfig emitterConfig
arEmitterConfig := sdk.KnownAutomaticRelayerEmitters
if env == common.MainNet {
directEmitterConfig = emitterConfig{}
directEmitterConfig = emitterConfig{
{chainId: vaa.ChainIDSolana, addr: "cf5f3614e2cd9b374558f35c7618b25f0d306d5e749b7d29cc030a1a15686238"},
{chainId: vaa.ChainIDEthereum, addr: "000000000000000000000000Db55492d7190D1baE8ACbE03911C4E3E7426870c"},
{chainId: vaa.ChainIDArbitrum, addr: "000000000000000000000000D1a8AB69e00266e8B791a15BC47514153A5045a6"},
{chainId: vaa.ChainIDOptimism, addr: "0000000000000000000000009bD8b7b527CA4e6738cBDaBdF51C22466756073d"},
{chainId: vaa.ChainIDBase, addr: "000000000000000000000000D1a8AB69e00266e8B791a15BC47514153A5045a6"},
}
} else if env == common.TestNet {
directEmitterConfig = emitterConfig{
{chainId: vaa.ChainIDSolana, addr: "7e6436b671cce379a1fa9833783e28b36d39a00e2cdc6bfeab5d2d836eb61c7f"},

View File

@ -275,7 +275,7 @@ func TestNttParseArMsgUnknownArEmitter(t *testing.T) {
func TestNttVerifyMainnetEmitters(t *testing.T) {
directEmitters, arEmitters, err := nttGetEmitters(common.MainNet)
require.NoError(t, err)
assert.Equal(t, 0, len(directEmitters)) // TODO: Change this when we add a mainnet emitter!
assert.Equal(t, 5, len(directEmitters)) // TODO: Change this when we add a mainnet emitter!
assert.NotEqual(t, 0, len(arEmitters))
}

View File

@ -577,6 +577,58 @@ func wormholeRelayerSetDefaultDeliveryProvider(req *nodev1.WormholeRelayerSetDef
return v, nil
}
func evmCallToVaa(evmCall *nodev1.EvmCall, timestamp time.Time, guardianSetIndex, nonce uint32, sequence uint64) (*vaa.VAA, error) {
governanceContract := ethcommon.HexToAddress(evmCall.GovernanceContract)
targetContract := ethcommon.HexToAddress(evmCall.TargetContract)
payload, err := hex.DecodeString(evmCall.AbiEncodedCall)
if err != nil {
return nil, fmt.Errorf("failed to decode ABI encoded call: %w", err)
}
body, err := vaa.BodyGeneralPurposeGovernanceEvm{
ChainID: vaa.ChainID(evmCall.ChainId),
GovernanceContract: governanceContract,
TargetContract: targetContract,
Payload: payload,
}.Serialize()
if err != nil {
return nil, fmt.Errorf("failed to serialize governance body: %w", err)
}
v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex, body)
return v, nil
}
func solanaCallToVaa(solanaCall *nodev1.SolanaCall, timestamp time.Time, guardianSetIndex, nonce uint32, sequence uint64) (*vaa.VAA, error) {
address, err := base58.Decode(solanaCall.GovernanceContract)
if err != nil {
return nil, fmt.Errorf("failed to decode base58 governance contract address: %w", err)
}
if len(address) != 32 {
return nil, errors.New("invalid governance contract address length (expected 32 bytes)")
}
var governanceContract [32]byte
copy(governanceContract[:], address)
instruction, err := hex.DecodeString(solanaCall.EncodedInstruction)
if err != nil {
return nil, fmt.Errorf("failed to decode instruction: %w", err)
}
v := vaa.CreateGovernanceVAA(timestamp, nonce, sequence, guardianSetIndex,
vaa.BodyGeneralPurposeGovernanceSolana{
ChainID: vaa.ChainID(solanaCall.ChainId),
GovernanceContract: governanceContract,
Instruction: instruction,
}.Serialize())
return v, nil
}
func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, timestamp time.Time) (*vaa.VAA, error) {
var (
v *vaa.VAA
@ -620,6 +672,10 @@ func GovMsgToVaa(message *nodev1.GovernanceMessage, currentSetIndex uint32, time
v, err = ibcUpdateChannelChain(payload.IbcUpdateChannelChain, timestamp, currentSetIndex, message.Nonce, message.Sequence)
case *nodev1.GovernanceMessage_WormholeRelayerSetDefaultDeliveryProvider:
v, err = wormholeRelayerSetDefaultDeliveryProvider(payload.WormholeRelayerSetDefaultDeliveryProvider, timestamp, currentSetIndex, message.Nonce, message.Sequence)
case *nodev1.GovernanceMessage_EvmCall:
v, err = evmCallToVaa(payload.EvmCall, timestamp, currentSetIndex, message.Nonce, message.Sequence)
case *nodev1.GovernanceMessage_SolanaCall:
v, err = solanaCallToVaa(payload.SolanaCall, timestamp, currentSetIndex, message.Nonce, message.Sequence)
default:
panic(fmt.Sprintf("unsupported VAA type: %T", payload))
}

View File

@ -43,7 +43,9 @@ func OpenDb(logger *zap.Logger, dataDir *string) *Database {
options = badger.DefaultOptions("").WithInMemory(true)
}
options = options.WithLogger(badgerZapLogger{logger})
if logger != nil {
options = options.WithLogger(badgerZapLogger{logger})
}
db, err := badger.Open(options)
if err != nil {

View File

@ -69,6 +69,8 @@ const guardianSetIndex = 5 // index of the active guardian set (can be anything,
var TEST_ID_CTR atomic.Uint32
var logger *zap.Logger
func getTestId() uint {
return uint(TEST_ID_CTR.Add(1))
}
@ -145,10 +147,9 @@ func mockGuardianRunnable(t testing.TB, gs []*mockGuardian, mockGuardianIndex ui
// Create a sub-context with cancel function that we can pass to G.run.
ctx, ctxCancel := context.WithCancel(ctx)
defer ctxCancel()
logger := supervisor.Logger(ctx)
// setup db
db := db.OpenDb(logger, nil)
db := db.OpenDb(nil, nil)
defer db.Close()
gs[mockGuardianIndex].db = db
@ -511,8 +512,11 @@ func waitForStatusServer(ctx context.Context, logger *zap.Logger, statusAddr str
}
func TestMain(m *testing.M) {
logger, _ = zap.NewDevelopment()
readiness.NoPanic = true // otherwise we'd panic when running multiple guardians
os.Exit(m.Run())
retVal := m.Run()
logger.Info("test exiting", zap.Int("retVal", retVal))
os.Exit(retVal)
}
func createGovernanceMsgAndVaa(t testing.TB) (*common.MessagePublication, *nodev1.GovernanceMessage) {
@ -648,8 +652,6 @@ func runConsensusTests(t *testing.T, testCases []testCase, numGuardians int) {
zapLogger, zapObserver, _ := setupLogsCapture(t)
supervisor.New(rootCtx, zapLogger, func(ctx context.Context) error {
logger := supervisor.Logger(ctx)
// create the Guardian Set
gs := newMockGuardianSet(t, testId, numGuardians)
@ -838,8 +840,12 @@ func runConsensusTests(t *testing.T, testCases []testCase, numGuardians int) {
<-rootCtx.Done()
assert.NotEqual(t, rootCtx.Err(), context.DeadlineExceeded)
zapLogger.Info("Test root context cancelled, waiting 10ms for everything to shut down properly...")
time.Sleep(time.Millisecond * 10)
// There are some things that happen outside of the supervisor context and are a bit racey when the root context
// is shutdown. Namely some pkg/db bits, metrics sinks, and p2p logging. This gives them time to shutdown so the
// tests are happy.
zapLogger.Info("Test root context cancelled, waiting for everything to shut down properly...")
time.Sleep(time.Millisecond * 50)
}
type testCaseGuardianConfig struct {
@ -950,7 +956,6 @@ func runGuardianConfigTests(t *testing.T, testCases []testCaseGuardianConfig) {
// Create a sub-context with cancel function that we can pass to G.run.
ctx, ctxCancel := context.WithCancel(ctx)
defer ctxCancel()
logger := supervisor.Logger(ctx)
if err := supervisor.Run(ctx, tc.name, NewGuardianNode(common.GoTest, nil).Run(ctxCancel, tc.opts...)); err != nil {
panic(err)
@ -1161,8 +1166,6 @@ func runConsensusBenchmark(t *testing.B, name string, numGuardians int, numMessa
zapLogger, zapObserver, setupLogsCapture := setupLogsCapture(t)
supervisor.New(rootCtx, zapLogger, func(ctx context.Context) error {
logger := supervisor.Logger(ctx)
// create the Guardian Set
gs := newMockGuardianSet(t, testId, numGuardians)

View File

@ -590,16 +590,19 @@ func Run(
}
if envelope.GetFrom() == h.ID() {
logger.Debug("received message from ourselves, ignoring",
zap.Any("payload", msg.Message))
if logger.Level().Enabled(zapcore.DebugLevel) {
logger.Debug("received message from ourselves, ignoring", zap.Any("payload", msg.Message))
}
p2pMessagesReceived.WithLabelValues("loopback").Inc()
continue
}
logger.Debug("received message",
zap.Any("payload", msg.Message),
zap.Binary("raw", envelope.Data),
zap.String("from", envelope.GetFrom().String()))
if logger.Level().Enabled(zapcore.DebugLevel) {
logger.Debug("received message",
zap.Any("payload", msg.Message),
zap.Binary("raw", envelope.Data),
zap.String("from", envelope.GetFrom().String()))
}
switch m := msg.Message.(type) {
case *gossipv1.GossipMessage_SignedHeartbeat:
@ -659,9 +662,9 @@ func Run(
}
}
} else {
logger.Debug("p2p_node_id_not_in_heartbeat",
zap.Error(err),
zap.Any("payload", heartbeat.NodeName))
if logger.Level().Enabled(zapcore.DebugLevel) {
logger.Debug("p2p_node_id_not_in_heartbeat", zap.Error(err), zap.Any("payload", heartbeat.NodeName))
}
}
}()
}
@ -693,24 +696,26 @@ func Run(
s := m.SignedObservationRequest
gs := gst.Get()
if gs == nil {
logger.Debug("dropping SignedObservationRequest - no guardian set",
zap.Any("value", s),
zap.String("from", envelope.GetFrom().String()))
if logger.Level().Enabled(zapcore.DebugLevel) {
logger.Debug("dropping SignedObservationRequest - no guardian set", zap.Any("value", s), zap.String("from", envelope.GetFrom().String()))
}
break
}
r, err := processSignedObservationRequest(s, gs)
if err != nil {
p2pMessagesReceived.WithLabelValues("invalid_signed_observation_request").Inc()
logger.Debug("invalid signed observation request received",
zap.Error(err),
zap.Any("payload", msg.Message),
zap.Any("value", s),
zap.Binary("raw", envelope.Data),
zap.String("from", envelope.GetFrom().String()))
if logger.Level().Enabled(zapcore.DebugLevel) {
logger.Debug("invalid signed observation request received",
zap.Error(err),
zap.Any("payload", msg.Message),
zap.Any("value", s),
zap.Binary("raw", envelope.Data),
zap.String("from", envelope.GetFrom().String()))
}
} else {
logger.Debug("valid signed observation request received",
zap.Any("value", r),
zap.String("from", envelope.GetFrom().String()))
if logger.Level().Enabled(zapcore.DebugLevel) {
logger.Debug("valid signed observation request received", zap.Any("value", r), zap.String("from", envelope.GetFrom().String()))
}
select {
case obsvReqC <- r:

View File

@ -15,6 +15,7 @@ import (
"github.com/wormhole-foundation/wormhole/sdk/vaa"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var (
@ -86,7 +87,11 @@ func (p *Processor) handleCleanup(ctx context.Context) {
//
// This is a rare case, and we can safely expire the state, since we
// have a quorum VAA.
p.logger.Info("Expiring late VAA", zap.String("digest", hash), zap.Duration("delta", delta))
p.logger.Info("Expiring late VAA",
zap.String("message_id", ourVaa.VAA.MessageID()),
zap.String("digest", hash),
zap.Duration("delta", delta),
)
aggregationStateLate.Inc()
delete(p.state.signatures, hash)
continue
@ -118,14 +123,17 @@ func (p *Processor) handleCleanup(ctx context.Context) {
chain = s.ourObservation.GetEmitterChain()
}
p.logger.Debug("observation considered settled",
zap.String("digest", hash),
zap.Duration("delta", delta),
zap.Int("have_sigs", hasSigs),
zap.Int("required_sigs", wantSigs),
zap.Bool("quorum", quorum),
zap.Stringer("emitter_chain", chain),
)
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("observation considered settled",
zap.String("message_id", s.LoggingID()),
zap.String("digest", hash),
zap.Duration("delta", delta),
zap.Int("have_sigs", hasSigs),
zap.Int("required_sigs", wantSigs),
zap.Bool("quorum", quorum),
zap.Stringer("emitter_chain", chain),
)
}
for _, k := range gs.Keys {
if _, ok := s.signatures[k]; ok {
@ -139,12 +147,23 @@ func (p *Processor) handleCleanup(ctx context.Context) {
// observation that come in. Therefore, keep it for a reasonable amount of time.
// If a very late observation arrives after cleanup, a nil aggregation state will be created
// and then expired after a while (as noted in observation.go, this can be abused by a byzantine guardian).
p.logger.Debug("expiring submitted observation", zap.String("digest", hash), zap.Duration("delta", delta))
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("expiring submitted observation",
zap.String("message_id", s.LoggingID()),
zap.String("digest", hash),
zap.Duration("delta", delta),
)
}
delete(p.state.signatures, hash)
aggregationStateExpiration.Inc()
case !s.submitted && ((s.ourMsg != nil && delta > retryLimitOurs) || (s.ourMsg == nil && delta > retryLimitNotOurs)):
// Clearly, this horse is dead and continued beatings won't bring it closer to quorum.
p.logger.Info("expiring unsubmitted observation after exhausting retries", zap.String("digest", hash), zap.Duration("delta", delta), zap.Bool("weObserved", s.ourMsg != nil))
p.logger.Info("expiring unsubmitted observation after exhausting retries",
zap.String("message_id", s.LoggingID()),
zap.String("digest", hash),
zap.Duration("delta", delta),
zap.Bool("weObserved", s.ourMsg != nil),
)
delete(p.state.signatures, hash)
aggregationStateTimeout.Inc()
case !s.submitted && delta >= FirstRetryMinWait && time.Since(s.nextRetry) >= 0:
@ -157,7 +176,11 @@ func (p *Processor) handleCleanup(ctx context.Context) {
if s.ourMsg != nil {
// Unreliable observations cannot be resubmitted and can be considered failed after 5 minutes
if !s.ourObservation.IsReliable() {
p.logger.Info("expiring unsubmitted unreliable observation", zap.String("digest", hash), zap.Duration("delta", delta))
p.logger.Info("expiring unsubmitted unreliable observation",
zap.String("message_id", s.LoggingID()),
zap.String("digest", hash),
zap.Duration("delta", delta),
)
delete(p.state.signatures, hash)
aggregationStateTimeout.Inc()
break
@ -165,20 +188,35 @@ func (p *Processor) handleCleanup(ctx context.Context) {
// Reobservation requests should not be resubmitted but we will keep waiting for more observations.
if s.ourObservation.IsReobservation() {
p.logger.Debug("not submitting reobservation request for reobservation", zap.String("digest", hash), zap.Duration("delta", delta))
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("not submitting reobservation request for reobservation",
zap.String("message_id", s.LoggingID()),
zap.String("digest", hash),
zap.Duration("delta", delta),
)
}
break
}
// If we have already stored this VAA, there is no reason for us to request reobservation.
alreadyInDB, err := p.signedVaaAlreadyInDB(hash, s)
if err != nil {
p.logger.Error("failed to check if observation is already in DB, requesting reobservation", zap.String("hash", hash), zap.Error(err))
p.logger.Error("failed to check if observation is already in DB, requesting reobservation",
zap.String("message_id", s.LoggingID()),
zap.String("hash", hash),
zap.Error(err))
}
if alreadyInDB {
p.logger.Debug("observation already in DB, not requesting reobservation", zap.String("digest", hash))
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("observation already in DB, not requesting reobservation",
zap.String("message_id", s.LoggingID()),
zap.String("digest", hash),
)
}
} else {
p.logger.Info("resubmitting observation",
zap.String("message_id", s.LoggingID()),
zap.String("digest", hash),
zap.Duration("delta", delta),
zap.String("firstObserved", s.firstObserved.String()),
@ -188,7 +226,7 @@ func (p *Processor) handleCleanup(ctx context.Context) {
TxHash: s.txHash,
}
if err := common.PostObservationRequest(p.obsvReqSendC, req); err != nil {
p.logger.Warn("failed to broadcast re-observation request", zap.Error(err))
p.logger.Warn("failed to broadcast re-observation request", zap.String("message_id", s.LoggingID()), zap.Error(err))
}
p.gossipSendC <- s.ourMsg
s.retryCtr++
@ -202,13 +240,16 @@ func (p *Processor) handleCleanup(ctx context.Context) {
hasSigs := len(s.signatures)
wantSigs := vaa.CalculateQuorum(len(p.gs.Keys))
p.logger.Debug("expiring unsubmitted nil observation",
zap.String("digest", hash),
zap.Duration("delta", delta),
zap.Int("have_sigs", hasSigs),
zap.Int("required_sigs", wantSigs),
zap.Bool("quorum", hasSigs >= wantSigs),
)
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("expiring unsubmitted nil observation",
zap.String("message_id", s.LoggingID()),
zap.String("digest", hash),
zap.Duration("delta", delta),
zap.Int("have_sigs", hasSigs),
zap.Int("required_sigs", wantSigs),
zap.Bool("quorum", hasSigs >= wantSigs),
)
}
delete(p.state.signatures, hash)
aggregationStateUnobserved.Inc()
}
@ -239,7 +280,12 @@ func (p *Processor) signedVaaAlreadyInDB(hash string, s *state) (bool, error) {
vb, err := p.db.GetSignedVAABytes(*vaaID)
if err != nil {
if err == db.ErrVAANotFound {
p.logger.Debug("VAA not in DB", zap.String("digest", hash), zap.String("message_id", s.ourObservation.MessageID()))
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("VAA not in DB",
zap.String("message_id", s.ourObservation.MessageID()),
zap.String("digest", hash),
)
}
return false, nil
} else {
return false, fmt.Errorf(`failed to look up message id "%s" in db: %w`, s.ourObservation.MessageID(), err)
@ -253,7 +299,12 @@ func (p *Processor) signedVaaAlreadyInDB(hash string, s *state) (bool, error) {
oldHash := hex.EncodeToString(v.SigningDigest().Bytes())
if hash != oldHash {
p.logger.Debug("VAA already in DB but hash is different", zap.String("old_hash", oldHash), zap.String("new_hash", hash))
if p.logger.Core().Enabled(zapcore.DebugLevel) {
p.logger.Debug("VAA already in DB but hash is different",
zap.String("message_id", s.ourObservation.MessageID()),
zap.String("old_hash", oldHash),
zap.String("new_hash", hash))
}
return false, fmt.Errorf("hash mismatch in_db: %s, new: %s", oldHash, hash)
}

View File

@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/certusone/wormhole/node/pkg/common"
"github.com/wormhole-foundation/wormhole/sdk/vaa"
@ -39,8 +40,7 @@ var (
func (p *Processor) handleMessage(k *common.MessagePublication) {
if p.gs == nil {
p.logger.Warn("dropping observation since we haven't initialized our guardian set yet",
zap.Stringer("emitter_chain", k.EmitterChain),
zap.Stringer("emitter_address", k.EmitterAddress),
zap.String("message_id", k.MessageIDString()),
zap.Uint32("nonce", k.Nonce),
zap.Stringer("txhash", k.TxHash),
zap.Time("timestamp", k.Timestamp),
@ -48,13 +48,14 @@ func (p *Processor) handleMessage(k *common.MessagePublication) {
return
}
p.logger.Debug("message publication confirmed",
zap.Stringer("emitter_chain", k.EmitterChain),
zap.Stringer("emitter_address", k.EmitterAddress),
zap.Uint32("nonce", k.Nonce),
zap.Stringer("txhash", k.TxHash),
zap.Time("timestamp", k.Timestamp),
)
if p.logger.Core().Enabled(zapcore.DebugLevel) {
p.logger.Debug("message publication confirmed",
zap.String("message_id", k.MessageIDString()),
zap.Uint32("nonce", k.Nonce),
zap.Stringer("txhash", k.TxHash),
zap.Time("timestamp", k.Timestamp),
)
}
messagesObservedTotal.With(prometheus.Labels{
"emitter_chain": k.EmitterChain.String(),
@ -89,21 +90,18 @@ func (p *Processor) handleMessage(k *common.MessagePublication) {
panic(err)
}
p.logger.Debug("observed and signed confirmed message publication",
zap.Stringer("source_chain", k.EmitterChain),
zap.Stringer("txhash", k.TxHash),
zap.String("txhash_b58", base58.Encode(k.TxHash.Bytes())),
zap.String("digest", hex.EncodeToString(digest.Bytes())),
zap.Uint32("nonce", k.Nonce),
zap.Uint64("sequence", k.Sequence),
zap.Stringer("emitter_chain", k.EmitterChain),
zap.Stringer("emitter_address", k.EmitterAddress),
zap.String("emitter_address_b58", base58.Encode(k.EmitterAddress.Bytes())),
zap.Uint8("consistency_level", k.ConsistencyLevel),
zap.String("message_id", v.MessageID()),
zap.String("signature", hex.EncodeToString(s)),
zap.Bool("isReobservation", k.IsReobservation),
)
if p.logger.Core().Enabled(zapcore.DebugLevel) {
p.logger.Debug("observed and signed confirmed message publication",
zap.String("message_id", k.MessageIDString()),
zap.Stringer("txhash", k.TxHash),
zap.String("txhash_b58", base58.Encode(k.TxHash.Bytes())),
zap.String("digest", hex.EncodeToString(digest.Bytes())),
zap.Uint32("nonce", k.Nonce),
zap.Uint8("consistency_level", k.ConsistencyLevel),
zap.String("signature", hex.EncodeToString(s)),
zap.Bool("isReobservation", k.IsReobservation),
)
}
messagesSignedTotal.With(prometheus.Labels{
"emitter_chain": k.EmitterChain.String()}).Add(1)

View File

@ -90,12 +90,12 @@ func (p *Processor) handleObservation(ctx context.Context, obs *node_common.MsgW
if p.logger.Core().Enabled(zapcore.DebugLevel) {
p.logger.Debug("received observation",
zap.String("message_id", m.MessageId),
zap.String("digest", hash),
zap.String("signature", hex.EncodeToString(m.Signature)),
zap.String("addr", hex.EncodeToString(m.Addr)),
zap.String("txhash", hex.EncodeToString(m.TxHash)),
zap.String("txhash_b58", base58.Encode(m.TxHash)),
zap.String("message_id", m.MessageId),
)
}
@ -106,6 +106,7 @@ func (p *Processor) handleObservation(ctx context.Context, obs *node_common.MsgW
pk, err := crypto.Ecrecover(m.Hash, m.Signature)
if err != nil {
p.logger.Warn("failed to verify signature on observation",
zap.String("messageId", m.MessageId),
zap.String("digest", hash),
zap.String("signature", hex.EncodeToString(m.Signature)),
zap.String("addr", hex.EncodeToString(m.Addr)),
@ -120,6 +121,7 @@ func (p *Processor) handleObservation(ctx context.Context, obs *node_common.MsgW
if their_addr != signer_pk {
p.logger.Info("invalid observation - address does not match pubkey",
zap.String("messageId", m.MessageId),
zap.String("digest", hash),
zap.String("signature", hex.EncodeToString(m.Signature)),
zap.String("addr", hex.EncodeToString(m.Addr)),
@ -155,6 +157,7 @@ func (p *Processor) handleObservation(ctx context.Context, obs *node_common.MsgW
// May as well not have received it/been offline - drop it and wait for the guardian set.
if gs == nil {
p.logger.Warn("dropping observations since we haven't initialized our guardian set yet",
zap.String("messageId", m.MessageId),
zap.String("digest", hash),
zap.String("their_addr", their_addr.Hex()),
)
@ -166,12 +169,15 @@ func (p *Processor) handleObservation(ctx context.Context, obs *node_common.MsgW
// who have the outdated guardian set, we'll just wait for the message to be retransmitted eventually.
_, ok := gs.KeyIndex(their_addr)
if !ok {
p.logger.Debug("received observation by unknown guardian - is our guardian set outdated?",
zap.String("digest", hash),
zap.String("their_addr", their_addr.Hex()),
zap.Uint32("index", gs.Index),
//zap.Any("keys", gs.KeysAsHexStrings()),
)
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("received observation by unknown guardian - is our guardian set outdated?",
zap.String("messageId", m.MessageId),
zap.String("digest", hash),
zap.String("their_addr", their_addr.Hex()),
zap.Uint32("index", gs.Index),
//zap.Any("keys", gs.KeysAsHexStrings()),
)
}
observationsFailedTotal.WithLabelValues("unknown_guardian").Inc()
return
}
@ -219,10 +225,12 @@ func (p *Processor) handleObservation(ctx context.Context, obs *node_common.MsgW
// We will later check for quorum again after assembling the VAA for a particular guardian set.
if len(s.signatures) < quorum {
// no quorum yet, we're done here
p.logger.Debug("quorum not yet met",
zap.String("digest", hash),
zap.String("messageId", m.MessageId),
)
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("quorum not yet met",
zap.String("messageId", m.MessageId),
zap.String("digest", hash),
)
}
return
}
@ -232,6 +240,7 @@ func (p *Processor) handleObservation(ctx context.Context, obs *node_common.MsgW
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("aggregation state for observation", // 1.3M out of 3M info messages / hour / guardian
zap.String("messageId", m.MessageId),
zap.String("digest", hash),
zap.Any("set", gs.KeysAsHexStrings()),
zap.Uint32("index", gs.Index),
@ -246,12 +255,20 @@ func (p *Processor) handleObservation(ctx context.Context, obs *node_common.MsgW
// we have reached quorum *with the active guardian set*
s.ourObservation.HandleQuorum(sigsVaaFormat, hash, p)
} else {
p.logger.Debug("quorum not met or already submitted, doing nothing", // 1.2M out of 3M info messages / hour / guardian
zap.String("digest", hash))
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("quorum not met or already submitted, doing nothing", // 1.2M out of 3M info messages / hour / guardian
zap.String("messageId", m.MessageId),
zap.String("digest", hash),
)
}
}
} else {
p.logger.Debug("we have not yet seen this observation - temporarily storing signature", // 175K out of 3M info messages / hour / guardian
zap.String("digest", hash))
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("we have not yet seen this observation - temporarily storing signature", // 175K out of 3M info messages / hour / guardian
zap.String("messageId", m.MessageId),
zap.String("digest", hash),
)
}
}
@ -270,7 +287,7 @@ func (p *Processor) handleInboundSignedVAAWithQuorum(ctx context.Context, m *gos
if p.haveSignedVAA(*db.VaaIDFromVAA(v)) {
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("ignored SignedVAAWithQuorum message for VAA we already stored",
zap.String("vaaID", string(db.VaaIDFromVAA(v).Bytes())),
zap.String("message_id", v.MessageID()),
)
}
return
@ -278,6 +295,7 @@ func (p *Processor) handleInboundSignedVAAWithQuorum(ctx context.Context, m *gos
if p.gs == nil {
p.logger.Warn("dropping SignedVAAWithQuorum message since we haven't initialized our guardian set yet",
zap.String("message_id", v.MessageID()),
zap.String("digest", hex.EncodeToString(v.SigningDigest().Bytes())),
zap.Any("message", m),
)
@ -287,6 +305,7 @@ func (p *Processor) handleInboundSignedVAAWithQuorum(ctx context.Context, m *gos
// Check if guardianSet doesn't have any keys
if len(p.gs.Keys) == 0 {
p.logger.Warn("dropping SignedVAAWithQuorum message since we have a guardian set without keys",
zap.String("message_id", v.MessageID()),
zap.String("digest", hex.EncodeToString(v.SigningDigest().Bytes())),
zap.Any("message", m),
)
@ -294,7 +313,8 @@ func (p *Processor) handleInboundSignedVAAWithQuorum(ctx context.Context, m *gos
}
if err := v.Verify(p.gs.Keys); err != nil {
p.logger.Warn("dropping SignedVAAWithQuorum message because it failed verification: " + err.Error())
// We format the error as part of the message so the tests can check for it.
p.logger.Warn("dropping SignedVAAWithQuorum message because it failed verification: "+err.Error(), zap.String("message_id", v.MessageID()))
return
}
@ -306,14 +326,18 @@ func (p *Processor) handleInboundSignedVAAWithQuorum(ctx context.Context, m *gos
// Store signed VAA in database.
if p.logger.Level().Enabled(zapcore.DebugLevel) {
p.logger.Debug("storing inbound signed VAA with quorum",
zap.String("message_id", v.MessageID()),
zap.String("digest", hex.EncodeToString(v.SigningDigest().Bytes())),
zap.Any("vaa", v),
zap.String("bytes", hex.EncodeToString(m.Vaa)),
zap.String("message_id", v.MessageID()))
)
}
if err := p.storeSignedVAA(v); err != nil {
p.logger.Error("failed to store signed VAA", zap.Error(err))
p.logger.Error("failed to store signed VAA",
zap.String("message_id", v.MessageID()),
zap.Error(err),
)
return
}
}

View File

@ -3,6 +3,7 @@ package processor
import (
"context"
"crypto/ecdsa"
"encoding/hex"
"fmt"
"time"
@ -82,6 +83,16 @@ type (
}
)
// LoggingID can be used to identify a state object in a log message. Note that it should not
// be used to uniquely identify an observation. It is only meant for logging purposes.
func (s *state) LoggingID() string {
if s.ourObservation != nil {
return s.ourObservation.MessageID()
}
return hex.EncodeToString(s.txHash)
}
type PythNetVaaEntry struct {
v *vaa.VAA
updateTime time.Time // Used for determining when to delete entries

View File

@ -28,11 +28,16 @@ func (v *VAA) HandleQuorum(sigs []*vaa.Signature, hash string, p *Processor) {
// Store signed VAA in database.
p.logger.Info("signed VAA with quorum",
zap.String("message_id", signed.MessageID()),
zap.String("digest", hash),
zap.String("message_id", signed.MessageID()))
)
if err := p.storeSignedVAA(signed); err != nil {
p.logger.Error("failed to store signed VAA", zap.Error(err))
p.logger.Error("failed to store signed VAA",
zap.String("message_id", signed.MessageID()),
zap.String("digest", hash),
zap.Error(err),
)
}
p.broadcastSignedVAA(signed)

File diff suppressed because it is too large Load Diff

View File

@ -207,12 +207,12 @@ func ccqBackFillDetermineMaxBatchSize(ctx context.Context, logger *zap.Logger, c
// Save the blocks we just retrieved to be used as our starting cache.
blocks := Blocks{}
for _, result := range results {
if result.err != nil {
return 0, nil, fmt.Errorf("failed to get block: %w", result.err)
for i := range results {
if results[i].err != nil {
return 0, nil, fmt.Errorf("failed to get block: %w", results[i].err)
}
m := &result.result
m := &results[i].result
if m.Number != 0 {
blocks = append(blocks, Block{
@ -262,12 +262,12 @@ func (w *Watcher) ccqBackfillGetBlocks(ctx context.Context, initialBlockNum int6
}
blocks := Blocks{}
for _, result := range results {
if result.err != nil {
for i := range results {
if results[i].err != nil {
return nil, fmt.Errorf("failed to get block: %w", err)
}
m := &result.result
m := &results[i].result
if m.Number != 0 {
blocks = append(blocks, Block{

View File

@ -1,6 +1,8 @@
package evm
import (
"errors"
"github.com/certusone/wormhole/node/pkg/common"
gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
"github.com/certusone/wormhole/node/pkg/query"
@ -20,6 +22,10 @@ type WatcherConfig struct {
L1FinalizerRequired watchers.NetworkID // (optional)
l1Finalizer interfaces.L1Finalizer
CcqBackfillCache bool
// These parameters are currently only used for Linea and should be set via SetLineaParams()
LineaRollUpUrl string
LineaRollUpContract string
}
func (wc *WatcherConfig) GetNetworkID() watchers.NetworkID {
@ -57,5 +63,12 @@ func (wc *WatcherConfig) Create(
watcher := NewEthWatcher(wc.Rpc, eth_common.HexToAddress(wc.Contract), string(wc.NetworkID), wc.ChainID, msgC, setWriteC, obsvReqC, queryReqC, queryResponseC, devMode, wc.CcqBackfillCache)
watcher.SetL1Finalizer(wc.l1Finalizer)
if wc.ChainID == vaa.ChainIDLinea {
if err := watcher.SetLineaParams(wc.LineaRollUpUrl, wc.LineaRollUpContract); err != nil {
return nil, nil, err
}
} else if wc.LineaRollUpUrl != "" || wc.LineaRollUpContract != "" {
return nil, nil, errors.New("LineaRollUpUrl and LineaRollUpContract may only be specified for Linea")
}
return watcher, watcher.Run, nil
}

View File

@ -223,7 +223,7 @@ func (b *BatchPollConnector) getBlocks(ctx context.Context, logger *zap.Logger)
}
var n big.Int
m := &result.result
m := &results[idx].result
if m.Number == nil {
logger.Debug("number is nil, treating as zero", zap.Stringer("finality", finality), zap.String("tag", b.batchData[idx].tag))
} else {
@ -275,14 +275,14 @@ func (b *BatchPollConnector) getBlockRange(ctx context.Context, logger *zap.Logg
}
ret := make(Blocks, numBlocks)
for idx, result := range results {
if result.err != nil {
logger.Error("failed to get block", zap.Int("idx", idx), zap.Stringer("finality", finality), zap.Error(result.err))
for idx := range results {
if results[idx].err != nil {
logger.Error("failed to get block", zap.Int("idx", idx), zap.Stringer("finality", finality), zap.Error(results[idx].err))
return nil, err
}
var n big.Int
m := &result.result
m := &results[idx].result
if m.Number == nil {
logger.Debug("number is nil, treating as zero", zap.Stringer("finality", finality))
} else {

View File

@ -107,7 +107,7 @@ func (e *mockConnectorForBatchPoller) RawBatchCallContext(ctx context.Context, b
return err
}
for _, entry := range b {
for i, entry := range b {
if entry.Method != "eth_getBlockByNumber" {
panic("method not implemented by mockConnectorForBatchPoller")
}
@ -125,7 +125,7 @@ func (e *mockConnectorForBatchPoller) RawBatchCallContext(ctx context.Context, b
e.blockNumbers = e.blockNumbers[1:]
}
str := fmt.Sprintf(`{"author":"0x24c275f0719fdaec6356c4eb9f39ecb9c4d37ce1","baseFeePerGas":"0x3b9aca00","difficulty":"0x0","extraData":"0x","gasLimit":"0xe4e1c0","gasUsed":"0x0","hash":"0xfc8b62a31110121c57cfcccfaf2b147cc2c13b6d01bde4737846cefd29f045cf","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x24c275f0719fdaec6356c4eb9f39ecb9c4d37ce1","nonce":"0x0000000000000000","number":"0x%x","parentHash":"0x09d6d33a658b712f41db7fb9f775f94911ae0132123116aa4f8cf3da9f774e89","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x201","stateRoot":"0x0409ed10e03fd49424ae1489c6fbc6ff1897f45d0e214655ebdb8df94eedc3c0","timestamp":"0x6373ec24","totalDifficulty":"0x0","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]}`, blockNumber)
err = json.Unmarshal([]byte(str), &entry.Result)
err = json.Unmarshal([]byte(str), &b[i].Result)
if entry.Args[0] == "latest" {
e.prevLatest = blockNumber
} else if entry.Args[0] == "safe" {

View File

@ -0,0 +1,218 @@
// A block is considered finalized on Linea when it is marked finalized by the LineaRollup contract on Ethereum.
//
// For a discussion of finality on Linea, see here:
// https://www.notion.so/wormholefoundation/Testnet-Info-V2-633e4aa64a634d56a7ce07a103789774?pvs=4#03513c2eb3654d33aff2206a562d25b1
//
// The LineaRollup proxy contract on ethereum is available at the following addresses:
// Mainnet: 0xd19d4B5d358258f05D7B411E21A1460D11B0876F
// Testnet: 0xB218f8A4Bc926cF1cA7b3423c154a0D627Bdb7E5
//
// To generate the golang abi for the LineaRollup contract:
// - Grab the ABIs from the LineaRollup contract (not the proxy) (0x934Dd4C63E285551CEceF8459103554D0096c179 on Ethereum mainnet) and put it in /tmp/LineaRollup.abi.
// - mkdir node/pkg/watchers/evm/connectors/lineaabi
// - Install abigen: go install github.com/ethereum/go-ethereum/cmd/abigen@latest
// - abigen --abi /tmp/LineaRollup.abi --pkg lineaabi --out node/pkg/watchers/evm/connectors/lineaabi/LineaRollup.go
package connectors
import (
"context"
"fmt"
"time"
"github.com/certusone/wormhole/node/pkg/common"
rollUpAbi "github.com/certusone/wormhole/node/pkg/watchers/evm/connectors/lineaabi"
ethereum "github.com/ethereum/go-ethereum"
ethBind "github.com/ethereum/go-ethereum/accounts/abi/bind"
ethCommon "github.com/ethereum/go-ethereum/common"
ethTypes "github.com/ethereum/go-ethereum/core/types"
ethClient "github.com/ethereum/go-ethereum/ethclient"
ethRpc "github.com/ethereum/go-ethereum/rpc"
"go.uber.org/zap"
)
// LineaConnector listens for new finalized blocks for Linea by reading the roll up contract on Ethereum.
type LineaConnector struct {
Connector
logger *zap.Logger
// These are used for querying the roll up contract.
rollUpRawClient *ethRpc.Client
rollUpClient *ethClient.Client
// These are used to subscribe for new block finalized events from the roll up contract.
rollUpFilterer *rollUpAbi.LineaabiFilterer
rollUpCaller *rollUpAbi.LineaabiCaller
latestBlockNum uint64
latestFinalizedBlockNum uint64
}
// NewLineaConnector creates a new Linea poll connector using the specified roll up contract.
func NewLineaConnector(
ctx context.Context,
logger *zap.Logger,
baseConnector Connector,
rollUpUrl string,
rollUpAddress string,
) (*LineaConnector, error) {
rollUpRawClient, err := ethRpc.DialContext(ctx, rollUpUrl)
if err != nil {
return nil, fmt.Errorf("failed to create roll up raw client for url %s: %w", rollUpUrl, err)
}
rollUpClient := ethClient.NewClient(rollUpRawClient)
addr := ethCommon.HexToAddress(rollUpAddress)
rollUpFilterer, err := rollUpAbi.NewLineaabiFilterer(addr, rollUpClient)
if err != nil {
return nil, fmt.Errorf("failed to create roll up filter for url %s: %w", rollUpUrl, err)
}
rollUpCaller, err := rollUpAbi.NewLineaabiCaller(addr, rollUpClient)
if err != nil {
return nil, fmt.Errorf("failed to create roll up caller for url %s: %w", rollUpUrl, err)
}
logger.Info("Using roll up for Linea", zap.String("rollUpUrl", rollUpUrl), zap.String("rollUpAddress", rollUpAddress))
connector := &LineaConnector{
Connector: baseConnector,
logger: logger,
rollUpRawClient: rollUpRawClient,
rollUpClient: rollUpClient,
rollUpFilterer: rollUpFilterer,
rollUpCaller: rollUpCaller,
}
return connector, nil
}
// SubscribeForBlocks starts polling. It implements the standard connector interface.
func (c *LineaConnector) SubscribeForBlocks(ctx context.Context, errC chan error, sink chan<- *NewBlock) (ethereum.Subscription, error) {
timeout, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel()
// Use the standard geth head sink to get latest blocks.
headSink := make(chan *ethTypes.Header, 2)
headerSubscription, err := c.Connector.Client().SubscribeNewHead(ctx, headSink)
if err != nil {
return nil, fmt.Errorf("failed to subscribe for latest blocks: %w", err)
}
// Subscribe to data finalized events from the roll up contract.
dataFinalizedChan := make(chan *rollUpAbi.LineaabiDataFinalized, 2)
dataFinalizedSub, err := c.rollUpFilterer.WatchDataFinalized(&ethBind.WatchOpts{Context: timeout}, dataFinalizedChan, nil, nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to subscribe for events from roll up contract: %w", err)
}
// Get the current latest block on Linea.
latestBlock, err := GetBlockByFinality(timeout, c.logger, c.Connector, Latest)
if err != nil {
return nil, fmt.Errorf("failed to get current latest block: %w", err)
}
c.latestBlockNum = latestBlock.Number.Uint64()
// Get and publish the current latest finalized block.
opts := &ethBind.CallOpts{Context: timeout}
initialBlock, err := c.rollUpCaller.CurrentL2BlockNumber(opts)
if err != nil {
return nil, fmt.Errorf("failed to get initial block: %w", err)
}
c.latestFinalizedBlockNum = initialBlock.Uint64()
if c.latestFinalizedBlockNum > c.latestBlockNum {
return nil, fmt.Errorf("latest finalized block reported by L1 (%d) is ahead of latest block reported by L2 (%d), L2 node seems to be stuck",
c.latestFinalizedBlockNum, c.latestBlockNum)
}
c.logger.Info("queried initial finalized block", zap.Uint64("initialBlock", c.latestFinalizedBlockNum), zap.Uint64("latestBlock", c.latestBlockNum))
if err = c.postFinalizedAndSafe(ctx, c.latestFinalizedBlockNum, sink); err != nil {
return nil, fmt.Errorf("failed to post initial block: %w", err)
}
common.RunWithScissors(ctx, errC, "linea_block_poller", func(ctx context.Context) error {
for {
select {
case <-ctx.Done():
dataFinalizedSub.Unsubscribe()
return nil
case err := <-dataFinalizedSub.Err():
errC <- fmt.Errorf("finalized data watcher posted an error: %w", err)
dataFinalizedSub.Unsubscribe()
return nil
case evt := <-dataFinalizedChan:
if err := c.processDataFinalizedEvent(ctx, sink, evt); err != nil {
errC <- fmt.Errorf("failed to process block finalized event: %w", err)
dataFinalizedSub.Unsubscribe()
return nil
}
case ev := <-headSink:
if ev == nil {
c.logger.Error("new latest header event is nil")
continue
}
if ev.Number == nil {
c.logger.Error("new latest header block number is nil")
continue
}
c.latestBlockNum = ev.Number.Uint64()
sink <- &NewBlock{
Number: ev.Number,
Time: ev.Time,
Hash: ev.Hash(),
Finality: Latest,
}
}
}
})
return headerSubscription, nil
}
// processDataFinalizedEvent handles a DataFinalized event published by the roll up contract.
func (c *LineaConnector) processDataFinalizedEvent(ctx context.Context, sink chan<- *NewBlock, evt *rollUpAbi.LineaabiDataFinalized) error {
latestFinalizedBlockNum := evt.LastBlockFinalized.Uint64()
// Leaving this log info in for now because these events come very infrequently.
c.logger.Info("processing data finalized event",
zap.Uint64("latestFinalizedBlockNum", latestFinalizedBlockNum),
zap.Uint64("prevFinalizedBlockNum", c.latestFinalizedBlockNum),
)
if latestFinalizedBlockNum > c.latestBlockNum {
return fmt.Errorf("latest finalized block reported by L1 (%d) is ahead of latest block reported by L2 (%d), L2 node seems to be stuck",
latestFinalizedBlockNum, c.latestBlockNum)
}
for blockNum := c.latestFinalizedBlockNum + 1; blockNum <= latestFinalizedBlockNum; blockNum++ {
if err := c.postFinalizedAndSafe(ctx, blockNum, sink); err != nil {
c.latestFinalizedBlockNum = blockNum - 1
return fmt.Errorf("failed to post block %d: %w", blockNum, err)
}
}
c.latestFinalizedBlockNum = latestFinalizedBlockNum
return nil
}
// postFinalizedAndSafe publishes a block as finalized and safe. It takes a block number and looks it up on chain to publish the current values.
func (c *LineaConnector) postFinalizedAndSafe(ctx context.Context, blockNum uint64, sink chan<- *NewBlock) error {
timeout, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel()
block, err := GetBlockByNumberUint64(timeout, c.logger, c.Connector, blockNum, Finalized)
if err != nil {
return fmt.Errorf("failed to get block %d: %w", blockNum, err)
}
// Publish the finalized block.
sink <- block
// Publish same thing for the safe block.
sink <- block.Copy(Safe)
return nil
}

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,7 @@ package evm
import (
"context"
"errors"
"fmt"
"math"
"math/big"
@ -136,6 +137,10 @@ type (
ccqBatchSize int64
ccqBackfillCache bool
ccqLogger *zap.Logger
// These parameters are currently only used for Linea and should be set via SetLineaParams()
lineaRollUpUrl string
lineaRollUpContract string
}
pendingKey struct {
@ -242,6 +247,19 @@ func (w *Watcher) Run(parentCtx context.Context) error {
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
return fmt.Errorf("dialing eth client failed: %w", err)
}
} else if w.chainID == vaa.ChainIDLinea {
baseConnector, err := connectors.NewEthereumBaseConnector(timeout, w.networkName, w.url, w.contract, logger)
if err != nil {
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
return fmt.Errorf("dialing eth client failed: %w", err)
}
w.ethConn, err = connectors.NewLineaConnector(ctx, logger, baseConnector, w.lineaRollUpUrl, w.lineaRollUpContract)
if err != nil {
ethConnectionErrors.WithLabelValues(w.networkName, "dial_error").Inc()
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
return fmt.Errorf("failed to create Linea poller: %w", err)
}
} else {
// Everything else is instant finality.
logger.Info("assuming instant finality")
@ -699,41 +717,61 @@ func fetchCurrentGuardianSet(ctx context.Context, ethConn connectors.Connector)
// getFinality determines if the chain supports "finalized" and "safe". This is hard coded so it requires thought to change something. However, it also reads the RPC
// to make sure the node actually supports the expected values, and returns an error if it doesn't. Note that we do not support using safe mode but not finalized mode.
func (w *Watcher) getFinality(ctx context.Context) (bool, bool, error) {
// TODO: Need to handle finality for Linea before it can be deployed in Mainnet.
finalized := false
safe := false
// Tilt supports polling for both finalized and safe.
if w.unsafeDevMode {
finalized = true
safe = true
// The following chains support polling for both finalized and safe.
} else if w.chainID == vaa.ChainIDAcala ||
w.chainID == vaa.ChainIDArbitrum ||
w.chainID == vaa.ChainIDArbitrumSepolia ||
w.chainID == vaa.ChainIDBase ||
w.chainID == vaa.ChainIDBaseSepolia ||
w.chainID == vaa.ChainIDBlast ||
w.chainID == vaa.ChainIDBSC ||
w.chainID == vaa.ChainIDEthereum ||
w.chainID == vaa.ChainIDHolesky ||
w.chainID == vaa.ChainIDKarura ||
w.chainID == vaa.ChainIDMantle ||
w.chainID == vaa.ChainIDMoonbeam ||
w.chainID == vaa.ChainIDOptimism ||
w.chainID == vaa.ChainIDSepolia ||
w.chainID == vaa.ChainIDHolesky ||
w.chainID == vaa.ChainIDArbitrumSepolia ||
w.chainID == vaa.ChainIDBaseSepolia ||
w.chainID == vaa.ChainIDOptimismSepolia ||
w.chainID == vaa.ChainIDSepolia ||
w.chainID == vaa.ChainIDXLayer {
finalized = true
safe = true
} else if w.chainID == vaa.ChainIDScroll {
// As of 11/10/2023 Scroll supports polling for finalized but not safe.
finalized = true
} else if w.chainID == vaa.ChainIDPolygon ||
w.chainID == vaa.ChainIDPolygonSepolia {
// The following chains have their own specialized finalizers.
} else if w.chainID == vaa.ChainIDCelo ||
w.chainID == vaa.ChainIDLinea {
return false, false, nil
// Polygon now supports polling for finalized but not safe.
// https://forum.polygon.technology/t/optimizing-decentralized-apps-ux-with-milestones-a-significantly-accelerated-finality-solution/13154
} else if w.chainID == vaa.ChainIDPolygon ||
w.chainID == vaa.ChainIDPolygonSepolia {
finalized = true
} else if w.chainID == vaa.ChainIDBerachain {
// Berachain supports instant finality: https://docs.berachain.com/faq/
// As of 11/10/2023 Scroll supports polling for finalized but not safe.
} else if w.chainID == vaa.ChainIDScroll {
finalized = true
// The following chains support instant finality.
} else if w.chainID == vaa.ChainIDAvalanche ||
w.chainID == vaa.ChainIDBerachain || // Berachain supports instant finality: https://docs.berachain.com/faq/
w.chainID == vaa.ChainIDOasis ||
w.chainID == vaa.ChainIDAurora ||
w.chainID == vaa.ChainIDFantom ||
w.chainID == vaa.ChainIDKlaytn {
return false, false, nil
// Anything else is undefined / not supported.
} else {
return false, false, fmt.Errorf("unsupported chain: %s", w.chainID.String())
}
// If finalized / safe should be supported, read the RPC to make sure they actually are.
@ -935,3 +973,22 @@ func (w *Watcher) waitForBlockTime(ctx context.Context, logger *zap.Logger, errC
func msgIdFromLogEvent(chainID vaa.ChainID, ev *ethabi.AbiLogMessagePublished) string {
return fmt.Sprintf("%v/%v/%v", uint16(chainID), PadAddress(ev.Sender), ev.Sequence)
}
// SetLineaParams is used to enable polling on Linea using the roll up contract on Ethereum.
func (w *Watcher) SetLineaParams(lineaRollUpUrl string, lineaRollUpContract string) error {
if w.chainID != vaa.ChainIDLinea {
return errors.New("function only allowed for Linea")
}
if w.unsafeDevMode && lineaRollUpUrl == "" && lineaRollUpContract == "" {
return nil
}
if lineaRollUpUrl == "" {
return fmt.Errorf("lineaRollUpUrl must be set")
}
if lineaRollUpContract == "" {
return fmt.Errorf("lineaRollUpContract must be set")
}
w.lineaRollUpUrl = lineaRollUpUrl
w.lineaRollUpContract = lineaRollUpContract
return nil
}

View File

@ -40,7 +40,7 @@ service NodePrivilegedService {
// ChainGovernorReleasePendingVAA release a VAA from the chain governor pending list, publishing it immediately.
rpc ChainGovernorReleasePendingVAA (ChainGovernorReleasePendingVAARequest) returns (ChainGovernorReleasePendingVAAResponse);
// ChainGovernorResetReleaseTimer resets the release timer for a chain governor pending VAA to the configured maximum.
rpc ChainGovernorResetReleaseTimer (ChainGovernorResetReleaseTimerRequest) returns (ChainGovernorResetReleaseTimerResponse);
@ -51,10 +51,10 @@ service NodePrivilegedService {
rpc SignExistingVAA (SignExistingVAARequest) returns (SignExistingVAAResponse);
// DumpRPCs returns the RPCs being used by the guardian
rpc DumpRPCs (DumpRPCsRequest) returns (DumpRPCsResponse);
rpc DumpRPCs (DumpRPCsRequest) returns (DumpRPCsResponse);
// GetMissingVAAs returns the VAAs from a cloud function that need to be reobserved.
rpc GetAndObserveMissingVAAs (GetAndObserveMissingVAAsRequest) returns (GetAndObserveMissingVAAsResponse);
rpc GetAndObserveMissingVAAs (GetAndObserveMissingVAAsRequest) returns (GetAndObserveMissingVAAsResponse);
}
message InjectGovernanceVAARequest {
@ -85,7 +85,7 @@ message GovernanceMessage {
GuardianSetUpdate guardian_set = 10;
ContractUpgrade contract_upgrade = 11;
// Token bridge, NFT module, and Wormhole Relayer module (for the first two)
// Token bridge, NFT module, and Wormhole Relayer module (for the first two)
BridgeRegisterChain bridge_register_chain = 12;
BridgeUpgradeContract bridge_contract_upgrade = 13;
@ -117,6 +117,10 @@ message GovernanceMessage {
IbcUpdateChannelChain ibc_update_channel_chain = 21;
// Wormhole Relayer module
WormholeRelayerSetDefaultDeliveryProvider wormhole_relayer_set_default_delivery_provider = 22;
// Generic governance
EvmCall evm_call = 28;
SolanaCall solana_call = 29;
}
}
@ -191,7 +195,7 @@ message AccountantModifyBalance {
// ContractUpgrade represents a Wormhole contract update to be submitted to and signed by the node.
message ContractUpgrade {
// ID of the chain where the Wormhole contract should be updated (uint8).
// ID of the chain where the Wormhole contract should be updated (uint16).
uint32 chain_id = 1;
// Hex-encoded address (without leading 0x) address of the new program/contract.
@ -417,3 +421,30 @@ message GetAndObserveMissingVAAsRequest {
message GetAndObserveMissingVAAsResponse {
string response =1;
}
// EvmCall represents a generic EVM call that can be executed by the generalized governance contract.
message EvmCall {
// ID of the chain where the action should be executed (uint16).
uint32 chain_id = 1;
// Address of the governance contract (eth address starting with 0x)
string governance_contract = 2;
// Address of the governed contract (eth address starting with 0x)
string target_contract = 3;
// ABI-encoded calldata to be passed on to the governed contract (hex encoded)
string abi_encoded_call = 4;
}
// SolanaCall represents a generic Solana call that can be executed by the generalized governance contract.
message SolanaCall {
// ID of the chain where the action should be executed (uint16).
uint32 chain_id = 1;
// Address of the governance contract (solana address)
string governance_contract = 2;
// Encoded instruction data to be passed on to the governed contract (hex encoded)
string encoded_instruction = 3;
}

View File

@ -1,5 +1,5 @@
# syntax=docker.io/docker/dockerfile:1.3@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2
FROM docker.io/golang:1.20.10-bullseye@sha256:082569b3303b164cc4a7c88ac59b19b69c1a5d662041ac0dca046ac239632442
FROM docker.io/golang:1.21.9-bullseye@sha256:311468bffa9fa4747a334b94e6ce3681b564126d653675a6adc46698b2b88d35
RUN useradd -u 1000 -U -m -d /home/lint lint
USER 1000

View File

@ -62,7 +62,7 @@ lint(){
# Do the actual linting!
cd "$ROOT"/node
golangci-lint run --skip-dirs pkg/supervisor --timeout=10m --path-prefix=node $GOLANGCI_LINT_ARGS ./...
golangci-lint run --timeout=10m --path-prefix=node $GOLANGCI_LINT_ARGS ./...
cd "${ROOT}/sdk"
golangci-lint run --timeout=10m $GOLANGCI_LINT_ARGS ./...

141
scripts/update-go-version.sh Executable file
View File

@ -0,0 +1,141 @@
#!/bin/bash
# Make updating to a new version of go a bit easier.
#
# Usage:
# scripts/update-go-version.sh 1.21.8
#
# Any actual go package dependency updates should be manually done for
# correctness and safety. Always verify any major dependency updates.
DOCKER=${DOCKER:-docker}
DOCKER_IMAGE_DEBIAN_DISTRO=bullseye
REPO_ROOT_DIR=$(dirname "$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )")
# Update the github actions to use the updated version of go
function update_github_actions() {
local version=$1
local directory=.github/workflows
# Don't cd in and then cd out
(
cd "$directory" || return 1
echo "Updating github actions under $directory"
git grep -l go-version | xargs sed -r -i -e '/go-version/s/:.*$/: "'"${version}"'"/g'
return "${PIPESTATUS[1]}"
)
return $?
}
# Update the documentation on versions of go to use
function update_developer_docs() {
local version=$1
local documents="DEVELOP.md docs/operations.md"
echo "Updating developer docs: $documents"
# shellcheck disable=SC2086
sed -i -e '/golang.org\/dl/s/>= 1\.[0-9]*\.[0-9x]*/>= '"${version}"'/' $documents
return $?
}
# Determine the digest from an image name and tag. This makes builds more
# repeatable as docker tags are mutable and can be changed.
#
# See also: scripts/check-docker-pin.sh
#
function get_docker_image_digest() {
local version="$1"
local image="${2:-docker.io/golang}"
echo "Attempting to pull ${image}:${version} to retrieve the image digest" >&2
# shellcheck disable=SC2155
local digest=$($DOCKER pull "${image}:${version}" | awk '/^Digest:/{print $NF}')
if [[ ${PIPESTATUS[0]} -ne 0 || -z "$digest" ]]; then
echo "WARNING: could not determine digest for ${image}:${version} container image" >&2
return 1
fi
echo "$digest"
}
# Keep go in Dockerfiles for wormhole specific stuff up to date with the latest go
# It is often impossible to update third party Dockerfiles due to the necessity of
# actual code changes to build with newer versions of go or go.mod dependency sad.
function update_our_dockerfiles() {
local version=$1
local image=docker.io/golang
# shellcheck disable=SC2207
local wormhole_dockerfiles=($(git grep -lEi 'FROM.*go(lang)' | grep -Ev '^(wormchain/D|third_party|algorand|terra)'))
# shellcheck disable=SC2155
local digest=$(get_docker_image_digest "$version" "docker.io/golang")
if [[ $? -ne 0 ]] || [[ -z "$digest" ]]; then
echo "WARNING: Problem getting docker image digest" >&2
return 1
fi
for dockerfile in "${wormhole_dockerfiles[@]}"; do
if grep -qEi 'FROM.*go.*alpine' "$dockerfile"; then
echo "WARNING: '$dockerfile' uses alpine and not debian. Please update manually" >&2
continue
fi
# Flag ordering here is important to work correctly on macOS
# with crappy bsd sed and on Linux with more sensible gnu sed.
#
# Also:
# https://xkcd.com/208/
sed -E -i -e '/docker\.io\/golang:/s/(:)[0-9]*\.[0-9]*\.([0-9]|[0-9a-zA-Z-])*(@)sha256:[0-9a-zA-Z-]*( (AS|as)*.*$)?/\1'"$version"'\3'"$digest"'\4/g' "$dockerfile"
# shellcheck disable=SC2181
if [[ $? -ne 0 ]]; then
echo "ERROR: problem updating $dockerfile to ${version}@${digest}" >&2
return 1
fi
if ! grep -q "${image}:${version}@${digest}" "$dockerfile"; then
echo "ERROR: Problem updating $dockerfile to ${version}@${digest}, please manually verify" >&2
return 1
fi
printf "Successfully updated %-38s to %s\n" "$dockerfile" "${image}:${version}@${digest}"
done
}
function update_go_mod() {
local version=$1
(
cd "${REPO_ROOT_DIR}/node" || exit 1
go mod edit -go "$version" -toolchain "go${version}"
# This is mandatory after go mod edit or it refuses to build
go mod tidy
)
return $?
}
function main() {
local version=$1
if [ -z "$version" ]; then
echo -e "ERROR: Missing go version\nUsage:\n\t$0 <GO VERSION>" >&2
exit 1
elif echo "$version" | grep -q ^v; then
echo "ERROR: use explicit semver versions, not a git tag for this script" >&2
exit 1
fi
if ! update_github_actions "$version"; then
echo "ERROR: Problem updating github actions" >&2
exit 1
fi
if ! update_developer_docs "$version"; then
echo "ERROR: Problem updating developer docs" >&2
exit 1
fi
if ! update_our_dockerfiles "${version}-${DOCKER_IMAGE_DEBIAN_DISTRO}"; then
echo "ERROR: Problem updating dockerfiles" >&2
exit 1
fi
if ! update_go_mod "${version}"; then
echo "ERROR: Problem updating dockerfiles" >&2
exit 1
fi
}
main "$@"

View File

@ -37,6 +37,7 @@ export const CHAINS = {
xlayer: 37,
linea: 38,
berachain: 39,
seievm: 40,
wormchain: 3104,
cosmoshub: 4000,
evmos: 4001,
@ -87,6 +88,7 @@ export const EVMChainNames = [
"xlayer",
"linea",
"berachain",
"seievm",
"sepolia",
"arbitrum_sepolia",
"base_sepolia",
@ -336,6 +338,11 @@ const MAINNET = {
token_bridge: undefined,
nft_bridge: undefined,
},
seievm: {
core: undefined,
token_bridge: undefined,
nft_bridge: undefined,
},
wormchain: {
core: "wormhole1ufs3tlq4umljk0qfe8k5ya0x6hpavn897u2cnf9k0en9jr7qarqqaqfk2j",
token_bridge:
@ -622,6 +629,11 @@ const TESTNET = {
token_bridge: "0xa10f2eF61dE1f19f586ab8B6F2EbA89bACE63F7a",
nft_bridge: undefined,
},
seievm: {
core: "0x07782FCe991dAb4DE7a3124032E534A0D059B4d8",
token_bridge: undefined,
nft_bridge: undefined,
},
wormchain: {
core: "wormhole16jzpxp0e8550c9aht6q9svcux30vtyyyyxv5w2l2djjra46580wsazcjwp",
token_bridge:
@ -901,6 +913,11 @@ const DEVNET = {
token_bridge: undefined,
nft_bridge: undefined,
},
seievm: {
core: undefined,
token_bridge: undefined,
nft_bridge: undefined,
},
wormchain: {
core: "wormhole1ghd753shjuwexxywmgs4xz7x2q732vcnkm6h2pyv9s6ah3hylvrqtm7t3h",
token_bridge:
@ -1060,6 +1077,7 @@ export const CHAIN_ID_BLAST = CHAINS["blast"];
export const CHAIN_ID_XLAYER = CHAINS["xlayer"];
export const CHAIN_ID_LINEA = CHAINS["linea"];
export const CHAIN_ID_BERACHAIN = CHAINS["berachain"];
export const CHAIN_ID_SEIEVM = CHAINS["seievm"];
export const CHAIN_ID_WORMCHAIN = CHAINS["wormchain"];
export const CHAIN_ID_GATEWAY = CHAIN_ID_WORMCHAIN;
export const CHAIN_ID_COSMOSHUB = CHAINS["cosmoshub"];

View File

@ -4,8 +4,9 @@ import (
"bytes"
"encoding/binary"
"fmt"
"math"
"github.com/ethereum/go-ethereum/common"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
)
@ -55,6 +56,13 @@ var WormholeRelayerModule = [32]byte{
}
var WormholeRelayerModuleStr = string(WormholeRelayerModule[:])
var GeneralPurposeGovernanceModule = [32]byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x6C,
0x50, 0x75, 0x72, 0x70, 0x6F, 0x73, 0x65, 0x47, 0x6F, 0x76, 0x65, 0x72, 0x6E, 0x61, 0x6E,
0x63, 0x65,
}
var GeneralPurposeGovernanceModuleStr = string(GeneralPurposeGovernanceModule[:])
type GovernanceAction uint8
var (
@ -99,6 +107,10 @@ var (
// Wormhole relayer governance actions
WormholeRelayerSetDefaultDeliveryProvider GovernanceAction = 3
// General purpose governance
GeneralPurposeGovernanceEvmAction GovernanceAction = 1
GeneralPurposeGovernanceSolanaAction GovernanceAction = 2
)
type (
@ -110,7 +122,7 @@ type (
// BodyGuardianSetUpdate is a governance message to set a new guardian set
BodyGuardianSetUpdate struct {
Keys []common.Address
Keys []ethcommon.Address
NewIndex uint32
}
@ -216,6 +228,24 @@ type (
ChainID ChainID
NewDefaultDeliveryProviderAddress Address
}
// BodyGeneralPurposeGovernanceEvm is a general purpose governance message for EVM chains
BodyGeneralPurposeGovernanceEvm struct {
ChainID ChainID
GovernanceContract ethcommon.Address
TargetContract ethcommon.Address
Payload []byte
}
// BodyGeneralPurposeGovernanceSolana is a general purpose governance message for Solana chains
BodyGeneralPurposeGovernanceSolana struct {
ChainID ChainID
GovernanceContract Address
// NOTE: unlike in EVM, no target contract in the schema here, the
// instruction encodes the target contract address (unlike in EVM, where
// an abi encoded calldata doesn't include the target contract address)
Instruction []byte
}
)
func (b BodyContractUpgrade) Serialize() []byte {
@ -402,6 +432,31 @@ func (r BodyWormholeRelayerSetDefaultDeliveryProvider) Serialize() []byte {
return serializeBridgeGovernanceVaa(WormholeRelayerModuleStr, WormholeRelayerSetDefaultDeliveryProvider, r.ChainID, payload.Bytes())
}
func (r BodyGeneralPurposeGovernanceEvm) Serialize() ([]byte, error) {
payload := &bytes.Buffer{}
payload.Write(r.GovernanceContract[:])
payload.Write(r.TargetContract[:])
// write payload len as uint16
if len(r.Payload) > math.MaxUint16 {
return nil, fmt.Errorf("payload too long; expected at most %d bytes", math.MaxUint16)
}
MustWrite(payload, binary.BigEndian, uint16(len(r.Payload)))
payload.Write(r.Payload)
return serializeBridgeGovernanceVaa(GeneralPurposeGovernanceModuleStr, GeneralPurposeGovernanceEvmAction, r.ChainID, payload.Bytes()), nil
}
func (r BodyGeneralPurposeGovernanceSolana) Serialize() []byte {
payload := &bytes.Buffer{}
payload.Write(r.GovernanceContract[:])
// NOTE: unlike in EVM, we don't write the payload length here, because we're using
// a custom instruction encoding (there is no standard encoding like evm ABI
// encoding), generated by an external tool. That tool length-prefixes all
// the relevant dynamic fields.
payload.Write(r.Instruction)
return serializeBridgeGovernanceVaa(GeneralPurposeGovernanceModuleStr, GeneralPurposeGovernanceSolanaAction, r.ChainID, payload.Bytes())
}
func EmptyPayloadVaa(module string, actionId GovernanceAction, chainId ChainID) []byte {
return serializeBridgeGovernanceVaa(module, actionId, chainId, []byte{})
}

View File

@ -207,6 +207,8 @@ func (c ChainID) String() string {
return "linea"
case ChainIDBerachain:
return "berachain"
case ChainIDSeiEVM:
return "seievm"
case ChainIDCosmoshub:
return "cosmoshub"
case ChainIDEvmos:
@ -322,6 +324,8 @@ func ChainIDFromString(s string) (ChainID, error) {
return ChainIDBerachain, nil
case "cosmoshub":
return ChainIDCosmoshub, nil
case "seievm":
return ChainIDSeiEVM, nil
case "evmos":
return ChainIDEvmos, nil
case "kujira":
@ -487,6 +491,8 @@ const (
ChainIDLinea ChainID = 38
// ChainIDBerachain is the ChainID of Berachain
ChainIDBerachain ChainID = 39
// ChainIDSeiEVM is the ChainID of SeiEVM
ChainIDSeiEVM ChainID = 40
//ChainIDWormchain is the ChainID of Wormchain
ChainIDWormchain ChainID = 3104
// ChainIDCosmoshub is the ChainID of Cosmoshub

View File

@ -65,6 +65,7 @@ func TestChainIDFromString(t *testing.T) {
{input: "xlayer", output: ChainIDXLayer},
{input: "linea", output: ChainIDLinea},
{input: "berachain", output: ChainIDBerachain},
{input: "seievm", output: ChainIDSeiEVM},
{input: "wormchain", output: ChainIDWormchain},
{input: "cosmoshub", output: ChainIDCosmoshub},
{input: "evmos", output: ChainIDEvmos},
@ -118,6 +119,7 @@ func TestChainIDFromString(t *testing.T) {
{input: "XLayer", output: ChainIDXLayer},
{input: "Linea", output: ChainIDLinea},
{input: "Berachain", output: ChainIDBerachain},
{input: "SeiEVM", output: ChainIDSeiEVM},
{input: "Wormchain", output: ChainIDWormchain},
{input: "Cosmoshub", output: ChainIDCosmoshub},
{input: "Evmos", output: ChainIDEvmos},
@ -311,6 +313,7 @@ func TestChainId_String(t *testing.T) {
{input: 37, output: "xlayer"},
{input: 38, output: "linea"},
{input: 39, output: "berachain"},
{input: 40, output: "seievm"},
{input: 3104, output: "wormchain"},
{input: 4000, output: "cosmoshub"},
{input: 4001, output: "evmos"},

View File

@ -38,7 +38,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/btcsuite/btcd v0.22.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect
@ -49,8 +49,7 @@ require (
github.com/cosmos/gogoproto v1.4.3 // indirect
github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/cosmos/iavl v0.19.4 // indirect
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
github.com/cosmos/ledger-go v0.9.2 // indirect
github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect
github.com/creachadair/taskgroup v0.3.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
@ -122,7 +121,8 @@ require (
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tendermint/btcd v0.1.1 // indirect
github.com/tendermint/go-amino v0.16.0 // indirect
github.com/zondax/hid v0.9.0 // indirect
github.com/zondax/hid v0.9.2 // indirect
github.com/zondax/ledger-go v0.14.3 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/net v0.2.0 // indirect

View File

@ -332,6 +332,7 @@ github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c=
github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y=
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
@ -579,6 +580,8 @@ github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8=
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw=
github.com/cosmos/ledger-cosmos-go v0.12.4/go.mod h1:fjfVWRf++Xkygt9wzCsjEBdjcf7wiiY35fv3ctT+k4M=
github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI=
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
@ -2118,6 +2121,10 @@ github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPS
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U=
github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw=
github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI=
gitlab.com/bosi/decorder v0.2.1/go.mod h1:6C/nhLSbF6qZbYD8bRmISBwc6vcWdNsiIBkRvjJFrH0=
gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=