From 0f52aa42072197e530408fbf5aeba44c9c8fe7c6 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 14 Dec 2023 14:21:48 +0100 Subject: [PATCH 01/35] bump Go version and sdk-go --- go.mod | 170 ++++++++++++++++++++++++++-- go.sum | 346 ++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 438 insertions(+), 78 deletions(-) diff --git a/go.mod b/go.mod index 31c3c06e..55cc5d46 100644 --- a/go.mod +++ b/go.mod @@ -1,35 +1,183 @@ module github.com/InjectiveLabs/peggo -go 1.16 +go 1.19 require ( github.com/InjectiveLabs/etherman v1.7.0 github.com/InjectiveLabs/metrics v0.0.1 - github.com/InjectiveLabs/sdk-go v1.47.6 + github.com/InjectiveLabs/sdk-go v1.48.16 github.com/avast/retry-go v3.0.0+incompatible - github.com/cometbft/cometbft v0.37.1 - github.com/cosmos/cosmos-sdk v0.47.2 + github.com/cometbft/cometbft v0.37.2 + github.com/cosmos/cosmos-sdk v0.47.3 github.com/ethereum/go-ethereum v1.11.5 github.com/hashicorp/go-multierror v1.1.1 github.com/jawher/mow.cli v1.2.0 - github.com/mattn/go-runewidth v0.0.13 // indirect github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.20.0 github.com/pkg/errors v0.9.1 - github.com/shirou/gopsutil v3.21.6+incompatible // indirect github.com/shopspring/decimal v1.2.0 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 github.com/xlab/closer v0.0.0-20190328110542-03326addb7c2 github.com/xlab/suplog v1.3.1 - golang.org/x/crypto v0.7.0 - google.golang.org/grpc v1.54.0 + golang.org/x/crypto v0.9.0 + google.golang.org/grpc v1.55.0 +) + +require ( + cosmossdk.io/api v0.3.1 // indirect + cosmossdk.io/core v0.5.1 // indirect + cosmossdk.io/depinject v1.0.0-alpha.3 // indirect + cosmossdk.io/errors v1.0.0-beta.7 // indirect + cosmossdk.io/math v1.0.1 // indirect + filippo.io/edwards25519 v1.0.0 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.1 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/CosmWasm/wasmd v0.40.0 // indirect + github.com/CosmWasm/wasmvm v1.2.4 // indirect + github.com/DataDog/datadog-go/v5 v5.1.0 // indirect + github.com/InjectiveLabs/suplog v1.3.3 // indirect + github.com/Microsoft/go-winio v0.6.0 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/alexcesaro/statsd v2.0.0+incompatible // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/aws/aws-sdk-go v1.44.203 // indirect + github.com/bandprotocol/bandchain-packet v0.0.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/btcsuite/btcd v0.23.4 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/btcsuite/btcd/btcutil v1.1.3 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect + github.com/bugsnag/bugsnag-go v2.1.2+incompatible // indirect + github.com/bugsnag/panicwrap v1.3.4 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cometbft/cometbft-db v0.8.0 // indirect + github.com/confio/ics23/go v0.9.0 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogoproto v1.4.10 // indirect + github.com/cosmos/iavl v0.20.0 // indirect + github.com/cosmos/ibc-go/v7 v7.0.1 // indirect + github.com/cosmos/ics23/go v0.10.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/dgraph-io/badger/v2 v2.2007.4 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gofrs/uuid v4.3.0+incompatible // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/glog v1.1.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.1.0 // indirect + github.com/holiman/uint256 v1.2.2 // indirect + github.com/huandu/skiplist v1.2.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/itchyny/gojq v0.12.2 // indirect + github.com/itchyny/timefmt-go v0.1.2 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/karalabe/usb v0.0.2 // indirect + github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect + github.com/klauspost/compress v1.16.3 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/linxGnu/grocksdb v1.7.16 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/nxadm/tail v1.4.8 // indirect + github.com/oklog/ulid v1.3.1 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.15.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/shirou/gopsutil v3.21.6+incompatible // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/cast v1.5.1 // indirect + github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.16.0 // indirect + github.com/subosito/gotenv v1.4.2 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tidwall/btree v1.6.0 // indirect + github.com/tidwall/gjson v1.6.8 // indirect + github.com/tidwall/match v1.0.3 // indirect + github.com/tidwall/pretty v1.0.2 // indirect + github.com/tidwall/sjson v1.1.5 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/zondax/hid v0.9.1 // indirect + github.com/zondax/ledger-go v0.14.1 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect + golang.org/x/mod v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/tools v0.7.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + pgregory.net/rapid v0.5.5 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) replace ( github.com/CosmWasm/wasmd => github.com/InjectiveLabs/wasmd v0.40.0-inj github.com/bandprotocol/bandchain-packet => github.com/InjectiveLabs/bandchain-packet v0.0.4-0.20230327115226-35199d4659d5 github.com/cometbft/cometbft => github.com/InjectiveLabs/cometbft v0.37.1-inj - github.com/cosmos/cosmos-sdk => github.com/InjectiveLabs/cosmos-sdk v0.47.2-inj-2 + github.com/cosmos/cosmos-sdk => github.com/InjectiveLabs/cosmos-sdk v0.47.3-inj-5 github.com/ethereum/go-ethereum => github.com/ethereum/go-ethereum v1.12.0 - ) diff --git a/go.sum b/go.sum index 3e86facd..cd9553b1 100644 --- a/go.sum +++ b/go.sum @@ -51,47 +51,64 @@ cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= +cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= +cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -101,26 +118,34 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= @@ -133,8 +158,8 @@ cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= @@ -142,30 +167,42 @@ cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGB cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= +cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= @@ -173,31 +210,41 @@ cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZx cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= +cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/firestore v1.8.0/go.mod h1:r3KB8cAdRIe8znzoPWLw8S6gpDVd9treohhn8b09424= @@ -206,21 +253,28 @@ cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJ cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= @@ -228,73 +282,99 @@ cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHD cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE= cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= +cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -302,67 +382,88 @@ cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjp cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= +cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= @@ -377,44 +478,59 @@ cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31 cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= +cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= +cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= code.gitea.io/sdk/gitea v0.12.0/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= @@ -434,22 +550,23 @@ cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= +cosmossdk.io/log v1.1.0 h1:v0ogPHYeTzPcBTcPR1A3j1hkei4pZama8kz8LKlCMv0= +cosmossdk.io/log v1.1.0/go.mod h1:6zjroETlcDs+mm62gd8Ig7mZ+N+fVOZS91V17H+M4N4= cosmossdk.io/math v1.0.0-beta.3/go.mod h1:3LYasri3Zna4XpbrTNdKsWmD5fHHkaNAod/mNT9XdE4= cosmossdk.io/math v1.0.0-beta.4/go.mod h1:An0MllWJY6PxibUpnwGk8jOm+a/qIxlKmL5Zyp9NnaM= cosmossdk.io/math v1.0.0-beta.6/go.mod h1:gUVtWwIzfSXqcOT+lBVz2jyjfua8DoBdzRsIyaUAT/8= -cosmossdk.io/math v1.0.0-rc.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= -cosmossdk.io/math v1.0.0/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= -cosmossdk.io/simapp v0.0.0-20230224204036-a6adb0821462/go.mod h1:4Dd3NLoLYoN90kZ0uyHoTHzVVk9+J0v4HhZRBNTAq2c= cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= @@ -532,10 +649,9 @@ github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3 github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= github.com/CloudyKit/jet/v6 v6.1.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= -github.com/CosmWasm/wasmvm v1.2.3 h1:OKYlobwmVGbl0eSn0mXoAAjE5hIuXnQCLPjbNd91sVY= -github.com/CosmWasm/wasmvm v1.2.3/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc= +github.com/CosmWasm/wasmvm v1.2.4 h1:6OfeZuEcEH/9iqwrg2pkeVtDCkMoj9U6PpKtcrCyVrQ= +github.com/CosmWasm/wasmvm v1.2.4/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go/v5 v5.1.0 h1:Zmq3tCk9+Tdq8Du73M71Zo6Dyx+cEo9QkCSCqQlHFaQ= github.com/DataDog/datadog-go/v5 v5.1.0/go.mod h1:KhiYb2Badlv9/rofz+OznKoEF5XKTonWyhx5K83AP8E= @@ -554,18 +670,19 @@ github.com/InjectiveLabs/bandchain-packet v0.0.4-0.20230327115226-35199d4659d5 h github.com/InjectiveLabs/bandchain-packet v0.0.4-0.20230327115226-35199d4659d5/go.mod h1:VoNDHSybdPQ35/3zxNwjewaGpzWHhYyTgV7cJzFglEE= github.com/InjectiveLabs/cometbft v0.37.1-inj h1:mNSorEwP72ovlb2HrYsH3L+uIgNgrUj5rI4DDXhatxk= github.com/InjectiveLabs/cometbft v0.37.1-inj/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= -github.com/InjectiveLabs/cosmos-sdk v0.47.2-inj-2 h1:2uzXsLcQ8Xc2VpmVt4B68xxm1epM8XVd+ur2adFSmyY= -github.com/InjectiveLabs/cosmos-sdk v0.47.2-inj-2/go.mod h1:zYzgI8w8hhotXTSoGbbSOAKfpJTx4wOy4XgbaKhtRtc= +github.com/InjectiveLabs/cosmos-sdk v0.47.3-inj-5 h1:WbNT7o2AbXBqOvmPptAd1nVmx67l1LtXIs4GjR0gvXo= +github.com/InjectiveLabs/cosmos-sdk v0.47.3-inj-5/go.mod h1:c4OfLdAykA9zsj1CqrxBRqXzVz48I++JSvIMPSPcEmk= github.com/InjectiveLabs/etherman v1.7.0 h1:ryYW87fqpnhRP33x+ykDhy6Lx9215Fl5T5LIiA78W88= github.com/InjectiveLabs/etherman v1.7.0/go.mod h1:7unNlA/9UVNZhneEWtNnFWfGDJ5KijkGprkpEF9I1BA= github.com/InjectiveLabs/metrics v0.0.1 h1:MXNj8JWOdIqiGZw83JdUTR+i6hgBrb12HatIUvaly9I= github.com/InjectiveLabs/metrics v0.0.1/go.mod h1:Dmgd60Z0pfi7uOGSUzyqZ00tbMYmZK25u8Sjgk3Ay4A= -github.com/InjectiveLabs/sdk-go v1.47.6 h1:Yc3zHxI5nStnMO3T7Eu+AK8qtsunr4VhmIV2weCwe/s= -github.com/InjectiveLabs/sdk-go v1.47.6/go.mod h1:jiG5d4TKRzhqTnPjlthVP8ijLz3w2q6gejUyGQG7bJE= +github.com/InjectiveLabs/sdk-go v1.48.16 h1:OAraiGNKHk/O1scFIjUh6CtgnjpYDnC/jsqK8OKDuZU= +github.com/InjectiveLabs/sdk-go v1.48.16/go.mod h1:IPc0yp3d0++M7b/c+Frfb3PpFQz8kMF4rb49IXj3Drw= github.com/InjectiveLabs/suplog v1.3.3 h1:ARIR3lWD9BxcrmqTwgcGBt8t7e10gwOqllUAXa/MfxI= github.com/InjectiveLabs/suplog v1.3.3/go.mod h1:+I9WRgUhzmo1V/n7IkW24kFBFB9ZTPAiXXXCogWxmTM= github.com/InjectiveLabs/wasmd v0.40.0-inj h1:HBienMKEZufMHIK8gaqBukzPNmIzj4NQcLL7YbZm7No= github.com/InjectiveLabs/wasmd v0.40.0-inj/go.mod h1:GKEn2k43oSu/WX4hd9tMGZi3ykgfcn01rLa116B/Dhs= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -639,7 +756,10 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= @@ -658,7 +778,6 @@ github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= @@ -667,8 +786,10 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= +github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ= github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs= github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= @@ -761,6 +882,8 @@ github.com/bombsimon/wsl/v2 v2.2.0/go.mod h1:Azh8c3XGEJl9LyX0/sFC+CKMc7Ssgua0g+6 github.com/bombsimon/wsl/v3 v3.0.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= github.com/breml/errchkjson v0.3.0/go.mod h1:9Cogkyv9gcT8HREpzi3TiqBxCqDzo8awa92zSDFcofU= @@ -797,6 +920,7 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/bufbuild/buf v1.7.0/go.mod h1:Go40fMAF46PnPLC7jJgTQhAI95pmC0+VtxFKVC0qLq0= github.com/bufbuild/connect-go v0.2.0/go.mod h1:4efZ2eXFENwd4p7tuLaL9m0qtTsCOzuBvrohvRGevDM= github.com/bufbuild/connect-go v1.0.0/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= @@ -829,7 +953,6 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= -github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -878,6 +1001,7 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 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-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= @@ -907,8 +1031,9 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= +github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= +github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= @@ -1046,6 +1171,7 @@ github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+ github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -1068,16 +1194,16 @@ github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETR github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+RooWXCnOWU= github.com/cosmos/gogoproto v1.4.4/go.mod h1:/yl6/nLwsZcZ2JY3OrqjRqvqCG9InUMcXRfRjQiF9DU= github.com/cosmos/gogoproto v1.4.6/go.mod h1:VS/ASYmPgv6zkPKLjR9EB91lwbLHOzaGCirmKKhncfI= -github.com/cosmos/gogoproto v1.4.8 h1:BrHKc6WFZt8+jRV71vKSQE+JrfF+JAnzrKo2VP7wIZ4= -github.com/cosmos/gogoproto v1.4.8/go.mod h1:hnb0DIEWTv+wdNzNcqus5xCQXq5+CXauq1FJuurRfVY= +github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= +github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/iavl v0.20.0-alpha4/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= github.com/cosmos/ibc-go/v7 v7.0.1 h1:NIBNRWjlOoFvFQu1ZlgwkaSeHO5avf4C1YQiWegt8jw= github.com/cosmos/ibc-go/v7 v7.0.1/go.mod h1:vEaapV6nuLPQlS+g8IKmxMo6auPi0i7HMv1PhViht/E= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab h1:I9ialKTQo7248V827Bba4OuKPmk+FPzmTVHsLXaIJWw= -github.com/cosmos/ics23/go v0.9.1-0.20221207100636-b1abd8678aab/go.mod h1:2CwqasX5dSD7Hbp/9b6lhK6BwoBDCBldx7gPKRukR60= +github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= +github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= 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/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= @@ -1093,7 +1219,6 @@ github.com/crate-crypto/go-ipa v0.0.0-20220523130400-f11357ae11c7/go.mod h1:gFnF github.com/crate-crypto/go-kzg-4844 v0.2.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4= github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk= github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= -github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -1136,7 +1261,6 @@ github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8l github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= -github.com/dgraph-io/badger v1.6.0 h1:DshxFxZWXUcO0xX476VJC07Xsr6ZCBVRHKZ93Oh7Evo= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= @@ -1231,11 +1355,13 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= 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.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= 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.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.2.0/go.mod h1:WI2Nd82DMZAAZI1wV2neKGost9EKjvbpQR9OqE5Qqa8= @@ -1246,11 +1372,8 @@ github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -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-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -1271,6 +1394,7 @@ github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nI github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/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= github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= @@ -1282,7 +1406,6 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= 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= @@ -1297,7 +1420,6 @@ github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYis github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-verkle v0.0.0-20220902153445-097bd83b7732/go.mod h1:o/XfIXWi4/GqbQirfRm5uTbXMG5NpqxkxblnbZ+QM9I= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= @@ -1325,6 +1447,11 @@ github.com/go-critic/go-critic v0.4.3/go.mod h1:j4O3D4RoIwRqlZw5jJpx0BNfXWWbpcJo github.com/go-critic/go-critic v0.6.5/go.mod h1:ezfP/Lh7MA6dBNn4c6ab5ALv3sKnZVLx37tr00uuaOY= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.4.0/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= @@ -1343,6 +1470,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -1378,6 +1507,8 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= @@ -1554,6 +1685,7 @@ github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErV github.com/google/crfs v0.0.0-20191108021818-71d77da419c9/go.mod h1:etGhoOqfwPkooV6aqoX3eBGQOJblqdoc9XvWOeuxpPw= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= 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= @@ -1613,6 +1745,7 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 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.3 h1:FAgZmpLl/SXurPEZyCMPBIiiYeTbqfjlbdnCNTAkbGE= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= @@ -1644,8 +1777,8 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= @@ -1732,12 +1865,10 @@ github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/ github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/api v1.15.3/go.mod h1:/g/qgcoBcEXALCNZgRRisyTW0nY86++L0KbeAMXYCeY= -github.com/hashicorp/consul/api v1.18.0/go.mod h1:owRRGJ9M5xReDC5nfT8FTJrNAPbT4NM6p/k+d03q2v4= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= -github.com/hashicorp/consul/sdk v0.13.0/go.mod h1:0hs/l5fOVhJy/VdcoaNqUSi2AUs95eF5WKtv+EYIQqE= 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= @@ -1748,7 +1879,6 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.7.0/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= @@ -1804,13 +1934,11 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= 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= github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/serf v0.9.8/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c/go.mod h1:fHzc09UnyJyqyW+bFuq864eh+wC7dj65aXmXLRe5to0= github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3/go.mod h1:5PC6ZNPde8bBqU/ewGZig35+UIZtw9Ytxez8/q5ZyFE= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= @@ -1900,6 +2028,7 @@ github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f/go.mod h1:qr2b5 github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= github.com/jhump/protoreflect v1.12.1-0.20220721211354-060cc04fc18b/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= @@ -1945,6 +2074,7 @@ github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0t github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= @@ -1970,6 +2100,7 @@ github.com/kataras/pio v0.0.11/go.mod h1:38hH6SWH6m4DKSYmRhlrCJ5WItwWgCVrTNU62XZ github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -1979,6 +2110,7 @@ github.com/kisielk/errcheck v1.6.2/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkHAIKE/contextcheck v1.1.3/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -2004,6 +2136,7 @@ github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs 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 v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= 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= @@ -2059,12 +2192,15 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= github.com/linxGnu/grocksdb v1.7.10/go.mod h1:0hTf+iA+GOr0jDX4CgIYyJZxqOH9XlBh6KVj8+zmF34= +github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= +github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -2118,8 +2254,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -2133,6 +2269,7 @@ github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lL github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= 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= @@ -2162,6 +2299,8 @@ github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= @@ -2401,23 +2540,27 @@ github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bA github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d h1:htwtWgtQo8YS6JFWWi2DNgY0RwSGJ1ruMoxY6CUUclk= -github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= +github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= @@ -2489,7 +2632,6 @@ github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+ 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.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= -github.com/prometheus/common v0.40.0/go.mod h1:L65ZJPSmfn/UBWLQIHV7dBrKFidB/wPlF1y5TlSt9OE= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -2533,6 +2675,7 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqn github.com/regen-network/gocuke v0.6.2 h1:pHviZ0kKAq2U2hN2q3smKNxct6hS0mGByFMHGnWA97M= github.com/regen-network/gocuke v0.6.2/go.mod h1:zYaqIHZobHyd0xOrHGPQjbhGJsuZ1oElx150u2o1xuk= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/go-dbus v0.0.0-20121104212943-b7232d34b1d5/go.mod h1:+u151txRmLpwxBmpYn9z3d1sdJdjRPQpsXuYeY9jNls= github.com/remyoudompheng/go-liblzma v0.0.0-20190506200333-81bf2d431b96/go.mod h1:90HvCY7+oHHUKkbeMCiHt1WuFR2/hPJ9QrljDG+v6ls= github.com/remyoudompheng/go-misc v0.0.0-20190427085024-2d6ac652a50e/go.mod h1:80FQABjoFzZ2M5uEa6FUaJYEmqU2UOKojlFVak1UAwI= @@ -2551,10 +2694,12 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= -github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= +github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= @@ -2562,6 +2707,8 @@ github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNl github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryancurrah/gomodguard v1.0.4/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0fVb9d5fSEaLhoE= github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUccKSJBU0UMXJFVM= github.com/ryancurrah/gomodguard v1.2.4/go.mod h1:+Kem4VjWwvFpUJRJSwa16s1tBJe+vbv02+naTow2f6M= @@ -2573,7 +2720,6 @@ github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiB github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= github.com/sagikazarmark/crypt v0.8.0/go.mod h1:TmKwZAo97S4Fy4sfMH/HX/cQP5D+ijra2NyLpNNmttY= -github.com/sagikazarmark/crypt v0.9.0/go.mod h1:RnH7sEhxfdnPm1z+XMgSLjWTEIjyK4z2dw6+4vHTMuo= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= @@ -2653,8 +2799,8 @@ github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY52 github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= -github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -2671,8 +2817,9 @@ github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -2691,8 +2838,8 @@ github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= -github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= +github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= @@ -2729,8 +2876,9 @@ github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= @@ -2755,7 +2903,6 @@ github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZ github.com/tdewolff/parse/v2 v2.6.3/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs= github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs= github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= @@ -2903,6 +3050,8 @@ github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= 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/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= 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/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= @@ -2923,21 +3072,17 @@ go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQc go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= -go.etcd.io/etcd/api/v3 v3.5.6/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= -go.etcd.io/etcd/client/pkg/v3 v3.5.6/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= go.etcd.io/etcd/client/v2 v2.305.5/go.mod h1:zQjKllfqfBVyVStbt4FaosoX2iYd8fV/GRy/PbowgP4= -go.etcd.io/etcd/client/v2 v2.305.6/go.mod h1:BHha8XJGe8vCIBfWBpbBLVZ4QjOIlfoouvOwydu63E0= go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c= -go.etcd.io/etcd/client/v3 v3.5.6/go.mod h1:f6GRinRMCsFVv9Ht42EyY7nfsVGwrNO0WEoS2pRKzQk= go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= @@ -3003,6 +3148,7 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= go.opentelemetry.io/proto/otlp v0.12.0/go.mod h1:TsIjwGWIx5VFYv9KGVlOpxoBl5Dy+63SUguV7GGvlSQ= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -3089,8 +3235,9 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4 golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -3099,6 +3246,7 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= @@ -3109,14 +3257,14 @@ golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8H golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/exp v0.0.0-20221019170559-20944726eadf/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230131160201-f062dba9d201/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/exp v0.0.0-20230310171629-522b1b587ee0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= @@ -3124,6 +3272,16 @@ golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91/go.mod h1:AbB0pIl golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -3269,8 +3427,9 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -3306,8 +3465,9 @@ golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= 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= @@ -3431,6 +3591,7 @@ golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210313202042-bd2e13477e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -3517,8 +3678,9 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -3532,8 +3694,9 @@ golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -3609,6 +3772,7 @@ golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -3675,6 +3839,7 @@ golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4X golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -3717,9 +3882,13 @@ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNq gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= @@ -3790,8 +3959,8 @@ google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4q google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.122.0 h1:zDobeejm3E7pEG1mNHvdxvjs5XJoCMzyNH+CmwL94Es= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -3938,19 +4107,28 @@ google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnp google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230202175211-008b39050e57/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 h1:EfLuoKW5WfkgVdDy7dTK8qSbH37AX5mj/MFh+bGPz14= google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= +google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -4006,8 +4184,8 @@ google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsA google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -4027,13 +4205,12 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.2-0.20230208135220-49eaa78c6c9c/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.2-0.20230222093303-bc1253ad3743/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVCwMc= -gopkg.in/alexcesaro/statsd.v2 v2.0.0/go.mod h1:i0ubccKGzBVNBpdGV5MocxyA/XlLUJzA7SLonnE4drU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -4114,6 +4291,7 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw= k8s.io/api v0.0.0-20180904230853-4e7be11eab3f/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= k8s.io/api v0.17.4/go.mod h1:5qxx6vjmwUVG2nHQTKGlLts8Tbok8PzHl4vHtVFuZCA= @@ -4191,11 +4369,45 @@ k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= 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= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= +modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= +modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE= mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= From d96433d9ecd95de0ade4ca7fbe513500d8739ddf Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 14 Dec 2023 15:00:06 +0100 Subject: [PATCH 02/35] use the new sdk-go api --- cmd/peggo/tx.go | 19 +++++++++++-- go.mod | 1 + go.sum | 1 + orchestrator/cosmos/network.go | 49 +++++++++++++++++++++++++--------- orchestrator/orchestrator.go | 4 +-- orchestrator/relayer.go | 14 ++++++++-- 6 files changed, 69 insertions(+), 19 deletions(-) diff --git a/cmd/peggo/tx.go b/cmd/peggo/tx.go index b8f4b643..e960d9e7 100644 --- a/cmd/peggo/tx.go +++ b/cmd/peggo/tx.go @@ -16,7 +16,6 @@ import ( chainclient "github.com/InjectiveLabs/sdk-go/client/chain" "github.com/InjectiveLabs/sdk-go/client/common" - "github.com/InjectiveLabs/peggo/orchestrator/cosmos" ) @@ -147,7 +146,23 @@ func registerEthKeyCmd(cmd *cli.Cmd) { } clientCtx = clientCtx.WithClient(tmRPC) - daemonClient, err := chainclient.NewChainClient(clientCtx, *cosmosGRPC, common.OptionGasPrices(*cosmosGasPrices)) + + var networkName, nodeName string + + switch *cosmosChainID { + case "injective-1": + networkName = "mainnet" + case "injective-777": + networkName = "devnet" + case "injective-888": + networkName = "testnet" + } + + nodeName = "lb" + + netCfg := common.LoadNetwork(networkName, nodeName) + + daemonClient, err := chainclient.NewChainClient(clientCtx, netCfg, common.OptionGasPrices(*cosmosGasPrices)) if err != nil { log.WithError(err).WithFields(log.Fields{ "endpoint": *cosmosGRPC, diff --git a/go.mod b/go.mod index 55cc5d46..54a7d699 100644 --- a/go.mod +++ b/go.mod @@ -92,6 +92,7 @@ require ( github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect diff --git a/go.sum b/go.sum index cd9553b1..890cccac 100644 --- a/go.sum +++ b/go.sum @@ -1847,6 +1847,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqC github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= diff --git a/orchestrator/cosmos/network.go b/orchestrator/cosmos/network.go index cc019a2a..376ab785 100644 --- a/orchestrator/cosmos/network.go +++ b/orchestrator/cosmos/network.go @@ -2,10 +2,9 @@ package cosmos import ( "context" + "strconv" "time" - rpchttp "github.com/cometbft/cometbft/rpc/client/http" - tmctypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/ethereum/go-ethereum/accounts/abi/bind" ethcmn "github.com/ethereum/go-ethereum/common" @@ -14,19 +13,21 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/connectivity" - "github.com/InjectiveLabs/peggo/orchestrator/cosmos/tmclient" "github.com/InjectiveLabs/peggo/orchestrator/ethereum/keystore" peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" "github.com/InjectiveLabs/sdk-go/chain/peggy/types" peggy "github.com/InjectiveLabs/sdk-go/chain/peggy/types" chainclient "github.com/InjectiveLabs/sdk-go/client/chain" "github.com/InjectiveLabs/sdk-go/client/common" + explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer" + explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb" ) type Network struct { - tmclient.TendermintClient + //tmclient.TendermintClient PeggyQueryClient PeggyBroadcastClient + explorerclient.ExplorerClient } func NewNetwork( @@ -44,16 +45,36 @@ func NewNetwork( return nil, errors.Wrapf(err, "failed to create client context for Injective chain") } - clientCtx = clientCtx.WithNodeURI(tendermintRPC) + //clientCtx = clientCtx.WithNodeURI(tendermintRPC) - tmRPC, err := rpchttp.New(tendermintRPC, "/websocket") - if err != nil { - return nil, errors.Wrapf(err, "failed to connect to Tendermint RPC %s", tendermintRPC) + //tmRPC, err := rpchttp.New(tendermintRPC, "/websocket") + //if err != nil { + // return nil, errors.Wrapf(err, "failed to connect to Tendermint RPC %s", tendermintRPC) + //} + + //clientCtx = clientCtx.WithClient(tmRPC) + + var networkName, nodeName string + + switch chainID { + case "injective-1": + networkName = "mainnet" + case "injective-777": + networkName = "devnet" + case "injective-888": + networkName = "testnet" } - clientCtx = clientCtx.WithClient(tmRPC) + nodeName = "lb" + + netCfg := common.LoadNetwork(networkName, nodeName) + + explorer, err := explorerclient.NewExplorerClient(netCfg) + if err != nil { + return nil, err + } - daemonClient, err := chainclient.NewChainClient(clientCtx, injectiveGRPC, common.OptionGasPrices(injectiveGasPrices)) + daemonClient, err := chainclient.NewChainClient(clientCtx, netCfg, common.OptionGasPrices(injectiveGasPrices)) if err != nil { return nil, errors.Wrapf(err, "failed to connect to Injective GRPC %s", injectiveGRPC) } @@ -68,9 +89,10 @@ func NewNetwork( peggyQuerier := types.NewQueryClient(grpcConn) n := &Network{ - TendermintClient: tmclient.NewRPCClient(tendermintRPC), + //TendermintClient: tmclient.NewRPCClient(tendermintRPC), PeggyQueryClient: NewPeggyQueryClient(peggyQuerier), PeggyBroadcastClient: NewPeggyBroadcastClient(peggyQuerier, daemonClient, signerFn, personalSignerFn), + ExplorerClient: explorer, } log.WithFields(log.Fields{ @@ -82,8 +104,9 @@ func NewNetwork( return n, nil } -func (n *Network) GetBlock(ctx context.Context, height int64) (*tmctypes.ResultBlock, error) { - return n.TendermintClient.GetBlock(ctx, height) +func (n *Network) GetBlock(ctx context.Context, height int64) (explorerPB.GetBlockResponse, error) { + return n.ExplorerClient.GetBlock(ctx, strconv.FormatInt(height, 10)) + //return n.TendermintClient.GetBlock(ctx, height) } func (n *Network) PeggyParams(ctx context.Context) (*peggy.Params, error) { diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index bff2bad2..0eeba167 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -2,10 +2,10 @@ package orchestrator import ( "context" + explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb" "math/big" "time" - tmctypes "github.com/cometbft/cometbft/rpc/core/types" eth "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" @@ -23,7 +23,7 @@ type PriceFeed interface { type InjectiveNetwork interface { PeggyParams(ctx context.Context) (*peggytypes.Params, error) - GetBlock(ctx context.Context, height int64) (*tmctypes.ResultBlock, error) + GetBlock(ctx context.Context, height int64) (explorerPB.GetBlockResponse, error) // claims LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index 04c97e64..479b6ae3 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -153,7 +153,12 @@ func (r *relayer) relayValsets( return errors.Wrapf(err, "failed to get block %d from Injective", oldestConfirmedValset.Height) } - if timeElapsed := time.Since(blockResult.Block.Time); timeElapsed <= r.relayValsetOffsetDur { + blockTime, err := time.Parse("2006-01-02 15:04:05.999 -0700 MST", blockResult.Data.Timestamp) + if err != nil { + return errors.Wrap(err, "failed to parse timestamp from block") + } + + if timeElapsed := time.Since(blockTime); timeElapsed <= r.relayValsetOffsetDur { timeRemaining := time.Duration(int64(r.relayBatchOffsetDur) - int64(timeElapsed)) r.log.WithField("time_remaining", timeRemaining.String()).Debugln("valset relay offset duration not expired") return nil @@ -252,7 +257,12 @@ func (r *relayer) relayBatches( return errors.Wrapf(err, "failed to get block %d from Injective", oldestConfirmedBatch.Block) } - if timeElapsed := time.Since(blockResult.Block.Time); timeElapsed <= r.relayValsetOffsetDur { + blockTime, err := time.Parse("2006-01-02 15:04:05.999 -0700 MST", blockResult.Data.Timestamp) + if err != nil { + return errors.Wrap(err, "failed to parse timestamp from block") + } + + if timeElapsed := time.Since(blockTime); timeElapsed <= r.relayValsetOffsetDur { timeRemaining := time.Duration(int64(r.relayBatchOffsetDur) - int64(timeElapsed)) r.log.WithField("time_remaining", timeRemaining.String()).Debugln("batch relay offset duration not expired") return nil From 1c7097fc2206877cffe05d7b98dd60b08b2a30e4 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Wed, 20 Dec 2023 18:37:32 +0100 Subject: [PATCH 03/35] ensure peggo code runs exclusively for known networks --- cmd/peggo/options.go | 2 +- cmd/peggo/tx.go | 6 ++---- orchestrator/cosmos/network.go | 23 ++++++++++++++++------- orchestrator/orchestrator.go | 3 +-- orchestrator/relayer.go | 14 ++------------ 5 files changed, 22 insertions(+), 26 deletions(-) diff --git a/cmd/peggo/options.go b/cmd/peggo/options.go index 60e05e69..271baeca 100644 --- a/cmd/peggo/options.go +++ b/cmd/peggo/options.go @@ -290,7 +290,7 @@ func initConfig(cmd *cli.Cmd) Config { Name: "cosmos-grpc", Desc: "Cosmos GRPC querying endpoint", EnvVar: "PEGGO_COSMOS_GRPC", - Value: "tcp://localhost:9900", + Value: "tcp://localhost:9090", }) cfg.tendermintRPC = cmd.String(cli.StringOpt{ diff --git a/cmd/peggo/tx.go b/cmd/peggo/tx.go index e960d9e7..39c30855 100644 --- a/cmd/peggo/tx.go +++ b/cmd/peggo/tx.go @@ -147,7 +147,7 @@ func registerEthKeyCmd(cmd *cli.Cmd) { clientCtx = clientCtx.WithClient(tmRPC) - var networkName, nodeName string + var networkName string switch *cosmosChainID { case "injective-1": @@ -158,9 +158,7 @@ func registerEthKeyCmd(cmd *cli.Cmd) { networkName = "testnet" } - nodeName = "lb" - - netCfg := common.LoadNetwork(networkName, nodeName) + netCfg := common.LoadNetwork(networkName, "lb") daemonClient, err := chainclient.NewChainClient(clientCtx, netCfg, common.OptionGasPrices(*cosmosGasPrices)) if err != nil { diff --git a/orchestrator/cosmos/network.go b/orchestrator/cosmos/network.go index 376ab785..9ea64978 100644 --- a/orchestrator/cosmos/network.go +++ b/orchestrator/cosmos/network.go @@ -20,7 +20,6 @@ import ( chainclient "github.com/InjectiveLabs/sdk-go/client/chain" "github.com/InjectiveLabs/sdk-go/client/common" explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer" - explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb" ) type Network struct { @@ -54,7 +53,7 @@ func NewNetwork( //clientCtx = clientCtx.WithClient(tmRPC) - var networkName, nodeName string + var networkName string switch chainID { case "injective-1": @@ -63,11 +62,11 @@ func NewNetwork( networkName = "devnet" case "injective-888": networkName = "testnet" + default: + return nil, errors.Errorf("provided chain id %v does not belong to any known Injective network", chainID) } - nodeName = "lb" - - netCfg := common.LoadNetwork(networkName, nodeName) + netCfg := common.LoadNetwork(networkName, "lb") explorer, err := explorerclient.NewExplorerClient(netCfg) if err != nil { @@ -104,8 +103,18 @@ func NewNetwork( return n, nil } -func (n *Network) GetBlock(ctx context.Context, height int64) (explorerPB.GetBlockResponse, error) { - return n.ExplorerClient.GetBlock(ctx, strconv.FormatInt(height, 10)) +func (n *Network) GetBlockCreationTime(ctx context.Context, height int64) (time.Time, error) { + block, err := n.ExplorerClient.GetBlock(ctx, strconv.FormatInt(height, 10)) + if err != nil { + return time.Time{}, err + } + + blockTime, err := time.Parse("2006-01-02 15:04:05.999 -0700 MST", block.Data.Timestamp) + if err != nil { + return time.Time{}, errors.Wrap(err, "failed to parse timestamp from block") + } + + return blockTime, nil //return n.TendermintClient.GetBlock(ctx, height) } diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index 0eeba167..54c4b6ae 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -2,7 +2,6 @@ package orchestrator import ( "context" - explorerPB "github.com/InjectiveLabs/sdk-go/exchange/explorer_rpc/pb" "math/big" "time" @@ -23,7 +22,7 @@ type PriceFeed interface { type InjectiveNetwork interface { PeggyParams(ctx context.Context) (*peggytypes.Params, error) - GetBlock(ctx context.Context, height int64) (explorerPB.GetBlockResponse, error) + GetBlockCreationTime(ctx context.Context, height int64) (time.Time, error) // claims LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index 479b6ae3..c7c06377 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -148,12 +148,7 @@ func (r *relayer) relayValsets( } // Check custom time delay offset - blockResult, err := injective.GetBlock(ctx, int64(oldestConfirmedValset.Height)) - if err != nil { - return errors.Wrapf(err, "failed to get block %d from Injective", oldestConfirmedValset.Height) - } - - blockTime, err := time.Parse("2006-01-02 15:04:05.999 -0700 MST", blockResult.Data.Timestamp) + blockTime, err := injective.GetBlockCreationTime(ctx, int64(oldestConfirmedValset.Height)) if err != nil { return errors.Wrap(err, "failed to parse timestamp from block") } @@ -252,12 +247,7 @@ func (r *relayer) relayBatches( } // Check custom time delay offset - blockResult, err := injective.GetBlock(ctx, int64(oldestConfirmedBatch.Block)) - if err != nil { - return errors.Wrapf(err, "failed to get block %d from Injective", oldestConfirmedBatch.Block) - } - - blockTime, err := time.Parse("2006-01-02 15:04:05.999 -0700 MST", blockResult.Data.Timestamp) + blockTime, err := injective.GetBlockCreationTime(ctx, int64(oldestConfirmedBatch.Block)) if err != nil { return errors.Wrap(err, "failed to parse timestamp from block") } From ee30dddcd3fb5c8b1b6519e26e5b679ac4bc73ff Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 21 Dec 2023 11:47:01 +0100 Subject: [PATCH 04/35] cleanup batch_request.go --- orchestrator/batch_request.go | 257 +++++++++++++++++++++++++--------- orchestrator/orchestrator.go | 2 + 2 files changed, 193 insertions(+), 66 deletions(-) diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index 7537c2f4..d0b9390c 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -2,76 +2,89 @@ package orchestrator import ( "context" + "github.com/InjectiveLabs/peggo/orchestrator/loops" + "github.com/InjectiveLabs/sdk-go/chain/peggy/types" "github.com/avast/retry-go" + cosmtypes "github.com/cosmos/cosmos-sdk/types" eth "github.com/ethereum/go-ethereum/common" "github.com/shopspring/decimal" log "github.com/xlab/suplog" - - "github.com/InjectiveLabs/peggo/orchestrator/loops" - "github.com/InjectiveLabs/sdk-go/chain/peggy/types" - cosmtypes "github.com/cosmos/cosmos-sdk/types" + "time" ) func (s *PeggyOrchestrator) BatchRequesterLoop(ctx context.Context) (err error) { - requester := &batchRequester{ - log: log.WithField("loop", "BatchRequester"), - retries: s.maxAttempts, - minBatchFee: s.minBatchFeeUSD, - erc20ContractMapping: s.erc20ContractMapping, + //requester := &batchRequester{ + // log: log.WithField("loop", "BatchRequester"), + // retries: s.maxAttempts, + // minBatchFee: s.minBatchFeeUSD, + // erc20ContractMapping: s.erc20ContractMapping, + //} + // + //return loops.RunLoop( + // ctx, + // defaultLoopDur, + // func() error { return requester.run(ctx, s.injective, s.pricefeed) }, + //) + + return newBatchRequestLoop(s, defaultLoopDur).Run(ctx, s.injective, s.pricefeed) +} + +type batchRequestLoop struct { + *PeggyOrchestrator + loopDuration time.Duration +} + +func newBatchRequestLoop(o *PeggyOrchestrator, loopDuration time.Duration) batchRequestLoop { + return batchRequestLoop{ + PeggyOrchestrator: o, + loopDuration: loopDuration, } +} - return loops.RunLoop( - ctx, - defaultLoopDur, - func() error { return requester.run(ctx, s.injective, s.pricefeed) }, - ) +func (l batchRequestLoop) Logger() log.Logger { + return l.logger.WithField("loop", "batch_request") } -type batchRequester struct { - log log.Logger - retries uint - minBatchFee float64 - erc20ContractMapping map[eth.Address]string +func (l batchRequestLoop) Run(ctx context.Context, injective InjectiveNetwork, priceFeed PriceFeed) error { + return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective, priceFeed)) } -func (r *batchRequester) run( - ctx context.Context, - injective InjectiveNetwork, - feed PriceFeed, -) error { - r.log.WithField("min_batch_fee", r.minBatchFee).Infoln("scanning Injective for potential batches") +func (l batchRequestLoop) loopFn(ctx context.Context, injective InjectiveNetwork, priceFeed PriceFeed) func() error { + return func() error { + fees, err := l.getUnbatchedTokenFees(ctx, injective) + if err != nil { + // non-fatal, just alert + l.Logger().WithError(err).Warningln("unable to get unbatched fees from Injective") + return nil + } - unbatchedFees, err := r.getUnbatchedFeesByToken(ctx, injective) - if err != nil { - // non-fatal, just alert - r.log.WithError(err).Warningln("unable to get unbatched fees from Injective") - return nil - } + if len(fees) == 0 { + l.Logger().Debugln("no token fees to batch") + return nil + } - if len(unbatchedFees) == 0 { - r.log.Debugln("no outgoing withdrawals or minimum batch fee is not met") - return nil - } + for _, fee := range fees { + l.requestBatch(ctx, injective, priceFeed, fee) - for _, tokenFee := range unbatchedFees { - r.requestBatchCreation(ctx, injective, feed, tokenFee) - } + // todo: in case of multiple tokens, we should sleep in between batch requests (non-continuous nonce) + } - return nil + return nil + } } -func (r *batchRequester) getUnbatchedFeesByToken(ctx context.Context, injective InjectiveNetwork) ([]*types.BatchFees, error) { +func (l batchRequestLoop) getUnbatchedTokenFees(ctx context.Context, injective InjectiveNetwork) ([]*types.BatchFees, error) { var unbatchedFees []*types.BatchFees - retryFn := func() (err error) { + getUnbatchedTokenFeesFn := func() (err error) { unbatchedFees, err = injective.UnbatchedTokenFees(ctx) return err } - if err := retry.Do(retryFn, + if err := retry.Do(getUnbatchedTokenFeesFn, retry.Context(ctx), - retry.Attempts(r.retries), + retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { - log.WithError(err).Errorf("failed to get unbatched fees, will retry (%d)", n) + l.Logger().WithError(err).Errorf("failed to get unbatched token fees, will retry (%d)", n) }), ); err != nil { return nil, err @@ -80,36 +93,36 @@ func (r *batchRequester) getUnbatchedFeesByToken(ctx context.Context, injective return unbatchedFees, nil } -func (r *batchRequester) requestBatchCreation( +func (l batchRequestLoop) requestBatch( ctx context.Context, injective InjectiveNetwork, feed PriceFeed, - batchFee *types.BatchFees, + fee *types.BatchFees, ) { var ( - tokenAddr = eth.HexToAddress(batchFee.Token) - denom = r.tokenDenom(tokenAddr) + tokenAddr = eth.HexToAddress(fee.Token) + denom = l.tokenDenom(tokenAddr) ) - if thresholdMet := r.checkFeeThreshold(feed, tokenAddr, batchFee.TotalFees); !thresholdMet { - r.log.WithFields(log.Fields{ + if thresholdMet := l.checkFeeThreshold(feed, tokenAddr, fee.TotalFees); !thresholdMet { + l.Logger().WithFields(log.Fields{ "denom": denom, "token_contract": tokenAddr.String(), - "total_fees": batchFee.TotalFees.String(), + "total_fees": fee.TotalFees.String(), }).Debugln("skipping underpriced batch") return } - r.log.WithFields(log.Fields{ + l.Logger().WithFields(log.Fields{ "denom": denom, "token_contract": tokenAddr.String(), - }).Infoln("requesting batch creation on Injective") + }).Infoln("requesting batch on Injective") _ = injective.SendRequestBatch(ctx, denom) } -func (r *batchRequester) tokenDenom(tokenAddr eth.Address) string { - if cosmosDenom, ok := r.erc20ContractMapping[tokenAddr]; ok { +func (l batchRequestLoop) tokenDenom(tokenAddr eth.Address) string { + if cosmosDenom, ok := l.erc20ContractMapping[tokenAddr]; ok { return cosmosDenom } @@ -117,12 +130,8 @@ func (r *batchRequester) tokenDenom(tokenAddr eth.Address) string { return types.PeggyDenomString(tokenAddr) } -func (r *batchRequester) checkFeeThreshold( - feed PriceFeed, - tokenAddr eth.Address, - totalFees cosmtypes.Int, -) bool { - if r.minBatchFee == 0 { +func (l batchRequestLoop) checkFeeThreshold(feed PriceFeed, tokenAddr eth.Address, fees cosmtypes.Int) bool { + if l.minBatchFeeUSD == 0 { return true } @@ -131,13 +140,129 @@ func (r *batchRequester) checkFeeThreshold( return false } + minFeeInUSDDec := decimal.NewFromFloat(l.minBatchFeeUSD) tokenPriceInUSDDec := decimal.NewFromFloat(tokenPriceInUSD) - totalFeeInUSDDec := decimal.NewFromBigInt(totalFees.BigInt(), -18).Mul(tokenPriceInUSDDec) - minFeeInUSDDec := decimal.NewFromFloat(r.minBatchFee) + totalFeeInUSDDec := decimal.NewFromBigInt(fees.BigInt(), -18).Mul(tokenPriceInUSDDec) - if totalFeeInUSDDec.GreaterThan(minFeeInUSDDec) { - return true + if totalFeeInUSDDec.LessThan(minFeeInUSDDec) { + return false } - return false + return true } + +// +//type batchRequester struct { +// log log.Logger +// retries uint +// minBatchFee float64 +// erc20ContractMapping map[eth.Address]string +//} +// +//func (r *batchRequester) run( +// ctx context.Context, +// injective InjectiveNetwork, +// feed PriceFeed, +//) error { +// r.log.WithField("min_batch_fee", r.minBatchFee).Infoln("scanning Injective for potential batches") +// +// unbatchedFees, err := r.getUnbatchedFeesByToken(ctx, injective) +// if err != nil { +// // non-fatal, just alert +// r.log.WithError(err).Warningln("unable to get unbatched fees from Injective") +// return nil +// } +// +// if len(unbatchedFees) == 0 { +// r.log.Debugln("no outgoing withdrawals or minimum batch fee is not met") +// return nil +// } +// +// for _, tokenFee := range unbatchedFees { +// r.requestBatchCreation(ctx, injective, feed, tokenFee) +// } +// +// return nil +//} +// +//func (r *batchRequester) getUnbatchedFeesByToken(ctx context.Context, injective InjectiveNetwork) ([]*types.BatchFees, error) { +// var unbatchedFees []*types.BatchFees +// retryFn := func() (err error) { +// unbatchedFees, err = injective.UnbatchedTokenFees(ctx) +// return err +// } +// +// if err := retry.Do(retryFn, +// retry.Context(ctx), +// retry.Attempts(r.retries), +// retry.OnRetry(func(n uint, err error) { +// log.WithError(err).Errorf("failed to get unbatched fees, will retry (%d)", n) +// }), +// ); err != nil { +// return nil, err +// } +// +// return unbatchedFees, nil +//} +// +//func (r *batchRequester) requestBatchCreation( +// ctx context.Context, +// injective InjectiveNetwork, +// feed PriceFeed, +// batchFee *types.BatchFees, +//) { +// var ( +// tokenAddr = eth.HexToAddress(batchFee.Token) +// denom = r.tokenDenom(tokenAddr) +// ) +// +// if thresholdMet := r.checkFeeThreshold(feed, tokenAddr, batchFee.TotalFees); !thresholdMet { +// r.log.WithFields(log.Fields{ +// "denom": denom, +// "token_contract": tokenAddr.String(), +// "total_fees": batchFee.TotalFees.String(), +// }).Debugln("skipping underpriced batch") +// return +// } +// +// r.log.WithFields(log.Fields{ +// "denom": denom, +// "token_contract": tokenAddr.String(), +// }).Infoln("requesting batch creation on Injective") +// +// _ = injective.SendRequestBatch(ctx, denom) +//} +// +//func (r *batchRequester) tokenDenom(tokenAddr eth.Address) string { +// if cosmosDenom, ok := r.erc20ContractMapping[tokenAddr]; ok { +// return cosmosDenom +// } +// +// // peggy denom +// return types.PeggyDenomString(tokenAddr) +//} +// +//func (r *batchRequester) checkFeeThreshold( +// feed PriceFeed, +// tokenAddr eth.Address, +// totalFees cosmtypes.Int, +//) bool { +// if r.minBatchFee == 0 { +// return true +// } +// +// tokenPriceInUSD, err := feed.QueryUSDPrice(tokenAddr) +// if err != nil { +// return false +// } +// +// tokenPriceInUSDDec := decimal.NewFromFloat(tokenPriceInUSD) +// totalFeeInUSDDec := decimal.NewFromBigInt(totalFees.BigInt(), -18).Mul(tokenPriceInUSDDec) +// minFeeInUSDDec := decimal.NewFromFloat(r.minBatchFee) +// +// if totalFeeInUSDDec.GreaterThan(minFeeInUSDDec) { +// return true +// } +// +// return false +//} diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index 54c4b6ae..41e27784 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -89,6 +89,7 @@ type EthereumNetwork interface { const defaultLoopDur = 60 * time.Second type PeggyOrchestrator struct { + logger log.Logger svcTags metrics.Tags injective InjectiveNetwork @@ -118,6 +119,7 @@ func NewPeggyOrchestrator( batchRelayingOffset string, ) (*PeggyOrchestrator, error) { orch := &PeggyOrchestrator{ + logger: log.DefaultLogger, svcTags: metrics.Tags{"svc": "peggy_orchestrator"}, injective: injective, ethereum: ethereum, From 10d88232fbf2d0a38225de59ac3f9b50724e4867 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 21 Dec 2023 13:28:56 +0100 Subject: [PATCH 05/35] clean up oracle.go --- orchestrator/oracle.go | 413 +++++++++++++++++++++++------------ orchestrator/orchestrator.go | 57 +++++ 2 files changed, 327 insertions(+), 143 deletions(-) diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index 9ac8976d..bc83b5ba 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -8,7 +8,6 @@ import ( "github.com/pkg/errors" log "github.com/xlab/suplog" - "github.com/InjectiveLabs/peggo/orchestrator/loops" wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" ) @@ -20,114 +19,54 @@ const ( defaultBlocksToSearch uint64 = 2000 ) -// EthOracleMainLoop is responsible for making sure that Ethereum events are retrieved from the Ethereum blockchain -// and ferried over to Cosmos where they will be used to issue tokens or process batches. -func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { - lastConfirmedEthHeight, err := s.getLastConfirmedEthHeightOnInjective(ctx) - if err != nil { - return err - } - - oracle := ðOracle{ - log: log.WithField("loop", "EthOracle"), - retries: s.maxAttempts, - lastResyncWithInjective: time.Now(), - lastCheckedEthHeight: lastConfirmedEthHeight, - } - - return loops.RunLoop( - ctx, - defaultLoopDur, - func() error { return oracle.run(ctx, s.injective, s.ethereum) }, - ) +type ethOracleLoop struct { + *PeggyOrchestrator + loopDuration time.Duration + lastResyncWithInjective time.Time + lastCheckedEthHeight uint64 } -func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Context) (uint64, error) { - var lastConfirmedEthHeight uint64 - retryFn := func() error { - lastClaimEvent, err := s.injective.LastClaimEvent(ctx) - if err == nil && lastClaimEvent != nil && lastClaimEvent.EthereumEventHeight != 0 { - lastConfirmedEthHeight = lastClaimEvent.EthereumEventHeight - return nil - - } - - log.WithError(err).Warningf("failed to get last claim from Injective. Querying peggy params...") +func (l ethOracleLoop) Logger() log.Logger { + return l.logger.WithField("loop", "EthOracle") +} - peggyParams, err := s.injective.PeggyParams(ctx) +func (l ethOracleLoop) LoopFn(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) func() error { + return func() error { + newHeight, err := l.relayEvents(ctx, injective, ethereum) if err != nil { - log.WithError(err).Fatalln("failed to query peggy module params, is injectived running?") return err } - lastConfirmedEthHeight = peggyParams.BridgeContractStartHeight - return nil - } - - if err := retry.Do(retryFn, - retry.Context(ctx), - retry.Attempts(s.maxAttempts), - retry.OnRetry(func(n uint, err error) { - log.WithError(err).Warningf("failed to get last confirmed Ethereum height on Injective, will retry (%d)", n) - }), - ); err != nil { - log.WithError(err).Errorln("got error, loop exits") - return 0, err - } - - return lastConfirmedEthHeight, nil -} - -type ethOracle struct { - log log.Logger - retries uint - lastResyncWithInjective time.Time - lastCheckedEthHeight uint64 -} - -func (o *ethOracle) run( - ctx context.Context, - injective InjectiveNetwork, - ethereum EthereumNetwork, -) error { - o.log.WithField("last_checked_eth_height", o.lastCheckedEthHeight).Infoln("scanning Ethereum for events") - - // Relays events from Ethereum -> Cosmos - newHeight, err := o.relayEvents(ctx, injective, ethereum) - if err != nil { - return err - } - - o.lastCheckedEthHeight = newHeight - - if time.Since(o.lastResyncWithInjective) >= 48*time.Hour { - /** - Auto re-sync to catch up the nonce. Reasons why event nonce fall behind. - 1. It takes some time for events to be indexed on Ethereum. So if peggo queried events immediately as block produced, there is a chance the event is missed. - we need to re-scan this block to ensure events are not missed due to indexing delay. - 2. if validator was in UnBonding state, the claims broadcasted in last iteration are failed. - 3. if infura call failed while filtering events, the peggo missed to broadcast claim events occured in last iteration. - **/ - if err := o.autoResync(ctx, injective); err != nil { - return err + l.Logger().WithFields(log.Fields{ + "block_start": l.lastCheckedEthHeight, + "block_end": newHeight, + }).Debugln("scanned Ethereum blocks for events") + l.lastCheckedEthHeight = newHeight + + if time.Since(l.lastResyncWithInjective) >= 48*time.Hour { + /** + Auto re-sync to catch up the nonce. Reasons why event nonce fall behind. + 1. It takes some time for events to be indexed on Ethereum. So if peggo queried events immediately as block produced, there is a chance the event is missed. + we need to re-scan this block to ensure events are not missed due to indexing delay. + 2. if validator was in UnBonding state, the claims broadcasted in last iteration are failed. + 3. if infura call failed while filtering events, the peggo missed to broadcast claim events occured in last iteration. + **/ + if err := l.autoResync(ctx, injective); err != nil { + return err + } } - } - return nil + return nil + } } -func (o *ethOracle) relayEvents( - ctx context.Context, - injective InjectiveNetwork, - ethereum EthereumNetwork, -) (uint64, error) { - // Relays events from Ethereum -> Cosmos +func (l ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) (uint64, error) { var ( latestHeight uint64 - currentHeight = o.lastCheckedEthHeight + currentHeight = l.lastCheckedEthHeight ) - retryFn := func() error { + scanEthBlocksAndRelayEventsFn := func() error { latestHeader, err := ethereum.HeaderByNumber(ctx, nil) if err != nil { return errors.Wrap(err, "failed to get latest ethereum header") @@ -136,7 +75,6 @@ func (o *ethOracle) relayEvents( // add delay to ensure minimum confirmations are received and block is finalised latestHeight = latestHeader.Number.Uint64() - ethBlockConfirmationDelay if latestHeight < currentHeight { - println(latestHeight) return nil } @@ -180,45 +118,18 @@ func (o *ethOracle) relayEvents( } legacyDeposits = filterSendToCosmosEventsByNonce(legacyDeposits, lastClaimEvent.EthereumEventNonce) - o.log.WithFields(log.Fields{ - "block_start": currentHeight, - "block_end": latestHeight, - "events": legacyDeposits, - }).Debugln("scanned SendToCosmos events") - deposits = filterSendToInjectiveEventsByNonce(deposits, lastClaimEvent.EthereumEventNonce) - o.log.WithFields(log.Fields{ - "block_start": currentHeight, - "block_end": latestHeight, - "events": deposits, - }).Debugln("scanned SendToInjective events") - withdrawals = filterTransactionBatchExecutedEventsByNonce(withdrawals, lastClaimEvent.EthereumEventNonce) - o.log.WithFields(log.Fields{ - "block_start": currentHeight, - "block_end": latestHeight, - "events": withdrawals, - }).Debugln("scanned TransactionBatchExecuted events") - erc20Deployments = filterERC20DeployedEventsByNonce(erc20Deployments, lastClaimEvent.EthereumEventNonce) - o.log.WithFields(log.Fields{ - "block_start": currentHeight, - "block_end": latestHeight, - "events": erc20Deployments, - }).Debugln("scanned FilterERC20Deployed events") - valsetUpdates = filterValsetUpdateEventsByNonce(valsetUpdates, lastClaimEvent.EthereumEventNonce) - o.log.WithFields(log.Fields{ - "block_start": currentHeight, - "block_end": latestHeight, - "events": valsetUpdates, - }).Debugln("scanned ValsetUpdated events") if len(legacyDeposits) == 0 && len(deposits) == 0 && len(withdrawals) == 0 && len(erc20Deployments) == 0 && len(valsetUpdates) == 0 { + l.Logger().Debugln("no new events on Ethereum") + return nil } @@ -233,35 +144,35 @@ func (o *ethOracle) relayEvents( return errors.Wrap(err, "failed to send event claims to Injective") } - o.log.WithFields(log.Fields{ + l.Logger().WithFields(log.Fields{ "last_claim_event_nonce": lastClaimEvent.EthereumEventNonce, "legacy_deposits": len(legacyDeposits), "deposits": len(deposits), "withdrawals": len(withdrawals), - "erc20Deployments": len(erc20Deployments), - "valsetUpdates": len(valsetUpdates), + "erc2_deployments": len(erc20Deployments), + "valset_updates": len(valsetUpdates), }).Infoln("sent new claims to Injective") return nil } - if err := retry.Do(retryFn, + if err := retry.Do(scanEthBlocksAndRelayEventsFn, retry.Context(ctx), - retry.Attempts(o.retries), + retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { - o.log.WithError(err).Warningf("error during Ethereum event checking, will retry (%d)", n) + l.Logger().WithError(err).Warningf("error during Ethereum event checking, will retry (%d)", n) }), ); err != nil { - o.log.WithError(err).Errorln("got error, loop exits") + l.Logger().WithError(err).Errorln("got error, loop exits") return 0, err } return latestHeight, nil } -func (o *ethOracle) autoResync(ctx context.Context, injective InjectiveNetwork) error { +func (l ethOracleLoop) autoResync(ctx context.Context, injective InjectiveNetwork) error { var latestHeight uint64 - retryFn := func() error { + getLastClaimEventFn := func() error { lastClaimEvent, err := injective.LastClaimEvent(ctx) if err != nil { return err @@ -271,28 +182,244 @@ func (o *ethOracle) autoResync(ctx context.Context, injective InjectiveNetwork) return nil } - if err := retry.Do(retryFn, + if err := retry.Do(getLastClaimEventFn, retry.Context(ctx), - retry.Attempts(o.retries), + retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { - o.log.WithError(err).Warningf("failed to get last confirmed eth height, will retry (%d)", n) + l.Logger().WithError(err).Warningf("failed to get last confirmed eth height, will retry (%d)", n) }), ); err != nil { - o.log.WithError(err).Errorln("got error, loop exits") + l.Logger().WithError(err).Errorln("got error, loop exits") return err } - o.lastCheckedEthHeight = latestHeight - o.lastResyncWithInjective = time.Now() + l.lastCheckedEthHeight = latestHeight + l.lastResyncWithInjective = time.Now() - o.log.WithFields(log.Fields{ - "last_resync": o.lastResyncWithInjective.String(), - "last_confirmed_eth_height": o.lastCheckedEthHeight, - }).Infoln("auto resync") + l.Logger().WithFields(log.Fields{ + "last_resync_time": l.lastResyncWithInjective.String(), + "last_confirmed_eth_height": l.lastCheckedEthHeight, + }).Infoln("auto resync nonce with Injective") return nil } +// +//type ethOracle struct { +// log log.Logger +// retries uint +// lastResyncWithInjective time.Time +// lastCheckedEthHeight uint64 +//} +// +//func (o *ethOracle) run( +// ctx context.Context, +// injective InjectiveNetwork, +// ethereum EthereumNetwork, +//) error { +// o.log.WithField("last_checked_eth_height", o.lastCheckedEthHeight).Infoln("scanning Ethereum for events") +// +// // Relays events from Ethereum -> Cosmos +// newHeight, err := o.relayEvents(ctx, injective, ethereum) +// if err != nil { +// return err +// } +// +// o.lastCheckedEthHeight = newHeight +// +// if time.Since(o.lastResyncWithInjective) >= 48*time.Hour { +// /** +// Auto re-sync to catch up the nonce. Reasons why event nonce fall behind. +// 1. It takes some time for events to be indexed on Ethereum. So if peggo queried events immediately as block produced, there is a chance the event is missed. +// we need to re-scan this block to ensure events are not missed due to indexing delay. +// 2. if validator was in UnBonding state, the claims broadcasted in last iteration are failed. +// 3. if infura call failed while filtering events, the peggo missed to broadcast claim events occured in last iteration. +// **/ +// if err := o.autoResync(ctx, injective); err != nil { +// return err +// } +// } +// +// return nil +//} +// +//func (o *ethOracle) relayEvents( +// ctx context.Context, +// injective InjectiveNetwork, +// ethereum EthereumNetwork, +//) (uint64, error) { +// // Relays events from Ethereum -> Cosmos +// var ( +// latestHeight uint64 +// currentHeight = o.lastCheckedEthHeight +// ) +// +// retryFn := func() error { +// latestHeader, err := ethereum.HeaderByNumber(ctx, nil) +// if err != nil { +// return errors.Wrap(err, "failed to get latest ethereum header") +// } +// +// // add delay to ensure minimum confirmations are received and block is finalised +// latestHeight = latestHeader.Number.Uint64() - ethBlockConfirmationDelay +// if latestHeight < currentHeight { +// println(latestHeight) +// return nil +// } +// +// if latestHeight > currentHeight+defaultBlocksToSearch { +// latestHeight = currentHeight + defaultBlocksToSearch +// } +// +// legacyDeposits, err := ethereum.GetSendToCosmosEvents(currentHeight, latestHeight) +// if err != nil { +// return errors.Wrap(err, "failed to get SendToCosmos events") +// } +// +// deposits, err := ethereum.GetSendToInjectiveEvents(currentHeight, latestHeight) +// if err != nil { +// return errors.Wrap(err, "failed to get SendToInjective events") +// } +// +// withdrawals, err := ethereum.GetTransactionBatchExecutedEvents(currentHeight, latestHeight) +// if err != nil { +// return errors.Wrap(err, "failed to get TransactionBatchExecuted events") +// } +// +// erc20Deployments, err := ethereum.GetPeggyERC20DeployedEvents(currentHeight, latestHeight) +// if err != nil { +// return errors.Wrap(err, "failed to get ERC20Deployed events") +// } +// +// valsetUpdates, err := ethereum.GetValsetUpdatedEvents(currentHeight, latestHeight) +// if err != nil { +// return errors.Wrap(err, "failed to get ValsetUpdated events") +// } +// +// // note that starting block overlaps with our last checked block, because we have to deal with +// // the possibility that the relayer was killed after relaying only one of multiple events in a single +// // block, so we also need this routine so make sure we don't send in the first event in this hypothetical +// // multi event block again. In theory we only send all events for every block and that will pass of fail +// // atomically but lets not take that risk. +// lastClaimEvent, err := injective.LastClaimEvent(ctx) +// if err != nil { +// return errors.New("failed to query last claim event from Injective") +// } +// +// legacyDeposits = filterSendToCosmosEventsByNonce(legacyDeposits, lastClaimEvent.EthereumEventNonce) +// o.log.WithFields(log.Fields{ +// "block_start": currentHeight, +// "block_end": latestHeight, +// "events": legacyDeposits, +// }).Debugln("scanned SendToCosmos events") +// +// deposits = filterSendToInjectiveEventsByNonce(deposits, lastClaimEvent.EthereumEventNonce) +// o.log.WithFields(log.Fields{ +// "block_start": currentHeight, +// "block_end": latestHeight, +// "events": deposits, +// }).Debugln("scanned SendToInjective events") +// +// withdrawals = filterTransactionBatchExecutedEventsByNonce(withdrawals, lastClaimEvent.EthereumEventNonce) +// o.log.WithFields(log.Fields{ +// "block_start": currentHeight, +// "block_end": latestHeight, +// "events": withdrawals, +// }).Debugln("scanned TransactionBatchExecuted events") +// +// erc20Deployments = filterERC20DeployedEventsByNonce(erc20Deployments, lastClaimEvent.EthereumEventNonce) +// o.log.WithFields(log.Fields{ +// "block_start": currentHeight, +// "block_end": latestHeight, +// "events": erc20Deployments, +// }).Debugln("scanned FilterERC20Deployed events") +// +// valsetUpdates = filterValsetUpdateEventsByNonce(valsetUpdates, lastClaimEvent.EthereumEventNonce) +// o.log.WithFields(log.Fields{ +// "block_start": currentHeight, +// "block_end": latestHeight, +// "events": valsetUpdates, +// }).Debugln("scanned ValsetUpdated events") +// +// if len(legacyDeposits) == 0 && +// len(deposits) == 0 && +// len(withdrawals) == 0 && +// len(erc20Deployments) == 0 && +// len(valsetUpdates) == 0 { +// return nil +// } +// +// if err := injective.SendEthereumClaims(ctx, +// lastClaimEvent.EthereumEventNonce, +// legacyDeposits, +// deposits, +// withdrawals, +// erc20Deployments, +// valsetUpdates, +// ); err != nil { +// return errors.Wrap(err, "failed to send event claims to Injective") +// } +// +// o.log.WithFields(log.Fields{ +// "last_claim_event_nonce": lastClaimEvent.EthereumEventNonce, +// "legacy_deposits": len(legacyDeposits), +// "deposits": len(deposits), +// "withdrawals": len(withdrawals), +// "erc20Deployments": len(erc20Deployments), +// "valsetUpdates": len(valsetUpdates), +// }).Infoln("sent new claims to Injective") +// +// return nil +// } +// +// if err := retry.Do(retryFn, +// retry.Context(ctx), +// retry.Attempts(o.retries), +// retry.OnRetry(func(n uint, err error) { +// o.log.WithError(err).Warningf("error during Ethereum event checking, will retry (%d)", n) +// }), +// ); err != nil { +// o.log.WithError(err).Errorln("got error, loop exits") +// return 0, err +// } +// +// return latestHeight, nil +//} +// +//func (o *ethOracle) autoResync(ctx context.Context, injective InjectiveNetwork) error { +// var latestHeight uint64 +// retryFn := func() error { +// lastClaimEvent, err := injective.LastClaimEvent(ctx) +// if err != nil { +// return err +// } +// +// latestHeight = lastClaimEvent.EthereumEventHeight +// return nil +// } +// +// if err := retry.Do(retryFn, +// retry.Context(ctx), +// retry.Attempts(o.retries), +// retry.OnRetry(func(n uint, err error) { +// o.log.WithError(err).Warningf("failed to get last confirmed eth height, will retry (%d)", n) +// }), +// ); err != nil { +// o.log.WithError(err).Errorln("got error, loop exits") +// return err +// } +// +// o.lastCheckedEthHeight = latestHeight +// o.lastResyncWithInjective = time.Now() +// +// o.log.WithFields(log.Fields{ +// "last_resync": o.lastResyncWithInjective.String(), +// "last_confirmed_eth_height": o.lastCheckedEthHeight, +// }).Infoln("auto resync") +// +// return nil +//} + func filterSendToCosmosEventsByNonce( events []*wrappers.PeggySendToCosmosEvent, nonce uint64, diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index 41e27784..215404a7 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -2,6 +2,7 @@ package orchestrator import ( "context" + "github.com/avast/retry-go" "math/big" "time" @@ -202,3 +203,59 @@ func (s *PeggyOrchestrator) startRelayerMode(ctx context.Context) error { return pg.Wait() } + +// EthOracleMainLoop is responsible for making sure that Ethereum events are retrieved from the Ethereum blockchain +// and ferried over to Cosmos where they will be used to issue tokens or process batches. +func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { + lastConfirmedEthHeight, err := s.getLastConfirmedEthHeightOnInjective(ctx) + if err != nil { + return err + } + + s.logger.Infoln("scanning Ethereum events from block", lastConfirmedEthHeight) + + oracle := ethOracleLoop{ + PeggyOrchestrator: s, + loopDuration: defaultLoopDur, + lastCheckedEthHeight: lastConfirmedEthHeight, + lastResyncWithInjective: time.Now(), + } + + return loops.RunLoop(ctx, defaultLoopDur, oracle.LoopFn(ctx, s.injective, s.ethereum)) +} + +func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Context) (uint64, error) { + var lastConfirmedEthHeight uint64 + getLastConfirmedEthHeightFn := func() error { + lastClaimEvent, err := s.injective.LastClaimEvent(ctx) + if err == nil && lastClaimEvent != nil && lastClaimEvent.EthereumEventHeight != 0 { + lastConfirmedEthHeight = lastClaimEvent.EthereumEventHeight + return nil + + } + + s.logger.WithError(err).Warningln("failed to get last claim from Injective. Querying peggy module params...") + + peggyParams, err := s.injective.PeggyParams(ctx) + if err != nil { + s.logger.WithError(err).Fatalln("failed to query peggy module params, is injectived running?") + return err + } + + lastConfirmedEthHeight = peggyParams.BridgeContractStartHeight + return nil + } + + if err := retry.Do(getLastConfirmedEthHeightFn, + retry.Context(ctx), + retry.Attempts(s.maxAttempts), + retry.OnRetry(func(n uint, err error) { + s.logger.WithError(err).Warningf("failed to get last confirmed Ethereum height on Injective, will retry (%d)", n) + }), + ); err != nil { + s.logger.WithError(err).Errorln("got error, loop exits") + return 0, err + } + + return lastConfirmedEthHeight, nil +} From 44314badf9428f877ca4ca5b4ddb7d98d3f6c7d6 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 21 Dec 2023 14:09:06 +0100 Subject: [PATCH 06/35] more cleanup --- orchestrator/batch_request.go | 27 +++---------- orchestrator/oracle.go | 73 ++++++++++++++++++++++++++++++----- orchestrator/orchestrator.go | 57 --------------------------- 3 files changed, 70 insertions(+), 87 deletions(-) diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index d0b9390c..e839b1bf 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -13,20 +13,12 @@ import ( ) func (s *PeggyOrchestrator) BatchRequesterLoop(ctx context.Context) (err error) { - //requester := &batchRequester{ - // log: log.WithField("loop", "BatchRequester"), - // retries: s.maxAttempts, - // minBatchFee: s.minBatchFeeUSD, - // erc20ContractMapping: s.erc20ContractMapping, - //} - // - //return loops.RunLoop( - // ctx, - // defaultLoopDur, - // func() error { return requester.run(ctx, s.injective, s.pricefeed) }, - //) + loop := batchRequestLoop{ + PeggyOrchestrator: s, + loopDuration: defaultLoopDur, + } - return newBatchRequestLoop(s, defaultLoopDur).Run(ctx, s.injective, s.pricefeed) + return loop.Run(ctx, s.injective, s.pricefeed) } type batchRequestLoop struct { @@ -34,15 +26,8 @@ type batchRequestLoop struct { loopDuration time.Duration } -func newBatchRequestLoop(o *PeggyOrchestrator, loopDuration time.Duration) batchRequestLoop { - return batchRequestLoop{ - PeggyOrchestrator: o, - loopDuration: loopDuration, - } -} - func (l batchRequestLoop) Logger() log.Logger { - return l.logger.WithField("loop", "batch_request") + return l.logger.WithField("loop", "BatchRequest") } func (l batchRequestLoop) Run(ctx context.Context, injective InjectiveNetwork, priceFeed PriceFeed) error { diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index bc83b5ba..c4d70371 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -2,6 +2,7 @@ package orchestrator import ( "context" + "github.com/InjectiveLabs/peggo/orchestrator/loops" "time" "github.com/avast/retry-go" @@ -19,6 +20,62 @@ const ( defaultBlocksToSearch uint64 = 2000 ) +// EthOracleMainLoop is responsible for making sure that Ethereum events are retrieved from the Ethereum blockchain +// and ferried over to Cosmos where they will be used to issue tokens or process batches. +func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { + lastConfirmedEthHeight, err := s.getLastConfirmedEthHeightOnInjective(ctx) + if err != nil { + return err + } + + s.logger.Infoln("scanning Ethereum events from block", lastConfirmedEthHeight) + + loop := ethOracleLoop{ + PeggyOrchestrator: s, + loopDuration: defaultLoopDur, + lastCheckedEthHeight: lastConfirmedEthHeight, + lastResyncWithInjective: time.Now(), + } + + return loop.Run(ctx, s.injective, s.ethereum) +} + +func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Context) (uint64, error) { + var lastConfirmedEthHeight uint64 + getLastConfirmedEthHeightFn := func() error { + lastClaimEvent, err := s.injective.LastClaimEvent(ctx) + if err == nil && lastClaimEvent != nil && lastClaimEvent.EthereumEventHeight != 0 { + lastConfirmedEthHeight = lastClaimEvent.EthereumEventHeight + return nil + + } + + s.logger.WithError(err).Warningln("failed to get last claim from Injective. Querying peggy module params...") + + peggyParams, err := s.injective.PeggyParams(ctx) + if err != nil { + s.logger.WithError(err).Fatalln("failed to query peggy module params, is injectived running?") + return err + } + + lastConfirmedEthHeight = peggyParams.BridgeContractStartHeight + return nil + } + + if err := retry.Do(getLastConfirmedEthHeightFn, + retry.Context(ctx), + retry.Attempts(s.maxAttempts), + retry.OnRetry(func(n uint, err error) { + s.logger.WithError(err).Warningf("failed to get last confirmed Ethereum height on Injective, will retry (%d)", n) + }), + ); err != nil { + s.logger.WithError(err).Errorln("got error, loop exits") + return 0, err + } + + return lastConfirmedEthHeight, nil +} + type ethOracleLoop struct { *PeggyOrchestrator loopDuration time.Duration @@ -30,17 +87,18 @@ func (l ethOracleLoop) Logger() log.Logger { return l.logger.WithField("loop", "EthOracle") } -func (l ethOracleLoop) LoopFn(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) func() error { +func (l ethOracleLoop) Run(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { + return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective, ethereum)) +} + +func (l ethOracleLoop) loopFn(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) func() error { return func() error { newHeight, err := l.relayEvents(ctx, injective, ethereum) if err != nil { return err } - l.Logger().WithFields(log.Fields{ - "block_start": l.lastCheckedEthHeight, - "block_end": newHeight, - }).Debugln("scanned Ethereum blocks for events") + l.Logger().WithFields(log.Fields{"block_start": l.lastCheckedEthHeight, "block_end": newHeight}).Debugln("scanned Ethereum blocks for events") l.lastCheckedEthHeight = newHeight if time.Since(l.lastResyncWithInjective) >= 48*time.Hour { @@ -196,10 +254,7 @@ func (l ethOracleLoop) autoResync(ctx context.Context, injective InjectiveNetwor l.lastCheckedEthHeight = latestHeight l.lastResyncWithInjective = time.Now() - l.Logger().WithFields(log.Fields{ - "last_resync_time": l.lastResyncWithInjective.String(), - "last_confirmed_eth_height": l.lastCheckedEthHeight, - }).Infoln("auto resync nonce with Injective") + l.Logger().WithFields(log.Fields{"last_resync_time": l.lastResyncWithInjective.String(), "last_confirmed_eth_height": l.lastCheckedEthHeight}).Infoln("auto resync nonce with Injective") return nil } diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index 215404a7..41e27784 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -2,7 +2,6 @@ package orchestrator import ( "context" - "github.com/avast/retry-go" "math/big" "time" @@ -203,59 +202,3 @@ func (s *PeggyOrchestrator) startRelayerMode(ctx context.Context) error { return pg.Wait() } - -// EthOracleMainLoop is responsible for making sure that Ethereum events are retrieved from the Ethereum blockchain -// and ferried over to Cosmos where they will be used to issue tokens or process batches. -func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { - lastConfirmedEthHeight, err := s.getLastConfirmedEthHeightOnInjective(ctx) - if err != nil { - return err - } - - s.logger.Infoln("scanning Ethereum events from block", lastConfirmedEthHeight) - - oracle := ethOracleLoop{ - PeggyOrchestrator: s, - loopDuration: defaultLoopDur, - lastCheckedEthHeight: lastConfirmedEthHeight, - lastResyncWithInjective: time.Now(), - } - - return loops.RunLoop(ctx, defaultLoopDur, oracle.LoopFn(ctx, s.injective, s.ethereum)) -} - -func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Context) (uint64, error) { - var lastConfirmedEthHeight uint64 - getLastConfirmedEthHeightFn := func() error { - lastClaimEvent, err := s.injective.LastClaimEvent(ctx) - if err == nil && lastClaimEvent != nil && lastClaimEvent.EthereumEventHeight != 0 { - lastConfirmedEthHeight = lastClaimEvent.EthereumEventHeight - return nil - - } - - s.logger.WithError(err).Warningln("failed to get last claim from Injective. Querying peggy module params...") - - peggyParams, err := s.injective.PeggyParams(ctx) - if err != nil { - s.logger.WithError(err).Fatalln("failed to query peggy module params, is injectived running?") - return err - } - - lastConfirmedEthHeight = peggyParams.BridgeContractStartHeight - return nil - } - - if err := retry.Do(getLastConfirmedEthHeightFn, - retry.Context(ctx), - retry.Attempts(s.maxAttempts), - retry.OnRetry(func(n uint, err error) { - s.logger.WithError(err).Warningf("failed to get last confirmed Ethereum height on Injective, will retry (%d)", n) - }), - ); err != nil { - s.logger.WithError(err).Errorln("got error, loop exits") - return 0, err - } - - return lastConfirmedEthHeight, nil -} From ce9d707c03e79a16825b3db6185c6f3a028e2701 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 21 Dec 2023 14:29:06 +0100 Subject: [PATCH 07/35] use pointer receivers --- orchestrator/batch_request.go | 14 +++++++------- orchestrator/oracle.go | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index e839b1bf..cdcbe763 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -26,15 +26,15 @@ type batchRequestLoop struct { loopDuration time.Duration } -func (l batchRequestLoop) Logger() log.Logger { +func (l *batchRequestLoop) Logger() log.Logger { return l.logger.WithField("loop", "BatchRequest") } -func (l batchRequestLoop) Run(ctx context.Context, injective InjectiveNetwork, priceFeed PriceFeed) error { +func (l *batchRequestLoop) Run(ctx context.Context, injective InjectiveNetwork, priceFeed PriceFeed) error { return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective, priceFeed)) } -func (l batchRequestLoop) loopFn(ctx context.Context, injective InjectiveNetwork, priceFeed PriceFeed) func() error { +func (l *batchRequestLoop) loopFn(ctx context.Context, injective InjectiveNetwork, priceFeed PriceFeed) func() error { return func() error { fees, err := l.getUnbatchedTokenFees(ctx, injective) if err != nil { @@ -58,7 +58,7 @@ func (l batchRequestLoop) loopFn(ctx context.Context, injective InjectiveNetwork } } -func (l batchRequestLoop) getUnbatchedTokenFees(ctx context.Context, injective InjectiveNetwork) ([]*types.BatchFees, error) { +func (l *batchRequestLoop) getUnbatchedTokenFees(ctx context.Context, injective InjectiveNetwork) ([]*types.BatchFees, error) { var unbatchedFees []*types.BatchFees getUnbatchedTokenFeesFn := func() (err error) { unbatchedFees, err = injective.UnbatchedTokenFees(ctx) @@ -78,7 +78,7 @@ func (l batchRequestLoop) getUnbatchedTokenFees(ctx context.Context, injective I return unbatchedFees, nil } -func (l batchRequestLoop) requestBatch( +func (l *batchRequestLoop) requestBatch( ctx context.Context, injective InjectiveNetwork, feed PriceFeed, @@ -106,7 +106,7 @@ func (l batchRequestLoop) requestBatch( _ = injective.SendRequestBatch(ctx, denom) } -func (l batchRequestLoop) tokenDenom(tokenAddr eth.Address) string { +func (l *batchRequestLoop) tokenDenom(tokenAddr eth.Address) string { if cosmosDenom, ok := l.erc20ContractMapping[tokenAddr]; ok { return cosmosDenom } @@ -115,7 +115,7 @@ func (l batchRequestLoop) tokenDenom(tokenAddr eth.Address) string { return types.PeggyDenomString(tokenAddr) } -func (l batchRequestLoop) checkFeeThreshold(feed PriceFeed, tokenAddr eth.Address, fees cosmtypes.Int) bool { +func (l *batchRequestLoop) checkFeeThreshold(feed PriceFeed, tokenAddr eth.Address, fees cosmtypes.Int) bool { if l.minBatchFeeUSD == 0 { return true } diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index c4d70371..69c786e7 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -83,15 +83,15 @@ type ethOracleLoop struct { lastCheckedEthHeight uint64 } -func (l ethOracleLoop) Logger() log.Logger { +func (l *ethOracleLoop) Logger() log.Logger { return l.logger.WithField("loop", "EthOracle") } -func (l ethOracleLoop) Run(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { +func (l *ethOracleLoop) Run(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective, ethereum)) } -func (l ethOracleLoop) loopFn(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) func() error { +func (l *ethOracleLoop) loopFn(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) func() error { return func() error { newHeight, err := l.relayEvents(ctx, injective, ethereum) if err != nil { @@ -118,7 +118,7 @@ func (l ethOracleLoop) loopFn(ctx context.Context, injective InjectiveNetwork, e } } -func (l ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) (uint64, error) { +func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) (uint64, error) { var ( latestHeight uint64 currentHeight = l.lastCheckedEthHeight @@ -228,7 +228,7 @@ func (l ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetwo return latestHeight, nil } -func (l ethOracleLoop) autoResync(ctx context.Context, injective InjectiveNetwork) error { +func (l *ethOracleLoop) autoResync(ctx context.Context, injective InjectiveNetwork) error { var latestHeight uint64 getLastClaimEventFn := func() error { lastClaimEvent, err := injective.LastClaimEvent(ctx) From 6a77996b50c9a2255f28d1fdd9fb0ba359f272aa Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 21 Dec 2023 15:30:46 +0100 Subject: [PATCH 08/35] clean up signer.go --- orchestrator/signer.go | 329 ++++++++++++++++++++++++++++++----------- 1 file changed, 246 insertions(+), 83 deletions(-) diff --git a/orchestrator/signer.go b/orchestrator/signer.go index a2d376b2..c8e13fc9 100644 --- a/orchestrator/signer.go +++ b/orchestrator/signer.go @@ -2,6 +2,8 @@ package orchestrator import ( "context" + "github.com/pkg/errors" + "time" "github.com/avast/retry-go" "github.com/ethereum/go-ethereum/common" @@ -21,32 +23,28 @@ func (s *PeggyOrchestrator) EthSignerMainLoop(ctx context.Context) error { return err } - signer := ðSigner{ - log: log.WithField("loop", "EthSigner"), - peggyID: peggyID, - ethFrom: s.ethereum.FromAddress(), - retries: s.maxAttempts, + loop := ethSignerLoop{ + PeggyOrchestrator: s, + loopDuration: defaultLoopDur, + peggyID: peggyID, + ethFrom: s.ethereum.FromAddress(), } - return loops.RunLoop( - ctx, - defaultLoopDur, - func() error { return signer.run(ctx, s.injective) }, - ) + return loop.Run(ctx, s.injective) } func (s *PeggyOrchestrator) getPeggyID(ctx context.Context) (common.Hash, error) { var peggyID common.Hash - retryFn := func() (err error) { + getPeggyIDFn := func() (err error) { peggyID, err = s.ethereum.GetPeggyID(ctx) return err } - if err := retry.Do(retryFn, + if err := retry.Do(getPeggyIDFn, retry.Context(ctx), retry.Attempts(s.maxAttempts), retry.OnRetry(func(n uint, err error) { - log.WithError(err).Warningf("failed to get peggy ID from Ethereum contract, will retry (%d)", n) + log.WithError(err).Warningf("failed to get Peggy ID from Ethereum contract, will retry (%d)", n) }), ); err != nil { log.WithError(err).Errorln("got error, loop exits") @@ -58,51 +56,81 @@ func (s *PeggyOrchestrator) getPeggyID(ctx context.Context) (common.Hash, error) return peggyID, nil } -type ethSigner struct { - log log.Logger - peggyID common.Hash - ethFrom common.Address - retries uint +type ethSignerLoop struct { + *PeggyOrchestrator + loopDuration time.Duration + peggyID common.Hash + ethFrom common.Address +} + +func (l *ethSignerLoop) Logger() log.Logger { + return l.logger.WithField("loop", "EthSigner") } -func (s *ethSigner) run(ctx context.Context, injective InjectiveNetwork) error { - s.log.Infoln("scanning Injective for unconfirmed batches and valset updates") +func (l *ethSignerLoop) Run(ctx context.Context, injective InjectiveNetwork) error { + return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective)) +} - if err := s.signNewValsetUpdates(ctx, injective); err != nil { - return err +func (l *ethSignerLoop) loopFn(ctx context.Context, injective InjectiveNetwork) func() error { + return func() error { + if err := l.signNewValsetUpdates(ctx, injective); err != nil { + return err + } + + if err := l.signNewBatch(ctx, injective); err != nil { + return err + } + + return nil } +} - if err := s.signNewBatches(ctx, injective); err != nil { +func (l *ethSignerLoop) signNewValsetUpdates(ctx context.Context, injective InjectiveNetwork) error { + oldestUnsignedValsets, err := l.getUnsignedValsets(ctx, injective) + if err != nil { return err } + if len(oldestUnsignedValsets) == 0 { + l.Logger().Debugln("no valset updates to confirm") + return nil + } + + for _, vs := range oldestUnsignedValsets { + if err := l.signValset(ctx, injective, vs); err != nil { + return err + } + + // todo: in case of multiple updates, we should sleep in between confirms requests (non-continuous nonce) + } + return nil } -func (s *ethSigner) signNewBatches(ctx context.Context, injective InjectiveNetwork) error { - oldestUnsignedTransactionBatch, err := s.getUnsignedBatch(ctx, injective) +func (l *ethSignerLoop) signNewBatch(ctx context.Context, injective InjectiveNetwork) error { + oldestUnsignedTransactionBatch, err := l.getUnsignedBatch(ctx, injective) if err != nil { return err } if oldestUnsignedTransactionBatch == nil { - s.log.Debugln("no batch to confirm") + l.Logger().Debugln("no outgoing batch to confirm") return nil } - if err := s.signBatch(ctx, injective, oldestUnsignedTransactionBatch); err != nil { + if err := l.signBatch(ctx, injective, oldestUnsignedTransactionBatch); err != nil { return err } return nil } -func (s *ethSigner) getUnsignedBatch(ctx context.Context, injective InjectiveNetwork) (*types.OutgoingTxBatch, error) { +func (l *ethSignerLoop) getUnsignedBatch(ctx context.Context, injective InjectiveNetwork) (*types.OutgoingTxBatch, error) { var oldestUnsignedTransactionBatch *types.OutgoingTxBatch retryFn := func() (err error) { // sign the last unsigned batch, TODO check if we already have signed this oldestUnsignedTransactionBatch, err = injective.OldestUnsignedTransactionBatch(ctx) - if err == cosmos.ErrNotFound || oldestUnsignedTransactionBatch == nil { + if errors.Is(err, cosmos.ErrNotFound) || oldestUnsignedTransactionBatch == nil { return nil } @@ -111,106 +139,241 @@ func (s *ethSigner) getUnsignedBatch(ctx context.Context, injective InjectiveNet if err := retry.Do(retryFn, retry.Context(ctx), - retry.Attempts(s.retries), + retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { - s.log.WithError(err).Warningf("failed to get unconfirmed batch, will retry (%d)", n) + l.Logger().WithError(err).Warningf("failed to get unconfirmed batch, will retry (%d)", n) }), ); err != nil { - s.log.WithError(err).Errorln("got error, loop exits") + l.Logger().WithError(err).Errorln("got error, loop exits") return nil, err } return oldestUnsignedTransactionBatch, nil } -func (s *ethSigner) signBatch( - ctx context.Context, - injective InjectiveNetwork, - batch *types.OutgoingTxBatch, -) error { +func (l *ethSignerLoop) signBatch(ctx context.Context, injective InjectiveNetwork, batch *types.OutgoingTxBatch) error { if err := retry.Do( - func() error { return injective.SendBatchConfirm(ctx, s.peggyID, batch, s.ethFrom) }, + func() error { return injective.SendBatchConfirm(ctx, l.peggyID, batch, l.ethFrom) }, retry.Context(ctx), - retry.Attempts(s.retries), + retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { - s.log.WithError(err).Warningf("failed to confirm batch on Injective, will retry (%d)", n) + l.Logger().WithError(err).Warningf("failed to confirm batch on Injective, will retry (%d)", n) }), ); err != nil { - s.log.WithError(err).Errorln("got error, loop exits") + l.Logger().WithError(err).Errorln("got error, loop exits") return err } - s.log.WithField("batch_nonce", batch.BatchNonce).Infoln("confirmed batch on Injective") - - return nil -} - -func (s *ethSigner) signNewValsetUpdates( - ctx context.Context, - injective InjectiveNetwork, -) error { - oldestUnsignedValsets, err := s.getUnsignedValsets(ctx, injective) - if err != nil { - return err - } - - if len(oldestUnsignedValsets) == 0 { - s.log.Debugln("no valset updates to confirm") - return nil - } - - for _, vs := range oldestUnsignedValsets { - if err := s.signValset(ctx, injective, vs); err != nil { - return err - } - } + l.Logger().WithFields(log.Fields{ + "token_contract": batch.TokenContract, + "nonce": batch.BatchNonce, + "txs": len(batch.Transactions), + }).Infoln("confirmed batch on Injective") return nil } -func (s *ethSigner) getUnsignedValsets(ctx context.Context, injective InjectiveNetwork) ([]*types.Valset, error) { +func (l *ethSignerLoop) getUnsignedValsets(ctx context.Context, injective InjectiveNetwork) ([]*types.Valset, error) { var oldestUnsignedValsets []*types.Valset - retryFn := func() (err error) { + getOldestUnsignedValsetsFn := func() (err error) { oldestUnsignedValsets, err = injective.OldestUnsignedValsets(ctx) - if err == cosmos.ErrNotFound || oldestUnsignedValsets == nil { + if errors.Is(err, cosmos.ErrNotFound) || oldestUnsignedValsets == nil { return nil } return err } - if err := retry.Do(retryFn, + if err := retry.Do(getOldestUnsignedValsetsFn, retry.Context(ctx), - retry.Attempts(s.retries), + retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { - s.log.WithError(err).Warningf("failed to get unconfirmed valset updates, will retry (%d)", n) + l.Logger().WithError(err).Warningf("failed to get unconfirmed valset updates, will retry (%d)", n) }), ); err != nil { - s.log.WithError(err).Errorln("got error, loop exits") + l.Logger().WithError(err).Errorln("got error, loop exits") return nil, err } return oldestUnsignedValsets, nil } -func (s *ethSigner) signValset( - ctx context.Context, - injective InjectiveNetwork, - vs *types.Valset, -) error { - if err := retry.Do( - func() error { return injective.SendValsetConfirm(ctx, s.peggyID, vs, s.ethFrom) }, +func (l *ethSignerLoop) signValset(ctx context.Context, injective InjectiveNetwork, vs *types.Valset) error { + if err := retry.Do(func() error { + return injective.SendValsetConfirm(ctx, l.peggyID, vs, l.ethFrom) + }, retry.Context(ctx), - retry.Attempts(s.retries), + retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { - s.log.WithError(err).Warningf("failed to confirm valset update on Injective, will retry (%d)", n) + l.Logger().WithError(err).Warningf("failed to confirm valset update on Injective, will retry (%d)", n) }), ); err != nil { - s.log.WithError(err).Errorln("got error, loop exits") + l.Logger().WithError(err).Errorln("got error, loop exits") return err } - s.log.WithField("valset_nonce", vs.Nonce).Infoln("confirmed valset update on Injective") + l.Logger().WithFields(log.Fields{ + "nonce": vs.Nonce, + "members": len(vs.Members), + }).Infoln("confirmed valset update on Injective") return nil } + +// +//type ethSigner struct { +// log log.Logger +// peggyID common.Hash +// ethFrom common.Address +// retries uint +//} +// +//func (s *ethSigner) run(ctx context.Context, injective InjectiveNetwork) error { +// s.log.Infoln("scanning Injective for unconfirmed batches and valset updates") +// +// if err := s.signNewValsetUpdates(ctx, injective); err != nil { +// return err +// } +// +// if err := s.signNewBatches(ctx, injective); err != nil { +// return err +// } +// +// return nil +//} +// +//func (s *ethSigner) signNewBatches(ctx context.Context, injective InjectiveNetwork) error { +// oldestUnsignedTransactionBatch, err := s.getUnsignedBatch(ctx, injective) +// if err != nil { +// return err +// } +// +// if oldestUnsignedTransactionBatch == nil { +// s.log.Debugln("no batch to confirm") +// return nil +// } +// +// if err := s.signBatch(ctx, injective, oldestUnsignedTransactionBatch); err != nil { +// return err +// } +// +// return nil +//} +// +//func (s *ethSigner) getUnsignedBatch(ctx context.Context, injective InjectiveNetwork) (*types.OutgoingTxBatch, error) { +// var oldestUnsignedTransactionBatch *types.OutgoingTxBatch +// retryFn := func() (err error) { +// // sign the last unsigned batch, TODO check if we already have signed this +// oldestUnsignedTransactionBatch, err = injective.OldestUnsignedTransactionBatch(ctx) +// if err == cosmos.ErrNotFound || oldestUnsignedTransactionBatch == nil { +// return nil +// } +// +// return err +// } +// +// if err := retry.Do(retryFn, +// retry.Context(ctx), +// retry.Attempts(s.retries), +// retry.OnRetry(func(n uint, err error) { +// s.log.WithError(err).Warningf("failed to get unconfirmed batch, will retry (%d)", n) +// }), +// ); err != nil { +// s.log.WithError(err).Errorln("got error, loop exits") +// return nil, err +// } +// +// return oldestUnsignedTransactionBatch, nil +//} +// +//func (s *ethSigner) signBatch( +// ctx context.Context, +// injective InjectiveNetwork, +// batch *types.OutgoingTxBatch, +//) error { +// if err := retry.Do( +// func() error { return injective.SendBatchConfirm(ctx, s.peggyID, batch, s.ethFrom) }, +// retry.Context(ctx), +// retry.Attempts(s.retries), +// retry.OnRetry(func(n uint, err error) { +// s.log.WithError(err).Warningf("failed to confirm batch on Injective, will retry (%d)", n) +// }), +// ); err != nil { +// s.log.WithError(err).Errorln("got error, loop exits") +// return err +// } +// +// s.log.WithField("batch_nonce", batch.BatchNonce).Infoln("confirmed batch on Injective") +// +// return nil +//} +// +//func (s *ethSigner) signNewValsetUpdates( +// ctx context.Context, +// injective InjectiveNetwork, +//) error { +// oldestUnsignedValsets, err := s.getUnsignedValsets(ctx, injective) +// if err != nil { +// return err +// } +// +// if len(oldestUnsignedValsets) == 0 { +// s.log.Debugln("no valset updates to confirm") +// return nil +// } +// +// for _, vs := range oldestUnsignedValsets { +// if err := s.signValset(ctx, injective, vs); err != nil { +// return err +// } +// } +// +// return nil +//} +// +//func (s *ethSigner) getUnsignedValsets(ctx context.Context, injective InjectiveNetwork) ([]*types.Valset, error) { +// var oldestUnsignedValsets []*types.Valset +// retryFn := func() (err error) { +// oldestUnsignedValsets, err = injective.OldestUnsignedValsets(ctx) +// if err == cosmos.ErrNotFound || oldestUnsignedValsets == nil { +// return nil +// } +// +// return err +// } +// +// if err := retry.Do(retryFn, +// retry.Context(ctx), +// retry.Attempts(s.retries), +// retry.OnRetry(func(n uint, err error) { +// s.log.WithError(err).Warningf("failed to get unconfirmed valset updates, will retry (%d)", n) +// }), +// ); err != nil { +// s.log.WithError(err).Errorln("got error, loop exits") +// return nil, err +// } +// +// return oldestUnsignedValsets, nil +//} +// +//func (s *ethSigner) signValset( +// ctx context.Context, +// injective InjectiveNetwork, +// vs *types.Valset, +//) error { +// if err := retry.Do( +// func() error { return injective.SendValsetConfirm(ctx, s.peggyID, vs, s.ethFrom) }, +// retry.Context(ctx), +// retry.Attempts(s.retries), +// retry.OnRetry(func(n uint, err error) { +// s.log.WithError(err).Warningf("failed to confirm valset update on Injective, will retry (%d)", n) +// }), +// ); err != nil { +// s.log.WithError(err).Errorln("got error, loop exits") +// return err +// } +// +// s.log.WithField("valset_nonce", vs.Nonce).Infoln("confirmed valset update on Injective") +// +// return nil +//} From 9ad3c597d621eec78ccd7837884e86165e58ca18 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 21 Dec 2023 16:02:16 +0100 Subject: [PATCH 09/35] clean up relayer.go --- orchestrator/relayer.go | 304 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 294 insertions(+), 10 deletions(-) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index c7c06377..1d0297ef 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -18,20 +18,304 @@ import ( ) func (s *PeggyOrchestrator) RelayerMainLoop(ctx context.Context) (err error) { - rel := &relayer{ - log: log.WithField("loop", "Relayer"), - retries: s.maxAttempts, - relayValsetOffsetDur: s.relayValsetOffsetDur, - relayBatchOffsetDur: s.relayBatchOffsetDur, - valsetRelaying: s.valsetRelayEnabled, - batchRelaying: s.batchRelayEnabled, + loop := relayerLoop{ + PeggyOrchestrator: s, + loopDuration: defaultLoopDur, } - return loops.RunLoop( + return loop.Run(ctx, s.injective, s.ethereum) +} + +type relayerLoop struct { + *PeggyOrchestrator + loopDuration time.Duration +} + +func (l *relayerLoop) Logger() log.Logger { + return l.logger.WithField("loop", "Relayer") +} + +func (l *relayerLoop) Run(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { + return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective, ethereum)) +} + +func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) func() error { + return func() error { + var pg loops.ParanoidGroup + + if l.valsetRelayEnabled { + pg.Go(func() error { + return retry.Do( + func() error { return l.relayValsets(ctx, injective, ethereum) }, + retry.Context(ctx), + retry.Attempts(l.maxAttempts), + retry.OnRetry(func(n uint, err error) { + l.Logger().WithError(err).Warningf("failed to relay valsets, will retry (%d)", n) + }), + ) + }) + } + + if l.batchRelayEnabled { + pg.Go(func() error { + return retry.Do( + func() error { return l.relayBatches(ctx, injective, ethereum) }, + retry.Context(ctx), + retry.Attempts(l.maxAttempts), + retry.OnRetry(func(n uint, err error) { + l.Logger().WithError(err).Warningf("failed to relay batches, will retry (%d)", n) + }), + ) + }) + } + + if pg.Initialized() { + if err := pg.Wait(); err != nil { + l.Logger().WithError(err).Errorln("got error, loop exits") + return err + } + } + + return nil + } +} + +func (l *relayerLoop) relayBatches(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { + latestBatches, err := injective.LatestTransactionBatches(ctx) + if err != nil { + return err + } + + var ( + oldestConfirmedBatch *types.OutgoingTxBatch + oldestConfirmedBatchSigs []*types.MsgConfirmBatch + ) + + for _, batch := range latestBatches { + sigs, err := injective.TransactionBatchSignatures(ctx, batch.BatchNonce, common.HexToAddress(batch.TokenContract)) + if err != nil { + return err + } else if len(sigs) == 0 { + continue + } + + oldestConfirmedBatch = batch + oldestConfirmedBatchSigs = sigs + } + + if oldestConfirmedBatch == nil { + l.Logger().Debugln("no confirmed transaction batches on Injective, nothing to relay...") + return nil + } + + latestEthereumBatch, err := ethereum.GetTxBatchNonce( + ctx, + common.HexToAddress(oldestConfirmedBatch.TokenContract), + ) + if err != nil { + return err + } + + currentValset, err := l.findLatestValsetOnEth(ctx, injective, ethereum) + if err != nil { + return errors.Wrap(err, "failed to find latest valset") + } else if currentValset == nil { + return errors.Wrap(err, "latest valset not found") + } + + l.Logger().WithFields(log.Fields{"inj_batch": oldestConfirmedBatch.BatchNonce, "eth_batch": latestEthereumBatch.Uint64()}).Debugln("latest batches") + + if oldestConfirmedBatch.BatchNonce <= latestEthereumBatch.Uint64() { + return nil + } + + latestEthereumBatch, err = ethereum.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) + if err != nil { + return err + } + + // Check if ethereum batch was updated by other validators + if oldestConfirmedBatch.BatchNonce <= latestEthereumBatch.Uint64() { + return nil + } + + // Check custom time delay offset + blockTime, err := injective.GetBlockCreationTime(ctx, int64(oldestConfirmedBatch.Block)) + if err != nil { + return errors.Wrap(err, "failed to parse timestamp from block") + } + + if timeElapsed := time.Since(blockTime); timeElapsed <= l.relayValsetOffsetDur { + timeRemaining := time.Duration(int64(l.relayBatchOffsetDur) - int64(timeElapsed)) + l.Logger().WithField("time_remaining", timeRemaining.String()).Debugln("batch relay offset duration not expired") + return nil + } + + l.Logger().WithFields(log.Fields{ + "inj_batch": oldestConfirmedBatch.BatchNonce, + "eth_batch": latestEthereumBatch.Uint64(), + "token_contract": common.HexToAddress(oldestConfirmedBatch.TokenContract), + }).Infoln("detected new batch on Injective") + + // Send SendTransactionBatch to Ethereum + txHash, err := ethereum.SendTransactionBatch(ctx, currentValset, oldestConfirmedBatch, oldestConfirmedBatchSigs) + if err != nil { + return err + } + + l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("sent batch tx to Ethereum") + + return nil +} + +func (l *relayerLoop) relayValsets(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { + // we should determine if we need to relay one + // to Ethereum for that we will find the latest confirmed valset and compare it to the ethereum chain + latestValsets, err := injective.LatestValsets(ctx) + if err != nil { + return errors.Wrap(err, "failed to get latest valset updates from Injective") + } + + var ( + oldestConfirmedValset *types.Valset + oldestConfirmedValsetSigs []*types.MsgValsetConfirm + ) + + for _, set := range latestValsets { + sigs, err := injective.AllValsetConfirms(ctx, set.Nonce) + if err != nil { + return errors.Wrapf(err, "failed to get valset confirmations for nonce %d", set.Nonce) + } else if len(sigs) == 0 { + continue + } + + oldestConfirmedValsetSigs = sigs + oldestConfirmedValset = set + break + } + + if oldestConfirmedValset == nil { + l.Logger().Debugln("no valset update to relay") + return nil + } + + currentEthValset, err := l.findLatestValsetOnEth(ctx, injective, ethereum) + if err != nil { + return errors.Wrap(err, "failed to find latest confirmed valset update on Ethereum") + } + + l.Logger().WithFields(log.Fields{"inj_valset": oldestConfirmedValset, "eth_valset": currentEthValset}).Debugln("latest valset updates") + + if oldestConfirmedValset.Nonce <= currentEthValset.Nonce { + return nil + } + + latestEthereumValsetNonce, err := ethereum.GetValsetNonce(ctx) + if err != nil { + return errors.Wrap(err, "failed to get latest valset nonce from Ethereum") + } + + // Check if other validators already updated the valset + if oldestConfirmedValset.Nonce <= latestEthereumValsetNonce.Uint64() { + return nil + } + + // Check custom time delay offset + blockTime, err := injective.GetBlockCreationTime(ctx, int64(oldestConfirmedValset.Height)) + if err != nil { + return errors.Wrap(err, "failed to parse timestamp from block") + } + + if timeElapsed := time.Since(blockTime); timeElapsed <= l.relayValsetOffsetDur { + timeRemaining := time.Duration(int64(l.relayBatchOffsetDur) - int64(timeElapsed)) + l.Logger().WithField("time_remaining", timeRemaining.String()).Debugln("valset relay offset duration not expired") + return nil + } + + l.Logger().WithFields(log.Fields{"inj_valset": oldestConfirmedValset.Nonce, "eth_valset": latestEthereumValsetNonce.Uint64()}).Infoln("detected new valset on Injective") + + txHash, err := ethereum.SendEthValsetUpdate( ctx, - defaultLoopDur, - func() error { return rel.run(ctx, s.injective, s.ethereum) }, + currentEthValset, + oldestConfirmedValset, + oldestConfirmedValsetSigs, ) + if err != nil { + return err + } + + l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("updated valset on Ethereum") + + return nil +} + +func (l *relayerLoop) findLatestValsetOnEth(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) (*types.Valset, error) { + latestHeader, err := ethereum.HeaderByNumber(ctx, nil) + if err != nil { + return nil, errors.Wrap(err, "failed to get latest eth header") + } + + latestEthereumValsetNonce, err := ethereum.GetValsetNonce(ctx) + if err != nil { + return nil, errors.Wrap(err, "failed to get latest valset nonce on Ethereum") + } + + cosmosValset, err := injective.ValsetAt(ctx, latestEthereumValsetNonce.Uint64()) + if err != nil { + return nil, errors.Wrap(err, "failed to get Injective valset") + } + + currentBlock := latestHeader.Number.Uint64() + + for currentBlock > 0 { + var startSearchBlock uint64 + if currentBlock <= valsetBlocksToSearch { + startSearchBlock = 0 + } else { + startSearchBlock = currentBlock - valsetBlocksToSearch + } + + l.Logger().WithFields(log.Fields{"block_start": startSearchBlock, "block_end": currentBlock}).Debugln("looking for the most recent ValsetUpdatedEvent on Ethereum") + + valsetUpdatedEvents, err := ethereum.GetValsetUpdatedEvents(startSearchBlock, currentBlock) + if err != nil { + return nil, errors.Wrap(err, "failed to filter past ValsetUpdated events from Ethereum") + } + + // by default the lowest found valset goes first, we want the highest + // + // TODO(xlab): this follows the original impl, but sort might be skipped there: + // we could access just the latest element later. + sort.Sort(sort.Reverse(PeggyValsetUpdatedEvents(valsetUpdatedEvents))) + + if len(valsetUpdatedEvents) == 0 { + currentBlock = startSearchBlock + continue + } + + // we take only the first event if we find any at all. + event := valsetUpdatedEvents[0] + valset := &types.Valset{ + Nonce: event.NewValsetNonce.Uint64(), + Members: make([]*types.BridgeValidator, 0, len(event.Powers)), + RewardAmount: sdk.NewIntFromBigInt(event.RewardAmount), + RewardToken: event.RewardToken.Hex(), + } + + for idx, p := range event.Powers { + valset.Members = append(valset.Members, &types.BridgeValidator{ + Power: p.Uint64(), + EthereumAddress: event.Validators[idx].Hex(), + }) + } + + checkIfValsetsDiffer(cosmosValset, valset) + + return valset, nil + + } + + return nil, ErrNotFound } type relayer struct { From c75066e721131c75fe7bdde45ea53746b62279d2 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 21 Dec 2023 16:07:55 +0100 Subject: [PATCH 10/35] log --- orchestrator/relayer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index 1d0297ef..8d3e62d2 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -104,7 +104,7 @@ func (l *relayerLoop) relayBatches(ctx context.Context, injective InjectiveNetwo } if oldestConfirmedBatch == nil { - l.Logger().Debugln("no confirmed transaction batches on Injective, nothing to relay...") + l.Logger().Debugln("no outgoing batch to relay") return nil } From 5d3f382a93ae7f9e01c59c17cede02194041f4fd Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 21 Dec 2023 16:09:28 +0100 Subject: [PATCH 11/35] relay offset --- orchestrator/relayer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index 8d3e62d2..d51271e9 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -145,7 +145,7 @@ func (l *relayerLoop) relayBatches(ctx context.Context, injective InjectiveNetwo return errors.Wrap(err, "failed to parse timestamp from block") } - if timeElapsed := time.Since(blockTime); timeElapsed <= l.relayValsetOffsetDur { + if timeElapsed := time.Since(blockTime); timeElapsed <= l.relayBatchOffsetDur { timeRemaining := time.Duration(int64(l.relayBatchOffsetDur) - int64(timeElapsed)) l.Logger().WithField("time_remaining", timeRemaining.String()).Debugln("batch relay offset duration not expired") return nil From b87cac0e5d995bbf6bc6883af39232dfae0df94a Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 21 Dec 2023 16:34:24 +0100 Subject: [PATCH 12/35] remove redundant code --- orchestrator/batch_request.go | 129 +------------- orchestrator/oracle.go | 222 +---------------------- orchestrator/relayer.go | 323 +--------------------------------- orchestrator/signer.go | 160 +---------------- 4 files changed, 13 insertions(+), 821 deletions(-) diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index cdcbe763..145a5c3a 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -2,14 +2,16 @@ package orchestrator import ( "context" - "github.com/InjectiveLabs/peggo/orchestrator/loops" - "github.com/InjectiveLabs/sdk-go/chain/peggy/types" + "time" + "github.com/avast/retry-go" cosmtypes "github.com/cosmos/cosmos-sdk/types" eth "github.com/ethereum/go-ethereum/common" "github.com/shopspring/decimal" log "github.com/xlab/suplog" - "time" + + "github.com/InjectiveLabs/peggo/orchestrator/loops" + "github.com/InjectiveLabs/sdk-go/chain/peggy/types" ) func (s *PeggyOrchestrator) BatchRequesterLoop(ctx context.Context) (err error) { @@ -98,10 +100,7 @@ func (l *batchRequestLoop) requestBatch( return } - l.Logger().WithFields(log.Fields{ - "denom": denom, - "token_contract": tokenAddr.String(), - }).Infoln("requesting batch on Injective") + l.Logger().WithFields(log.Fields{"denom": denom, "token_contract": tokenAddr.String()}).Infoln("requesting batch on Injective") _ = injective.SendRequestBatch(ctx, denom) } @@ -135,119 +134,3 @@ func (l *batchRequestLoop) checkFeeThreshold(feed PriceFeed, tokenAddr eth.Addre return true } - -// -//type batchRequester struct { -// log log.Logger -// retries uint -// minBatchFee float64 -// erc20ContractMapping map[eth.Address]string -//} -// -//func (r *batchRequester) run( -// ctx context.Context, -// injective InjectiveNetwork, -// feed PriceFeed, -//) error { -// r.log.WithField("min_batch_fee", r.minBatchFee).Infoln("scanning Injective for potential batches") -// -// unbatchedFees, err := r.getUnbatchedFeesByToken(ctx, injective) -// if err != nil { -// // non-fatal, just alert -// r.log.WithError(err).Warningln("unable to get unbatched fees from Injective") -// return nil -// } -// -// if len(unbatchedFees) == 0 { -// r.log.Debugln("no outgoing withdrawals or minimum batch fee is not met") -// return nil -// } -// -// for _, tokenFee := range unbatchedFees { -// r.requestBatchCreation(ctx, injective, feed, tokenFee) -// } -// -// return nil -//} -// -//func (r *batchRequester) getUnbatchedFeesByToken(ctx context.Context, injective InjectiveNetwork) ([]*types.BatchFees, error) { -// var unbatchedFees []*types.BatchFees -// retryFn := func() (err error) { -// unbatchedFees, err = injective.UnbatchedTokenFees(ctx) -// return err -// } -// -// if err := retry.Do(retryFn, -// retry.Context(ctx), -// retry.Attempts(r.retries), -// retry.OnRetry(func(n uint, err error) { -// log.WithError(err).Errorf("failed to get unbatched fees, will retry (%d)", n) -// }), -// ); err != nil { -// return nil, err -// } -// -// return unbatchedFees, nil -//} -// -//func (r *batchRequester) requestBatchCreation( -// ctx context.Context, -// injective InjectiveNetwork, -// feed PriceFeed, -// batchFee *types.BatchFees, -//) { -// var ( -// tokenAddr = eth.HexToAddress(batchFee.Token) -// denom = r.tokenDenom(tokenAddr) -// ) -// -// if thresholdMet := r.checkFeeThreshold(feed, tokenAddr, batchFee.TotalFees); !thresholdMet { -// r.log.WithFields(log.Fields{ -// "denom": denom, -// "token_contract": tokenAddr.String(), -// "total_fees": batchFee.TotalFees.String(), -// }).Debugln("skipping underpriced batch") -// return -// } -// -// r.log.WithFields(log.Fields{ -// "denom": denom, -// "token_contract": tokenAddr.String(), -// }).Infoln("requesting batch creation on Injective") -// -// _ = injective.SendRequestBatch(ctx, denom) -//} -// -//func (r *batchRequester) tokenDenom(tokenAddr eth.Address) string { -// if cosmosDenom, ok := r.erc20ContractMapping[tokenAddr]; ok { -// return cosmosDenom -// } -// -// // peggy denom -// return types.PeggyDenomString(tokenAddr) -//} -// -//func (r *batchRequester) checkFeeThreshold( -// feed PriceFeed, -// tokenAddr eth.Address, -// totalFees cosmtypes.Int, -//) bool { -// if r.minBatchFee == 0 { -// return true -// } -// -// tokenPriceInUSD, err := feed.QueryUSDPrice(tokenAddr) -// if err != nil { -// return false -// } -// -// tokenPriceInUSDDec := decimal.NewFromFloat(tokenPriceInUSD) -// totalFeeInUSDDec := decimal.NewFromBigInt(totalFees.BigInt(), -18).Mul(tokenPriceInUSDDec) -// minFeeInUSDDec := decimal.NewFromFloat(r.minBatchFee) -// -// if totalFeeInUSDDec.GreaterThan(minFeeInUSDDec) { -// return true -// } -// -// return false -//} diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index 69c786e7..67615041 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -2,13 +2,13 @@ package orchestrator import ( "context" - "github.com/InjectiveLabs/peggo/orchestrator/loops" "time" "github.com/avast/retry-go" "github.com/pkg/errors" log "github.com/xlab/suplog" + "github.com/InjectiveLabs/peggo/orchestrator/loops" wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" ) @@ -28,7 +28,7 @@ func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { return err } - s.logger.Infoln("scanning Ethereum events from block", lastConfirmedEthHeight) + s.logger.Debugln("scanning Ethereum events from block", lastConfirmedEthHeight) loop := ethOracleLoop{ PeggyOrchestrator: s, @@ -207,7 +207,7 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetw "legacy_deposits": len(legacyDeposits), "deposits": len(deposits), "withdrawals": len(withdrawals), - "erc2_deployments": len(erc20Deployments), + "erc20_deployments": len(erc20Deployments), "valset_updates": len(valsetUpdates), }).Infoln("sent new claims to Injective") @@ -259,222 +259,6 @@ func (l *ethOracleLoop) autoResync(ctx context.Context, injective InjectiveNetwo return nil } -// -//type ethOracle struct { -// log log.Logger -// retries uint -// lastResyncWithInjective time.Time -// lastCheckedEthHeight uint64 -//} -// -//func (o *ethOracle) run( -// ctx context.Context, -// injective InjectiveNetwork, -// ethereum EthereumNetwork, -//) error { -// o.log.WithField("last_checked_eth_height", o.lastCheckedEthHeight).Infoln("scanning Ethereum for events") -// -// // Relays events from Ethereum -> Cosmos -// newHeight, err := o.relayEvents(ctx, injective, ethereum) -// if err != nil { -// return err -// } -// -// o.lastCheckedEthHeight = newHeight -// -// if time.Since(o.lastResyncWithInjective) >= 48*time.Hour { -// /** -// Auto re-sync to catch up the nonce. Reasons why event nonce fall behind. -// 1. It takes some time for events to be indexed on Ethereum. So if peggo queried events immediately as block produced, there is a chance the event is missed. -// we need to re-scan this block to ensure events are not missed due to indexing delay. -// 2. if validator was in UnBonding state, the claims broadcasted in last iteration are failed. -// 3. if infura call failed while filtering events, the peggo missed to broadcast claim events occured in last iteration. -// **/ -// if err := o.autoResync(ctx, injective); err != nil { -// return err -// } -// } -// -// return nil -//} -// -//func (o *ethOracle) relayEvents( -// ctx context.Context, -// injective InjectiveNetwork, -// ethereum EthereumNetwork, -//) (uint64, error) { -// // Relays events from Ethereum -> Cosmos -// var ( -// latestHeight uint64 -// currentHeight = o.lastCheckedEthHeight -// ) -// -// retryFn := func() error { -// latestHeader, err := ethereum.HeaderByNumber(ctx, nil) -// if err != nil { -// return errors.Wrap(err, "failed to get latest ethereum header") -// } -// -// // add delay to ensure minimum confirmations are received and block is finalised -// latestHeight = latestHeader.Number.Uint64() - ethBlockConfirmationDelay -// if latestHeight < currentHeight { -// println(latestHeight) -// return nil -// } -// -// if latestHeight > currentHeight+defaultBlocksToSearch { -// latestHeight = currentHeight + defaultBlocksToSearch -// } -// -// legacyDeposits, err := ethereum.GetSendToCosmosEvents(currentHeight, latestHeight) -// if err != nil { -// return errors.Wrap(err, "failed to get SendToCosmos events") -// } -// -// deposits, err := ethereum.GetSendToInjectiveEvents(currentHeight, latestHeight) -// if err != nil { -// return errors.Wrap(err, "failed to get SendToInjective events") -// } -// -// withdrawals, err := ethereum.GetTransactionBatchExecutedEvents(currentHeight, latestHeight) -// if err != nil { -// return errors.Wrap(err, "failed to get TransactionBatchExecuted events") -// } -// -// erc20Deployments, err := ethereum.GetPeggyERC20DeployedEvents(currentHeight, latestHeight) -// if err != nil { -// return errors.Wrap(err, "failed to get ERC20Deployed events") -// } -// -// valsetUpdates, err := ethereum.GetValsetUpdatedEvents(currentHeight, latestHeight) -// if err != nil { -// return errors.Wrap(err, "failed to get ValsetUpdated events") -// } -// -// // note that starting block overlaps with our last checked block, because we have to deal with -// // the possibility that the relayer was killed after relaying only one of multiple events in a single -// // block, so we also need this routine so make sure we don't send in the first event in this hypothetical -// // multi event block again. In theory we only send all events for every block and that will pass of fail -// // atomically but lets not take that risk. -// lastClaimEvent, err := injective.LastClaimEvent(ctx) -// if err != nil { -// return errors.New("failed to query last claim event from Injective") -// } -// -// legacyDeposits = filterSendToCosmosEventsByNonce(legacyDeposits, lastClaimEvent.EthereumEventNonce) -// o.log.WithFields(log.Fields{ -// "block_start": currentHeight, -// "block_end": latestHeight, -// "events": legacyDeposits, -// }).Debugln("scanned SendToCosmos events") -// -// deposits = filterSendToInjectiveEventsByNonce(deposits, lastClaimEvent.EthereumEventNonce) -// o.log.WithFields(log.Fields{ -// "block_start": currentHeight, -// "block_end": latestHeight, -// "events": deposits, -// }).Debugln("scanned SendToInjective events") -// -// withdrawals = filterTransactionBatchExecutedEventsByNonce(withdrawals, lastClaimEvent.EthereumEventNonce) -// o.log.WithFields(log.Fields{ -// "block_start": currentHeight, -// "block_end": latestHeight, -// "events": withdrawals, -// }).Debugln("scanned TransactionBatchExecuted events") -// -// erc20Deployments = filterERC20DeployedEventsByNonce(erc20Deployments, lastClaimEvent.EthereumEventNonce) -// o.log.WithFields(log.Fields{ -// "block_start": currentHeight, -// "block_end": latestHeight, -// "events": erc20Deployments, -// }).Debugln("scanned FilterERC20Deployed events") -// -// valsetUpdates = filterValsetUpdateEventsByNonce(valsetUpdates, lastClaimEvent.EthereumEventNonce) -// o.log.WithFields(log.Fields{ -// "block_start": currentHeight, -// "block_end": latestHeight, -// "events": valsetUpdates, -// }).Debugln("scanned ValsetUpdated events") -// -// if len(legacyDeposits) == 0 && -// len(deposits) == 0 && -// len(withdrawals) == 0 && -// len(erc20Deployments) == 0 && -// len(valsetUpdates) == 0 { -// return nil -// } -// -// if err := injective.SendEthereumClaims(ctx, -// lastClaimEvent.EthereumEventNonce, -// legacyDeposits, -// deposits, -// withdrawals, -// erc20Deployments, -// valsetUpdates, -// ); err != nil { -// return errors.Wrap(err, "failed to send event claims to Injective") -// } -// -// o.log.WithFields(log.Fields{ -// "last_claim_event_nonce": lastClaimEvent.EthereumEventNonce, -// "legacy_deposits": len(legacyDeposits), -// "deposits": len(deposits), -// "withdrawals": len(withdrawals), -// "erc20Deployments": len(erc20Deployments), -// "valsetUpdates": len(valsetUpdates), -// }).Infoln("sent new claims to Injective") -// -// return nil -// } -// -// if err := retry.Do(retryFn, -// retry.Context(ctx), -// retry.Attempts(o.retries), -// retry.OnRetry(func(n uint, err error) { -// o.log.WithError(err).Warningf("error during Ethereum event checking, will retry (%d)", n) -// }), -// ); err != nil { -// o.log.WithError(err).Errorln("got error, loop exits") -// return 0, err -// } -// -// return latestHeight, nil -//} -// -//func (o *ethOracle) autoResync(ctx context.Context, injective InjectiveNetwork) error { -// var latestHeight uint64 -// retryFn := func() error { -// lastClaimEvent, err := injective.LastClaimEvent(ctx) -// if err != nil { -// return err -// } -// -// latestHeight = lastClaimEvent.EthereumEventHeight -// return nil -// } -// -// if err := retry.Do(retryFn, -// retry.Context(ctx), -// retry.Attempts(o.retries), -// retry.OnRetry(func(n uint, err error) { -// o.log.WithError(err).Warningf("failed to get last confirmed eth height, will retry (%d)", n) -// }), -// ); err != nil { -// o.log.WithError(err).Errorln("got error, loop exits") -// return err -// } -// -// o.lastCheckedEthHeight = latestHeight -// o.lastResyncWithInjective = time.Now() -// -// o.log.WithFields(log.Fields{ -// "last_resync": o.lastResyncWithInjective.String(), -// "last_confirmed_eth_height": o.lastCheckedEthHeight, -// }).Infoln("auto resync") -// -// return nil -//} - func filterSendToCosmosEventsByNonce( events []*wrappers.PeggySendToCosmosEvent, nonce uint64, diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index d51271e9..d8e492b9 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -5,6 +5,7 @@ import ( "sort" "time" + "github.com/InjectiveLabs/sdk-go/chain/peggy/types" "github.com/avast/retry-go" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" @@ -14,7 +15,6 @@ import ( "github.com/InjectiveLabs/peggo/orchestrator/ethereum/util" "github.com/InjectiveLabs/peggo/orchestrator/loops" wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" - "github.com/InjectiveLabs/sdk-go/chain/peggy/types" ) func (s *PeggyOrchestrator) RelayerMainLoop(ctx context.Context) (err error) { @@ -249,316 +249,6 @@ func (l *relayerLoop) relayValsets(ctx context.Context, injective InjectiveNetwo return nil } -func (l *relayerLoop) findLatestValsetOnEth(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) (*types.Valset, error) { - latestHeader, err := ethereum.HeaderByNumber(ctx, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to get latest eth header") - } - - latestEthereumValsetNonce, err := ethereum.GetValsetNonce(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to get latest valset nonce on Ethereum") - } - - cosmosValset, err := injective.ValsetAt(ctx, latestEthereumValsetNonce.Uint64()) - if err != nil { - return nil, errors.Wrap(err, "failed to get Injective valset") - } - - currentBlock := latestHeader.Number.Uint64() - - for currentBlock > 0 { - var startSearchBlock uint64 - if currentBlock <= valsetBlocksToSearch { - startSearchBlock = 0 - } else { - startSearchBlock = currentBlock - valsetBlocksToSearch - } - - l.Logger().WithFields(log.Fields{"block_start": startSearchBlock, "block_end": currentBlock}).Debugln("looking for the most recent ValsetUpdatedEvent on Ethereum") - - valsetUpdatedEvents, err := ethereum.GetValsetUpdatedEvents(startSearchBlock, currentBlock) - if err != nil { - return nil, errors.Wrap(err, "failed to filter past ValsetUpdated events from Ethereum") - } - - // by default the lowest found valset goes first, we want the highest - // - // TODO(xlab): this follows the original impl, but sort might be skipped there: - // we could access just the latest element later. - sort.Sort(sort.Reverse(PeggyValsetUpdatedEvents(valsetUpdatedEvents))) - - if len(valsetUpdatedEvents) == 0 { - currentBlock = startSearchBlock - continue - } - - // we take only the first event if we find any at all. - event := valsetUpdatedEvents[0] - valset := &types.Valset{ - Nonce: event.NewValsetNonce.Uint64(), - Members: make([]*types.BridgeValidator, 0, len(event.Powers)), - RewardAmount: sdk.NewIntFromBigInt(event.RewardAmount), - RewardToken: event.RewardToken.Hex(), - } - - for idx, p := range event.Powers { - valset.Members = append(valset.Members, &types.BridgeValidator{ - Power: p.Uint64(), - EthereumAddress: event.Validators[idx].Hex(), - }) - } - - checkIfValsetsDiffer(cosmosValset, valset) - - return valset, nil - - } - - return nil, ErrNotFound -} - -type relayer struct { - log log.Logger - retries uint - relayValsetOffsetDur time.Duration - relayBatchOffsetDur time.Duration - valsetRelaying bool - batchRelaying bool -} - -func (r *relayer) run( - ctx context.Context, - injective InjectiveNetwork, - ethereum EthereumNetwork, -) error { - var pg loops.ParanoidGroup - - if r.valsetRelaying { - r.log.Infoln("scanning Injective for confirmed valset updates") - pg.Go(func() error { - return retry.Do( - func() error { return r.relayValsets(ctx, injective, ethereum) }, - retry.Context(ctx), - retry.Attempts(r.retries), - retry.OnRetry(func(n uint, err error) { - r.log.WithError(err).Warningf("failed to relay valsets, will retry (%d)", n) - }), - ) - }) - } - - if r.batchRelaying { - r.log.Infoln("scanning Injective for confirmed batches") - pg.Go(func() error { - return retry.Do( - func() error { return r.relayBatches(ctx, injective, ethereum) }, - retry.Context(ctx), - retry.Attempts(r.retries), - retry.OnRetry(func(n uint, err error) { - r.log.WithError(err).Warningf("failed to relay batches, will retry (%d)", n) - }), - ) - }) - } - - if pg.Initialized() { - if err := pg.Wait(); err != nil { - r.log.WithError(err).Errorln("got error, loop exits") - return err - } - } - - return nil -} - -func (r *relayer) relayValsets( - ctx context.Context, - injective InjectiveNetwork, - ethereum EthereumNetwork, -) error { - // we should determine if we need to relay one - // to Ethereum for that we will find the latest confirmed valset and compare it to the ethereum chain - latestValsets, err := injective.LatestValsets(ctx) - if err != nil { - return errors.Wrap(err, "failed to get latest valset updates from Injective") - } - - var ( - oldestConfirmedValset *types.Valset - oldestConfirmedValsetSigs []*types.MsgValsetConfirm - ) - - for _, set := range latestValsets { - sigs, err := injective.AllValsetConfirms(ctx, set.Nonce) - if err != nil { - return errors.Wrapf(err, "failed to get valset confirmations for nonce %d", set.Nonce) - } else if len(sigs) == 0 { - continue - } - - oldestConfirmedValsetSigs = sigs - oldestConfirmedValset = set - break - } - - if oldestConfirmedValset == nil { - r.log.Debugln("no confirmed valset updates to relay") - return nil - } - - currentEthValset, err := r.findLatestValsetOnEth(ctx, injective, ethereum) - if err != nil { - return errors.Wrap(err, "failed to find latest confirmed valset update on Ethereum") - } - - r.log.WithFields(log.Fields{ - "inj_valset": oldestConfirmedValset, - "eth_valset": currentEthValset, - }).Debugln("latest valset updates") - - if oldestConfirmedValset.Nonce <= currentEthValset.Nonce { - return nil - } - - latestEthereumValsetNonce, err := ethereum.GetValsetNonce(ctx) - if err != nil { - return errors.Wrap(err, "failed to get latest valset nonce from Ethereum") - } - - // Check if other validators already updated the valset - if oldestConfirmedValset.Nonce <= latestEthereumValsetNonce.Uint64() { - return nil - } - - // Check custom time delay offset - blockTime, err := injective.GetBlockCreationTime(ctx, int64(oldestConfirmedValset.Height)) - if err != nil { - return errors.Wrap(err, "failed to parse timestamp from block") - } - - if timeElapsed := time.Since(blockTime); timeElapsed <= r.relayValsetOffsetDur { - timeRemaining := time.Duration(int64(r.relayBatchOffsetDur) - int64(timeElapsed)) - r.log.WithField("time_remaining", timeRemaining.String()).Debugln("valset relay offset duration not expired") - return nil - } - - r.log.WithFields(log.Fields{ - "inj_valset": oldestConfirmedValset.Nonce, - "eth_valset": latestEthereumValsetNonce.Uint64(), - }).Infoln("detected new valset on Injective") - - txHash, err := ethereum.SendEthValsetUpdate( - ctx, - currentEthValset, - oldestConfirmedValset, - oldestConfirmedValsetSigs, - ) - - if err != nil { - return err - } - - r.log.WithField("tx_hash", txHash.Hex()).Infoln("updated valset on Ethereum") - - return nil -} - -func (r *relayer) relayBatches( - ctx context.Context, - injective InjectiveNetwork, - ethereum EthereumNetwork, -) error { - latestBatches, err := injective.LatestTransactionBatches(ctx) - if err != nil { - return err - } - - var ( - oldestConfirmedBatch *types.OutgoingTxBatch - oldestConfirmedBatchSigs []*types.MsgConfirmBatch - ) - - for _, batch := range latestBatches { - sigs, err := injective.TransactionBatchSignatures(ctx, batch.BatchNonce, common.HexToAddress(batch.TokenContract)) - if err != nil { - return err - } else if len(sigs) == 0 { - continue - } - - oldestConfirmedBatch = batch - oldestConfirmedBatchSigs = sigs - } - - if oldestConfirmedBatch == nil { - r.log.Debugln("no confirmed transaction batches on Injective, nothing to relay...") - return nil - } - - latestEthereumBatch, err := ethereum.GetTxBatchNonce( - ctx, - common.HexToAddress(oldestConfirmedBatch.TokenContract), - ) - if err != nil { - return err - } - - currentValset, err := r.findLatestValsetOnEth(ctx, injective, ethereum) - if err != nil { - return errors.Wrap(err, "failed to find latest valset") - } else if currentValset == nil { - return errors.Wrap(err, "latest valset not found") - } - - r.log.WithFields(log.Fields{ - "inj_batch": oldestConfirmedBatch.BatchNonce, - "eth_batch": latestEthereumBatch.Uint64(), - }).Debugln("latest batches") - - if oldestConfirmedBatch.BatchNonce <= latestEthereumBatch.Uint64() { - return nil - } - - latestEthereumBatch, err = ethereum.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) - if err != nil { - return err - } - - // Check if ethereum batch was updated by other validators - if oldestConfirmedBatch.BatchNonce <= latestEthereumBatch.Uint64() { - return nil - } - - // Check custom time delay offset - blockTime, err := injective.GetBlockCreationTime(ctx, int64(oldestConfirmedBatch.Block)) - if err != nil { - return errors.Wrap(err, "failed to parse timestamp from block") - } - - if timeElapsed := time.Since(blockTime); timeElapsed <= r.relayValsetOffsetDur { - timeRemaining := time.Duration(int64(r.relayBatchOffsetDur) - int64(timeElapsed)) - r.log.WithField("time_remaining", timeRemaining.String()).Debugln("batch relay offset duration not expired") - return nil - } - - r.log.WithFields(log.Fields{ - "inj_batch": oldestConfirmedBatch.BatchNonce, - "eth_batch": latestEthereumBatch.Uint64(), - "token_contract": common.HexToAddress(oldestConfirmedBatch.TokenContract), - }).Infoln("detected new batch on Injective") - - // Send SendTransactionBatch to Ethereum - txHash, err := ethereum.SendTransactionBatch(ctx, currentValset, oldestConfirmedBatch, oldestConfirmedBatchSigs) - if err != nil { - return err - } - - r.log.WithField("tx_hash", txHash.Hex()).Infoln("sent batch tx to Ethereum") - - return nil -} - const valsetBlocksToSearch = 2000 // FindLatestValset finds the latest valset on the Peggy contract by looking back through the event @@ -566,11 +256,7 @@ const valsetBlocksToSearch = 2000 // as the latest update will be in recent blockchain history and the search moves from the present // backwards in time. In the case that the validator set has not been updated for a very long time // this will take longer. -func (r *relayer) findLatestValsetOnEth( - ctx context.Context, - injective InjectiveNetwork, - ethereum EthereumNetwork, -) (*types.Valset, error) { +func (l *relayerLoop) findLatestValsetOnEth(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) (*types.Valset, error) { latestHeader, err := ethereum.HeaderByNumber(ctx, nil) if err != nil { return nil, errors.Wrap(err, "failed to get latest eth header") @@ -596,10 +282,7 @@ func (r *relayer) findLatestValsetOnEth( startSearchBlock = currentBlock - valsetBlocksToSearch } - r.log.WithFields(log.Fields{ - "block_start": startSearchBlock, - "block_end": currentBlock, - }).Debugln("looking for the most recent ValsetUpdatedEvent on Ethereum") + l.Logger().WithFields(log.Fields{"block_start": startSearchBlock, "block_end": currentBlock}).Debugln("looking for the most recent ValsetUpdatedEvent on Ethereum") valsetUpdatedEvents, err := ethereum.GetValsetUpdatedEvents(startSearchBlock, currentBlock) if err != nil { diff --git a/orchestrator/signer.go b/orchestrator/signer.go index c8e13fc9..f02c09f3 100644 --- a/orchestrator/signer.go +++ b/orchestrator/signer.go @@ -2,11 +2,11 @@ package orchestrator import ( "context" - "github.com/pkg/errors" "time" "github.com/avast/retry-go" "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" log "github.com/xlab/suplog" "github.com/InjectiveLabs/peggo/orchestrator/cosmos" @@ -219,161 +219,3 @@ func (l *ethSignerLoop) signValset(ctx context.Context, injective InjectiveNetwo return nil } - -// -//type ethSigner struct { -// log log.Logger -// peggyID common.Hash -// ethFrom common.Address -// retries uint -//} -// -//func (s *ethSigner) run(ctx context.Context, injective InjectiveNetwork) error { -// s.log.Infoln("scanning Injective for unconfirmed batches and valset updates") -// -// if err := s.signNewValsetUpdates(ctx, injective); err != nil { -// return err -// } -// -// if err := s.signNewBatches(ctx, injective); err != nil { -// return err -// } -// -// return nil -//} -// -//func (s *ethSigner) signNewBatches(ctx context.Context, injective InjectiveNetwork) error { -// oldestUnsignedTransactionBatch, err := s.getUnsignedBatch(ctx, injective) -// if err != nil { -// return err -// } -// -// if oldestUnsignedTransactionBatch == nil { -// s.log.Debugln("no batch to confirm") -// return nil -// } -// -// if err := s.signBatch(ctx, injective, oldestUnsignedTransactionBatch); err != nil { -// return err -// } -// -// return nil -//} -// -//func (s *ethSigner) getUnsignedBatch(ctx context.Context, injective InjectiveNetwork) (*types.OutgoingTxBatch, error) { -// var oldestUnsignedTransactionBatch *types.OutgoingTxBatch -// retryFn := func() (err error) { -// // sign the last unsigned batch, TODO check if we already have signed this -// oldestUnsignedTransactionBatch, err = injective.OldestUnsignedTransactionBatch(ctx) -// if err == cosmos.ErrNotFound || oldestUnsignedTransactionBatch == nil { -// return nil -// } -// -// return err -// } -// -// if err := retry.Do(retryFn, -// retry.Context(ctx), -// retry.Attempts(s.retries), -// retry.OnRetry(func(n uint, err error) { -// s.log.WithError(err).Warningf("failed to get unconfirmed batch, will retry (%d)", n) -// }), -// ); err != nil { -// s.log.WithError(err).Errorln("got error, loop exits") -// return nil, err -// } -// -// return oldestUnsignedTransactionBatch, nil -//} -// -//func (s *ethSigner) signBatch( -// ctx context.Context, -// injective InjectiveNetwork, -// batch *types.OutgoingTxBatch, -//) error { -// if err := retry.Do( -// func() error { return injective.SendBatchConfirm(ctx, s.peggyID, batch, s.ethFrom) }, -// retry.Context(ctx), -// retry.Attempts(s.retries), -// retry.OnRetry(func(n uint, err error) { -// s.log.WithError(err).Warningf("failed to confirm batch on Injective, will retry (%d)", n) -// }), -// ); err != nil { -// s.log.WithError(err).Errorln("got error, loop exits") -// return err -// } -// -// s.log.WithField("batch_nonce", batch.BatchNonce).Infoln("confirmed batch on Injective") -// -// return nil -//} -// -//func (s *ethSigner) signNewValsetUpdates( -// ctx context.Context, -// injective InjectiveNetwork, -//) error { -// oldestUnsignedValsets, err := s.getUnsignedValsets(ctx, injective) -// if err != nil { -// return err -// } -// -// if len(oldestUnsignedValsets) == 0 { -// s.log.Debugln("no valset updates to confirm") -// return nil -// } -// -// for _, vs := range oldestUnsignedValsets { -// if err := s.signValset(ctx, injective, vs); err != nil { -// return err -// } -// } -// -// return nil -//} -// -//func (s *ethSigner) getUnsignedValsets(ctx context.Context, injective InjectiveNetwork) ([]*types.Valset, error) { -// var oldestUnsignedValsets []*types.Valset -// retryFn := func() (err error) { -// oldestUnsignedValsets, err = injective.OldestUnsignedValsets(ctx) -// if err == cosmos.ErrNotFound || oldestUnsignedValsets == nil { -// return nil -// } -// -// return err -// } -// -// if err := retry.Do(retryFn, -// retry.Context(ctx), -// retry.Attempts(s.retries), -// retry.OnRetry(func(n uint, err error) { -// s.log.WithError(err).Warningf("failed to get unconfirmed valset updates, will retry (%d)", n) -// }), -// ); err != nil { -// s.log.WithError(err).Errorln("got error, loop exits") -// return nil, err -// } -// -// return oldestUnsignedValsets, nil -//} -// -//func (s *ethSigner) signValset( -// ctx context.Context, -// injective InjectiveNetwork, -// vs *types.Valset, -//) error { -// if err := retry.Do( -// func() error { return injective.SendValsetConfirm(ctx, s.peggyID, vs, s.ethFrom) }, -// retry.Context(ctx), -// retry.Attempts(s.retries), -// retry.OnRetry(func(n uint, err error) { -// s.log.WithError(err).Warningf("failed to confirm valset update on Injective, will retry (%d)", n) -// }), -// ); err != nil { -// s.log.WithError(err).Errorln("got error, loop exits") -// return err -// } -// -// s.log.WithField("valset_nonce", vs.Nonce).Infoln("confirmed valset update on Injective") -// -// return nil -//} From c21129e7afa6774267dc724171a44e70d72ff388 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Fri, 22 Dec 2023 11:57:26 +0100 Subject: [PATCH 13/35] refactor definitions --- orchestrator/batch_request.go | 2 +- orchestrator/ethereum.go | 39 +++++++++++++++ orchestrator/injective.go | 40 ++++++++++++++++ orchestrator/oracle.go | 6 +-- orchestrator/oracle_test.go | 2 +- orchestrator/orchestrator.go | 90 ++++------------------------------- orchestrator/price_feed.go | 8 ++++ orchestrator/relayer.go | 2 +- orchestrator/signer.go | 6 +-- orchestrator/signer_test.go | 2 +- 10 files changed, 105 insertions(+), 92 deletions(-) create mode 100644 orchestrator/ethereum.go create mode 100644 orchestrator/injective.go create mode 100644 orchestrator/price_feed.go diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index 145a5c3a..1e8c1079 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -20,7 +20,7 @@ func (s *PeggyOrchestrator) BatchRequesterLoop(ctx context.Context) (err error) loopDuration: defaultLoopDur, } - return loop.Run(ctx, s.injective, s.pricefeed) + return loop.Run(ctx, s.inj, s.pricefeed) } type batchRequestLoop struct { diff --git a/orchestrator/ethereum.go b/orchestrator/ethereum.go new file mode 100644 index 00000000..c35ad852 --- /dev/null +++ b/orchestrator/ethereum.go @@ -0,0 +1,39 @@ +package orchestrator + +import ( + "context" + "math/big" + + eth "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + + peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" + peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" +) + +// EthereumNetwork is the orchestrator's reference endpoint to the Ethereum network +type EthereumNetwork interface { + FromAddress() eth.Address + HeaderByNumber(ctx context.Context, number *big.Int) (*ethtypes.Header, error) + GetPeggyID(ctx context.Context) (eth.Hash, error) + + GetSendToCosmosEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggySendToCosmosEvent, error) + GetSendToInjectiveEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggySendToInjectiveEvent, error) + GetPeggyERC20DeployedEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggyERC20DeployedEvent, error) + GetValsetUpdatedEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggyValsetUpdatedEvent, error) + GetTransactionBatchExecutedEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggyTransactionBatchExecutedEvent, error) + + GetValsetNonce(ctx context.Context) (*big.Int, error) + SendEthValsetUpdate(ctx context.Context, + oldValset *peggytypes.Valset, + newValset *peggytypes.Valset, + confirms []*peggytypes.MsgValsetConfirm, + ) (*eth.Hash, error) + + GetTxBatchNonce(ctx context.Context, erc20ContractAddress eth.Address) (*big.Int, error) + SendTransactionBatch(ctx context.Context, + currentValset *peggytypes.Valset, + batch *peggytypes.OutgoingTxBatch, + confirms []*peggytypes.MsgConfirmBatch, + ) (*eth.Hash, error) +} diff --git a/orchestrator/injective.go b/orchestrator/injective.go new file mode 100644 index 00000000..fda9cb67 --- /dev/null +++ b/orchestrator/injective.go @@ -0,0 +1,40 @@ +package orchestrator + +import ( + "context" + "time" + + eth "github.com/ethereum/go-ethereum/common" + + peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" + peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" +) + +// InjectiveNetwork is the orchestrator's reference endpoint to the Injective network +type InjectiveNetwork interface { + PeggyParams(ctx context.Context) (*peggytypes.Params, error) + GetBlockCreationTime(ctx context.Context, height int64) (time.Time, error) + + LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) + SendEthereumClaims(ctx context.Context, + lastClaimEvent uint64, + oldDeposits []*peggyevents.PeggySendToCosmosEvent, + deposits []*peggyevents.PeggySendToInjectiveEvent, + withdraws []*peggyevents.PeggyTransactionBatchExecutedEvent, + erc20Deployed []*peggyevents.PeggyERC20DeployedEvent, + valsetUpdates []*peggyevents.PeggyValsetUpdatedEvent, + ) error + + UnbatchedTokenFees(ctx context.Context) ([]*peggytypes.BatchFees, error) + SendRequestBatch(ctx context.Context, denom string) error + OldestUnsignedTransactionBatch(ctx context.Context) (*peggytypes.OutgoingTxBatch, error) + SendBatchConfirm(ctx context.Context, peggyID eth.Hash, batch *peggytypes.OutgoingTxBatch, ethFrom eth.Address) error + LatestTransactionBatches(ctx context.Context) ([]*peggytypes.OutgoingTxBatch, error) + TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract eth.Address) ([]*peggytypes.MsgConfirmBatch, error) + + OldestUnsignedValsets(ctx context.Context) ([]*peggytypes.Valset, error) + SendValsetConfirm(ctx context.Context, peggyID eth.Hash, valset *peggytypes.Valset, ethFrom eth.Address) error + LatestValsets(ctx context.Context) ([]*peggytypes.Valset, error) + AllValsetConfirms(ctx context.Context, nonce uint64) ([]*peggytypes.MsgValsetConfirm, error) + ValsetAt(ctx context.Context, nonce uint64) (*peggytypes.Valset, error) +} diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index 67615041..c77a7d8c 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -37,13 +37,13 @@ func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { lastResyncWithInjective: time.Now(), } - return loop.Run(ctx, s.injective, s.ethereum) + return loop.Run(ctx, s.inj, s.eth) } func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Context) (uint64, error) { var lastConfirmedEthHeight uint64 getLastConfirmedEthHeightFn := func() error { - lastClaimEvent, err := s.injective.LastClaimEvent(ctx) + lastClaimEvent, err := s.inj.LastClaimEvent(ctx) if err == nil && lastClaimEvent != nil && lastClaimEvent.EthereumEventHeight != 0 { lastConfirmedEthHeight = lastClaimEvent.EthereumEventHeight return nil @@ -52,7 +52,7 @@ func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Con s.logger.WithError(err).Warningln("failed to get last claim from Injective. Querying peggy module params...") - peggyParams, err := s.injective.PeggyParams(ctx) + peggyParams, err := s.inj.PeggyParams(ctx) if err != nil { s.logger.WithError(err).Fatalln("failed to query peggy module params, is injectived running?") return err diff --git a/orchestrator/oracle_test.go b/orchestrator/oracle_test.go index c4f8ffed..a91e16a1 100644 --- a/orchestrator/oracle_test.go +++ b/orchestrator/oracle_test.go @@ -22,7 +22,7 @@ func TestEthOracle(t *testing.T) { t.Parallel() orch := &PeggyOrchestrator{ - ethereum: mockEthereum{ + eth: mockEthereum{ headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { return nil, errors.New("fail") }, diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index 41e27784..26cee586 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -2,98 +2,24 @@ package orchestrator import ( "context" - "math/big" "time" eth "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" log "github.com/xlab/suplog" "github.com/InjectiveLabs/metrics" "github.com/InjectiveLabs/peggo/orchestrator/loops" - peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" - peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" ) -type PriceFeed interface { - QueryUSDPrice(address eth.Address) (float64, error) -} - -type InjectiveNetwork interface { - PeggyParams(ctx context.Context) (*peggytypes.Params, error) - GetBlockCreationTime(ctx context.Context, height int64) (time.Time, error) - - // claims - LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) - SendEthereumClaims( - ctx context.Context, - lastClaimEvent uint64, - oldDeposits []*peggyevents.PeggySendToCosmosEvent, - deposits []*peggyevents.PeggySendToInjectiveEvent, - withdraws []*peggyevents.PeggyTransactionBatchExecutedEvent, - erc20Deployed []*peggyevents.PeggyERC20DeployedEvent, - valsetUpdates []*peggyevents.PeggyValsetUpdatedEvent, - ) error - - // batches - UnbatchedTokenFees(ctx context.Context) ([]*peggytypes.BatchFees, error) - SendRequestBatch(ctx context.Context, denom string) error - OldestUnsignedTransactionBatch(ctx context.Context) (*peggytypes.OutgoingTxBatch, error) - SendBatchConfirm(ctx context.Context, peggyID eth.Hash, batch *peggytypes.OutgoingTxBatch, ethFrom eth.Address) error - LatestTransactionBatches(ctx context.Context) ([]*peggytypes.OutgoingTxBatch, error) - TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract eth.Address) ([]*peggytypes.MsgConfirmBatch, error) - - // valsets - OldestUnsignedValsets(ctx context.Context) ([]*peggytypes.Valset, error) - SendValsetConfirm(ctx context.Context, peggyID eth.Hash, valset *peggytypes.Valset, ethFrom eth.Address) error - LatestValsets(ctx context.Context) ([]*peggytypes.Valset, error) - AllValsetConfirms(ctx context.Context, nonce uint64) ([]*peggytypes.MsgValsetConfirm, error) - ValsetAt(ctx context.Context, nonce uint64) (*peggytypes.Valset, error) -} - -type EthereumNetwork interface { - FromAddress() eth.Address - HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) - GetPeggyID(ctx context.Context) (eth.Hash, error) - - // events - GetSendToCosmosEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggySendToCosmosEvent, error) - GetSendToInjectiveEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggySendToInjectiveEvent, error) - GetPeggyERC20DeployedEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggyERC20DeployedEvent, error) - GetValsetUpdatedEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggyValsetUpdatedEvent, error) - GetTransactionBatchExecutedEvents(startBlock, endBlock uint64) ([]*peggyevents.PeggyTransactionBatchExecutedEvent, error) - - // valsets - GetValsetNonce(ctx context.Context) (*big.Int, error) - SendEthValsetUpdate( - ctx context.Context, - oldValset *peggytypes.Valset, - newValset *peggytypes.Valset, - confirms []*peggytypes.MsgValsetConfirm, - ) (*eth.Hash, error) - - // batches - GetTxBatchNonce( - ctx context.Context, - erc20ContractAddress eth.Address, - ) (*big.Int, error) - SendTransactionBatch( - ctx context.Context, - currentValset *peggytypes.Valset, - batch *peggytypes.OutgoingTxBatch, - confirms []*peggytypes.MsgConfirmBatch, - ) (*eth.Hash, error) -} - const defaultLoopDur = 60 * time.Second type PeggyOrchestrator struct { logger log.Logger svcTags metrics.Tags - injective InjectiveNetwork - ethereum EthereumNetwork + inj InjectiveNetwork + eth EthereumNetwork pricefeed PriceFeed erc20ContractMapping map[eth.Address]string @@ -118,11 +44,11 @@ func NewPeggyOrchestrator( valsetRelayingOffset, batchRelayingOffset string, ) (*PeggyOrchestrator, error) { - orch := &PeggyOrchestrator{ + o := &PeggyOrchestrator{ logger: log.DefaultLogger, svcTags: metrics.Tags{"svc": "peggy_orchestrator"}, - injective: injective, - ethereum: ethereum, + inj: injective, + eth: ethereum, pricefeed: priceFeed, erc20ContractMapping: erc20ContractMapping, minBatchFeeUSD: minBatchFeeUSD, @@ -137,7 +63,7 @@ func NewPeggyOrchestrator( return nil, errors.Wrapf(err, "valset relaying enabled but offset duration is not properly set") } - orch.relayValsetOffsetDur = dur + o.relayValsetOffsetDur = dur } if batchRelayingEnabled { @@ -146,10 +72,10 @@ func NewPeggyOrchestrator( return nil, errors.Wrapf(err, "batch relaying enabled but offset duration is not properly set") } - orch.relayBatchOffsetDur = dur + o.relayBatchOffsetDur = dur } - return orch, nil + return o, nil } // Run starts all major loops required to make diff --git a/orchestrator/price_feed.go b/orchestrator/price_feed.go new file mode 100644 index 00000000..2ff81c8c --- /dev/null +++ b/orchestrator/price_feed.go @@ -0,0 +1,8 @@ +package orchestrator + +import eth "github.com/ethereum/go-ethereum/common" + +// PriceFeed provides token price for a given contract address +type PriceFeed interface { + QueryUSDPrice(address eth.Address) (float64, error) +} diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index d8e492b9..e2ed9fa9 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -23,7 +23,7 @@ func (s *PeggyOrchestrator) RelayerMainLoop(ctx context.Context) (err error) { loopDuration: defaultLoopDur, } - return loop.Run(ctx, s.injective, s.ethereum) + return loop.Run(ctx, s.inj, s.eth) } type relayerLoop struct { diff --git a/orchestrator/signer.go b/orchestrator/signer.go index f02c09f3..69a83a46 100644 --- a/orchestrator/signer.go +++ b/orchestrator/signer.go @@ -27,16 +27,16 @@ func (s *PeggyOrchestrator) EthSignerMainLoop(ctx context.Context) error { PeggyOrchestrator: s, loopDuration: defaultLoopDur, peggyID: peggyID, - ethFrom: s.ethereum.FromAddress(), + ethFrom: s.eth.FromAddress(), } - return loop.Run(ctx, s.injective) + return loop.Run(ctx, s.inj) } func (s *PeggyOrchestrator) getPeggyID(ctx context.Context) (common.Hash, error) { var peggyID common.Hash getPeggyIDFn := func() (err error) { - peggyID, err = s.ethereum.GetPeggyID(ctx) + peggyID, err = s.eth.GetPeggyID(ctx) return err } diff --git a/orchestrator/signer_test.go b/orchestrator/signer_test.go index c0c8bd05..286b871b 100644 --- a/orchestrator/signer_test.go +++ b/orchestrator/signer_test.go @@ -21,7 +21,7 @@ func TestEthSignerLoop(t *testing.T) { orch := &PeggyOrchestrator{ maxAttempts: 1, - ethereum: mockEthereum{ + eth: mockEthereum{ getPeggyIDFn: func(context.Context) (common.Hash, error) { return [32]byte{}, errors.New("fail") }, From 68631a0f3e94ad9c542ed02c1c3ad2c3f5b4dc32 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Fri, 22 Dec 2023 13:11:32 +0100 Subject: [PATCH 14/35] set defaultRelayerLoopDur to 5min like on mainnet/testnet --- orchestrator/relayer.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index e2ed9fa9..c86ebee5 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -5,7 +5,6 @@ import ( "sort" "time" - "github.com/InjectiveLabs/sdk-go/chain/peggy/types" "github.com/avast/retry-go" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" @@ -15,12 +14,18 @@ import ( "github.com/InjectiveLabs/peggo/orchestrator/ethereum/util" "github.com/InjectiveLabs/peggo/orchestrator/loops" wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" + "github.com/InjectiveLabs/sdk-go/chain/peggy/types" +) + +const ( + defaultRelayerLoopDur = 5 * time.Minute + findValsetBlocksToSearch = 2000 ) func (s *PeggyOrchestrator) RelayerMainLoop(ctx context.Context) (err error) { loop := relayerLoop{ PeggyOrchestrator: s, - loopDuration: defaultLoopDur, + loopDuration: defaultRelayerLoopDur, } return loop.Run(ctx, s.inj, s.eth) @@ -45,8 +50,7 @@ func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, et if l.valsetRelayEnabled { pg.Go(func() error { - return retry.Do( - func() error { return l.relayValsets(ctx, injective, ethereum) }, + return retry.Do(func() error { return l.relayValsets(ctx, injective, ethereum) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -58,8 +62,7 @@ func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, et if l.batchRelayEnabled { pg.Go(func() error { - return retry.Do( - func() error { return l.relayBatches(ctx, injective, ethereum) }, + return retry.Do(func() error { return l.relayBatches(ctx, injective, ethereum) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -249,8 +252,6 @@ func (l *relayerLoop) relayValsets(ctx context.Context, injective InjectiveNetwo return nil } -const valsetBlocksToSearch = 2000 - // FindLatestValset finds the latest valset on the Peggy contract by looking back through the event // history and finding the most recent ValsetUpdatedEvent. Most of the time this will be very fast // as the latest update will be in recent blockchain history and the search moves from the present @@ -276,14 +277,12 @@ func (l *relayerLoop) findLatestValsetOnEth(ctx context.Context, injective Injec for currentBlock > 0 { var startSearchBlock uint64 - if currentBlock <= valsetBlocksToSearch { + if currentBlock <= findValsetBlocksToSearch { startSearchBlock = 0 } else { - startSearchBlock = currentBlock - valsetBlocksToSearch + startSearchBlock = currentBlock - findValsetBlocksToSearch } - l.Logger().WithFields(log.Fields{"block_start": startSearchBlock, "block_end": currentBlock}).Debugln("looking for the most recent ValsetUpdatedEvent on Ethereum") - valsetUpdatedEvents, err := ethereum.GetValsetUpdatedEvents(startSearchBlock, currentBlock) if err != nil { return nil, errors.Wrap(err, "failed to filter past ValsetUpdated events from Ethereum") From 914a8376b9f83cc5ef559255823727150b43b5ef Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Fri, 22 Dec 2023 14:04:16 +0100 Subject: [PATCH 15/35] fix logging in batch_request; add todo --- orchestrator/batch_request.go | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index 1e8c1079..92f68c76 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -41,19 +41,19 @@ func (l *batchRequestLoop) loopFn(ctx context.Context, injective InjectiveNetwor fees, err := l.getUnbatchedTokenFees(ctx, injective) if err != nil { // non-fatal, just alert - l.Logger().WithError(err).Warningln("unable to get unbatched fees from Injective") + l.Logger().WithError(err).Warningln("unable to get outgoing withdrawal fees") return nil } if len(fees) == 0 { - l.Logger().Debugln("no token fees to batch") + l.Logger().Debugln("no outgoing withdrawals to batch") return nil } for _, fee := range fees { l.requestBatch(ctx, injective, priceFeed, fee) - // todo: in case of multiple tokens, we should sleep in between batch requests (non-continuous nonce) + // todo: in case of multiple requests, we should sleep in between (non-continuous nonce) } return nil @@ -71,7 +71,7 @@ func (l *batchRequestLoop) getUnbatchedTokenFees(ctx context.Context, injective retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { - l.Logger().WithError(err).Errorf("failed to get unbatched token fees, will retry (%d)", n) + l.Logger().WithError(err).Errorf("failed to get outgoing withdrawal fees, will retry (%d)", n) }), ); err != nil { return nil, err @@ -87,22 +87,17 @@ func (l *batchRequestLoop) requestBatch( fee *types.BatchFees, ) { var ( - tokenAddr = eth.HexToAddress(fee.Token) - denom = l.tokenDenom(tokenAddr) + tokenAddr = eth.HexToAddress(fee.Token) + tokenDenom = l.tokenDenom(tokenAddr) ) if thresholdMet := l.checkFeeThreshold(feed, tokenAddr, fee.TotalFees); !thresholdMet { - l.Logger().WithFields(log.Fields{ - "denom": denom, - "token_contract": tokenAddr.String(), - "total_fees": fee.TotalFees.String(), - }).Debugln("skipping underpriced batch") return } - l.Logger().WithFields(log.Fields{"denom": denom, "token_contract": tokenAddr.String()}).Infoln("requesting batch on Injective") + l.Logger().WithFields(log.Fields{"denom": tokenDenom, "token_contract": tokenAddr.String()}).Infoln("requesting batch on Injective") - _ = injective.SendRequestBatch(ctx, denom) + _ = injective.SendRequestBatch(ctx, tokenDenom) } func (l *batchRequestLoop) tokenDenom(tokenAddr eth.Address) string { @@ -111,6 +106,8 @@ func (l *batchRequestLoop) tokenDenom(tokenAddr eth.Address) string { } // peggy denom + // todo: in reality, peggy denominators don't have an actual price listing + // So it seems that bridge fee must always be inj return types.PeggyDenomString(tokenAddr) } @@ -129,6 +126,11 @@ func (l *batchRequestLoop) checkFeeThreshold(feed PriceFeed, tokenAddr eth.Addre totalFeeInUSDDec := decimal.NewFromBigInt(fees.BigInt(), -18).Mul(tokenPriceInUSDDec) if totalFeeInUSDDec.LessThan(minFeeInUSDDec) { + l.Logger().WithFields(log.Fields{ + "token_contract": tokenAddr.String(), + "batch_fees": totalFeeInUSDDec.String(), + "min_fees": minFeeInUSDDec.String(), + }).Debugln("skipping insufficient token fees") return false } From 05b869d5d31588368a3eb54a7513dc932a4613d1 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Fri, 22 Dec 2023 14:33:41 +0100 Subject: [PATCH 16/35] fix oracle logs --- orchestrator/cosmos/broadcast.go | 54 ++++++++++++++++---------------- orchestrator/oracle.go | 7 +++-- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/orchestrator/cosmos/broadcast.go b/orchestrator/cosmos/broadcast.go index b998af99..9d4ae931 100644 --- a/orchestrator/cosmos/broadcast.go +++ b/orchestrator/cosmos/broadcast.go @@ -255,7 +255,7 @@ func (s *peggyBroadcastClient) sendOldDepositClaims( "destination": sdk.AccAddress(oldDeposit.Destination[12:32]).String(), "amount": oldDeposit.Amount.String(), "event_nonce": oldDeposit.EventNonce.String(), - }).Infoln("Oracle observed old deposit event. Sending MsgDepositClaim") + }).Debugln("observed SendToCosmos event. Sending MsgDepositClaim...") msg := &types.MsgDepositClaim{ EventNonce: oldDeposit.EventNonce.Uint64(), @@ -275,7 +275,7 @@ func (s *peggyBroadcastClient) sendOldDepositClaims( } else { log.WithFields(log.Fields{ "event_nonce": oldDeposit.EventNonce.String(), - "txHash": txResponse.TxResponse.TxHash, + "tx_hash": txResponse.TxResponse.TxHash, }).Infoln("Oracle sent old deposit event successfully") } @@ -301,7 +301,7 @@ func (s *peggyBroadcastClient) sendDepositClaims( "amount": deposit.Amount.String(), "event_nonce": deposit.EventNonce.String(), "data": deposit.Data, - }).Infoln("Oracle observed a deposit event. Sending MsgDepositClaim") + }).Debugln("observed SendToInjective event. Sending MsgDepositClaim...") msg := &types.MsgDepositClaim{ EventNonce: deposit.EventNonce.Uint64(), @@ -321,7 +321,7 @@ func (s *peggyBroadcastClient) sendDepositClaims( } else { log.WithFields(log.Fields{ "event_nonce": deposit.EventNonce.String(), - "txHash": txResponse.TxResponse.TxHash, + "tx_hash": txResponse.TxResponse.TxHash, }).Infoln("Oracle sent deposit event successfully") } @@ -340,7 +340,7 @@ func (s *peggyBroadcastClient) sendWithdrawClaims( "nonce": withdraw.BatchNonce.String(), "token_contract": withdraw.Token.Hex(), "event_nonce": withdraw.EventNonce.String(), - }).Infoln("Oracle observed a withdraw batch event. Sending MsgWithdrawClaim") + }).Debugln("observed TransactionBatchExecuted event. Sending MsgWithdrawClaim...") // WithdrawClaim claims that a batch of withdrawal // operations on the bridge contract was executed. @@ -359,8 +359,8 @@ func (s *peggyBroadcastClient) sendWithdrawClaims( } else { log.WithFields(log.Fields{ "event_nonce": withdraw.EventNonce.String(), - "txHash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent Withdraw event successfully") + "tx_hash": txResponse.TxResponse.TxHash, + }).Infoln("Oracle sent withdraw event successfully") } return nil @@ -375,13 +375,13 @@ func (s *peggyBroadcastClient) sendValsetUpdateClaims( defer doneFn() log.WithFields(log.Fields{ - "EventNonce": valsetUpdate.EventNonce.Uint64(), - "ValsetNonce": valsetUpdate.NewValsetNonce.Uint64(), - "_validators": valsetUpdate.Validators, - "_powers": valsetUpdate.Powers, - "rewardAmount": valsetUpdate.RewardAmount, - "rewardToken": valsetUpdate.RewardToken.Hex(), - }).Infoln("Oracle observed a valsetUpdate event. Sending MsgValsetUpdatedClaim") + "event_nonce": valsetUpdate.EventNonce.Uint64(), + "valset_nonce": valsetUpdate.NewValsetNonce.Uint64(), + "validators": valsetUpdate.Validators, + "powers": valsetUpdate.Powers, + "reward_amount": valsetUpdate.RewardAmount, + "reward_token": valsetUpdate.RewardToken.Hex(), + }).Debugln("observed ValsetUpdatedEvent event. Sending MsgValsetUpdatedClaim...") members := make([]*types.BridgeValidator, len(valsetUpdate.Validators)) for i, val := range valsetUpdate.Validators { @@ -408,8 +408,8 @@ func (s *peggyBroadcastClient) sendValsetUpdateClaims( } else { log.WithFields(log.Fields{ "event_nonce": valsetUpdate.EventNonce.String(), - "txHash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent ValsetUpdate event successfully") + "tx_hash": txResponse.TxResponse.TxHash, + }).Infoln("Oracle sent valset update event successfully") } return nil @@ -424,13 +424,13 @@ func (s *peggyBroadcastClient) sendErc20DeployedClaims( defer doneFn() log.WithFields(log.Fields{ - "EventNonce": erc20Deployed.EventNonce.Uint64(), - "CosmosDenom": erc20Deployed.CosmosDenom, - "TokenContract": erc20Deployed.TokenContract.Hex(), - "Name": erc20Deployed.Name, - "Symbol": erc20Deployed.Symbol, - "Decimals": erc20Deployed.Decimals, - }).Infoln("Oracle observed a erc20Deployed event. Sending MsgERC20DeployedClaim") + "event_nonce": erc20Deployed.EventNonce.Uint64(), + "cosmos_denom": erc20Deployed.CosmosDenom, + "token_contract": erc20Deployed.TokenContract.Hex(), + "name": erc20Deployed.Name, + "symbol": erc20Deployed.Symbol, + "decimals": erc20Deployed.Decimals, + }).Debugln("observed ERC20Deployed event. Sending MsgERC20DeployedClaim...") msg := &types.MsgERC20DeployedClaim{ EventNonce: erc20Deployed.EventNonce.Uint64(), @@ -450,8 +450,8 @@ func (s *peggyBroadcastClient) sendErc20DeployedClaims( } else { log.WithFields(log.Fields{ "event_nonce": erc20Deployed.EventNonce.String(), - "txHash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent ERC20DeployedEvent event successfully") + "tx_hash": txResponse.TxResponse.TxHash, + }).Infoln("Oracle sent erc20 deployed event successfully") } return nil @@ -521,10 +521,10 @@ func (s *peggyBroadcastClient) SendEthereumClaims( count = count + 1 lastClaimEvent = lastClaimEvent + 1 - // Considering blockTime=2.8s on Injective chain, Adding Sleep to make sure new event is + // Considering blockTime=1s on Injective chain, Adding Sleep to make sure new event is // sent only after previous event is executed successfully. // Otherwise it will through `non contiguous event nonce` failing CheckTx. - time.Sleep(3 * time.Second) + time.Sleep(1200 * time.Millisecond) } return nil } diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index c77a7d8c..0b64f77a 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -12,6 +12,7 @@ import ( wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" ) +// todo: this is outdated, need to update // Considering blocktime of up to 3 seconds approx on the Injective Chain and an oracle loop duration = 1 minute, // we broadcast only 20 events in each iteration. // So better to search only 20 blocks to ensure all the events are broadcast to Injective Chain without misses. @@ -28,7 +29,7 @@ func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { return err } - s.logger.Debugln("scanning Ethereum events from block", lastConfirmedEthHeight) + s.logger.Debugln("last observed ethereum block", lastConfirmedEthHeight) loop := ethOracleLoop{ PeggyOrchestrator: s, @@ -50,11 +51,11 @@ func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Con } - s.logger.WithError(err).Warningln("failed to get last claim from Injective. Querying peggy module params...") + s.logger.WithError(err).Warningln("unable to get last event claim from Injective. Querying Peggy module params...") peggyParams, err := s.inj.PeggyParams(ctx) if err != nil { - s.logger.WithError(err).Fatalln("failed to query peggy module params, is injectived running?") + s.logger.WithError(err).Fatalln("unable to query peggy module params, is injectived running?") return err } From dc174106641b30e88ebe53fe78059a0c4999bc6d Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Fri, 22 Dec 2023 15:41:33 +0100 Subject: [PATCH 17/35] fix relayer logs --- orchestrator/relayer.go | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index c86ebee5..683d845a 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -50,7 +50,7 @@ func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, et if l.valsetRelayEnabled { pg.Go(func() error { - return retry.Do(func() error { return l.relayValsets(ctx, injective, ethereum) }, + return retry.Do(func() error { return l.relayValset(ctx, injective, ethereum) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -62,7 +62,7 @@ func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, et if l.batchRelayEnabled { pg.Go(func() error { - return retry.Do(func() error { return l.relayBatches(ctx, injective, ethereum) }, + return retry.Do(func() error { return l.relayBatch(ctx, injective, ethereum) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -83,7 +83,7 @@ func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, et } } -func (l *relayerLoop) relayBatches(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { +func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { latestBatches, err := injective.LatestTransactionBatches(ctx) if err != nil { return err @@ -111,10 +111,7 @@ func (l *relayerLoop) relayBatches(ctx context.Context, injective InjectiveNetwo return nil } - latestEthereumBatch, err := ethereum.GetTxBatchNonce( - ctx, - common.HexToAddress(oldestConfirmedBatch.TokenContract), - ) + latestEthereumBatch, err := ethereum.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) if err != nil { return err } @@ -126,8 +123,6 @@ func (l *relayerLoop) relayBatches(ctx context.Context, injective InjectiveNetwo return errors.Wrap(err, "latest valset not found") } - l.Logger().WithFields(log.Fields{"inj_batch": oldestConfirmedBatch.BatchNonce, "eth_batch": latestEthereumBatch.Uint64()}).Debugln("latest batches") - if oldestConfirmedBatch.BatchNonce <= latestEthereumBatch.Uint64() { return nil } @@ -155,9 +150,8 @@ func (l *relayerLoop) relayBatches(ctx context.Context, injective InjectiveNetwo } l.Logger().WithFields(log.Fields{ - "inj_batch": oldestConfirmedBatch.BatchNonce, - "eth_batch": latestEthereumBatch.Uint64(), - "token_contract": common.HexToAddress(oldestConfirmedBatch.TokenContract), + "inj_batch_nonce": oldestConfirmedBatch.BatchNonce, + "eth_batch_nonce": latestEthereumBatch.Uint64(), }).Infoln("detected new batch on Injective") // Send SendTransactionBatch to Ethereum @@ -171,7 +165,7 @@ func (l *relayerLoop) relayBatches(ctx context.Context, injective InjectiveNetwo return nil } -func (l *relayerLoop) relayValsets(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { +func (l *relayerLoop) relayValset(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { // we should determine if we need to relay one // to Ethereum for that we will find the latest confirmed valset and compare it to the ethereum chain latestValsets, err := injective.LatestValsets(ctx) @@ -207,8 +201,6 @@ func (l *relayerLoop) relayValsets(ctx context.Context, injective InjectiveNetwo return errors.Wrap(err, "failed to find latest confirmed valset update on Ethereum") } - l.Logger().WithFields(log.Fields{"inj_valset": oldestConfirmedValset, "eth_valset": currentEthValset}).Debugln("latest valset updates") - if oldestConfirmedValset.Nonce <= currentEthValset.Nonce { return nil } @@ -230,12 +222,15 @@ func (l *relayerLoop) relayValsets(ctx context.Context, injective InjectiveNetwo } if timeElapsed := time.Since(blockTime); timeElapsed <= l.relayValsetOffsetDur { - timeRemaining := time.Duration(int64(l.relayBatchOffsetDur) - int64(timeElapsed)) + timeRemaining := time.Duration(int64(l.relayValsetOffsetDur) - int64(timeElapsed)) l.Logger().WithField("time_remaining", timeRemaining.String()).Debugln("valset relay offset duration not expired") return nil } - l.Logger().WithFields(log.Fields{"inj_valset": oldestConfirmedValset.Nonce, "eth_valset": latestEthereumValsetNonce.Uint64()}).Infoln("detected new valset on Injective") + l.Logger().WithFields(log.Fields{ + "inj_valset_nonce": oldestConfirmedValset.Nonce, + "eth_valset_nonce": latestEthereumValsetNonce.Uint64()}, + ).Infoln("detected new valset on Injective") txHash, err := ethereum.SendEthValsetUpdate( ctx, From ef230bd7553868c0d780569ed041b15e5efaca46 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Tue, 26 Dec 2023 12:06:44 +0100 Subject: [PATCH 18/35] reintroduce metrics in some methods --- orchestrator/batch_request.go | 6 ++-- orchestrator/oracle.go | 57 ++++++++++++++++++++--------------- orchestrator/relayer.go | 9 ++++++ 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index 92f68c76..eccbb26b 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -128,9 +128,9 @@ func (l *batchRequestLoop) checkFeeThreshold(feed PriceFeed, tokenAddr eth.Addre if totalFeeInUSDDec.LessThan(minFeeInUSDDec) { l.Logger().WithFields(log.Fields{ "token_contract": tokenAddr.String(), - "batch_fees": totalFeeInUSDDec.String(), - "min_fees": minFeeInUSDDec.String(), - }).Debugln("skipping insufficient token fees") + "batch_fee": totalFeeInUSDDec.String(), + "min_fee": minFeeInUSDDec.String(), + }).Debugln("insufficient token batch fee") return false } diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index 0b64f77a..e292babb 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" log "github.com/xlab/suplog" + "github.com/InjectiveLabs/metrics" "github.com/InjectiveLabs/peggo/orchestrator/loops" wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" ) @@ -43,24 +44,18 @@ func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Context) (uint64, error) { var lastConfirmedEthHeight uint64 - getLastConfirmedEthHeightFn := func() error { - lastClaimEvent, err := s.inj.LastClaimEvent(ctx) - if err == nil && lastClaimEvent != nil && lastClaimEvent.EthereumEventHeight != 0 { - lastConfirmedEthHeight = lastClaimEvent.EthereumEventHeight - return nil - - } - - s.logger.WithError(err).Warningln("unable to get last event claim from Injective. Querying Peggy module params...") + getLastConfirmedEthHeightFn := func() (err error) { + lastConfirmedEthHeight, err = s.getLastClaimBlockHeight(ctx) + if lastConfirmedEthHeight == 0 { + peggyParams, err := s.inj.PeggyParams(ctx) + if err != nil { + s.logger.WithError(err).Fatalln("unable to query peggy module params, is injectived running?") + return err + } - peggyParams, err := s.inj.PeggyParams(ctx) - if err != nil { - s.logger.WithError(err).Fatalln("unable to query peggy module params, is injectived running?") - return err + lastConfirmedEthHeight = peggyParams.BridgeContractStartHeight } - - lastConfirmedEthHeight = peggyParams.BridgeContractStartHeight - return nil + return } if err := retry.Do(getLastConfirmedEthHeightFn, @@ -77,6 +72,19 @@ func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Con return lastConfirmedEthHeight, nil } +func (s *PeggyOrchestrator) getLastClaimBlockHeight(ctx context.Context) (uint64, error) { + metrics.ReportFuncCall(s.svcTags) + doneFn := metrics.ReportFuncTiming(s.svcTags) + defer doneFn() + + claim, err := s.inj.LastClaimEvent(ctx) + if err != nil { + return 0, err + } + + return claim.EthereumEventHeight, nil +} + type ethOracleLoop struct { *PeggyOrchestrator loopDuration time.Duration @@ -126,6 +134,10 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetw ) scanEthBlocksAndRelayEventsFn := func() error { + metrics.ReportFuncCall(l.svcTags) + doneFn := metrics.ReportFuncTiming(l.svcTags) + defer doneFn() + latestHeader, err := ethereum.HeaderByNumber(ctx, nil) if err != nil { return errors.Wrap(err, "failed to get latest ethereum header") @@ -231,14 +243,9 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetw func (l *ethOracleLoop) autoResync(ctx context.Context, injective InjectiveNetwork) error { var latestHeight uint64 - getLastClaimEventFn := func() error { - lastClaimEvent, err := injective.LastClaimEvent(ctx) - if err != nil { - return err - } - - latestHeight = lastClaimEvent.EthereumEventHeight - return nil + getLastClaimEventFn := func() (err error) { + latestHeight, err = l.getLastClaimBlockHeight(ctx) + return } if err := retry.Do(getLastClaimEventFn, @@ -255,7 +262,7 @@ func (l *ethOracleLoop) autoResync(ctx context.Context, injective InjectiveNetwo l.lastCheckedEthHeight = latestHeight l.lastResyncWithInjective = time.Now() - l.Logger().WithFields(log.Fields{"last_resync_time": l.lastResyncWithInjective.String(), "last_confirmed_eth_height": l.lastCheckedEthHeight}).Infoln("auto resync nonce with Injective") + l.Logger().WithFields(log.Fields{"last_resync_time": l.lastResyncWithInjective.String(), "last_confirmed_eth_height": l.lastCheckedEthHeight}).Infoln("auto resync event nonce with Injective") return nil } diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index 683d845a..209584ce 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" log "github.com/xlab/suplog" + "github.com/InjectiveLabs/metrics" "github.com/InjectiveLabs/peggo/orchestrator/ethereum/util" "github.com/InjectiveLabs/peggo/orchestrator/loops" wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" @@ -84,6 +85,10 @@ func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, et } func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { + metrics.ReportFuncCall(l.svcTags) + doneFn := metrics.ReportFuncTiming(l.svcTags) + defer doneFn() + latestBatches, err := injective.LatestTransactionBatches(ctx) if err != nil { return err @@ -166,6 +171,10 @@ func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork } func (l *relayerLoop) relayValset(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { + metrics.ReportFuncCall(l.svcTags) + doneFn := metrics.ReportFuncTiming(l.svcTags) + defer doneFn() + // we should determine if we need to relay one // to Ethereum for that we will find the latest confirmed valset and compare it to the ethereum chain latestValsets, err := injective.LatestValsets(ctx) From 9cea34187d604d6d4ded16a41533a7b8cddaa79b Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Tue, 26 Dec 2023 12:22:23 +0100 Subject: [PATCH 19/35] remove redundant method params --- orchestrator/batch_request.go | 27 ++++++++----------- orchestrator/oracle.go | 32 +++++++++++----------- orchestrator/relayer.go | 47 +++++++++++++++----------------- orchestrator/signer.go | 51 +++++++++++++++-------------------- 4 files changed, 71 insertions(+), 86 deletions(-) diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index eccbb26b..340374bc 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -20,7 +20,7 @@ func (s *PeggyOrchestrator) BatchRequesterLoop(ctx context.Context) (err error) loopDuration: defaultLoopDur, } - return loop.Run(ctx, s.inj, s.pricefeed) + return loop.Run(ctx) } type batchRequestLoop struct { @@ -32,13 +32,13 @@ func (l *batchRequestLoop) Logger() log.Logger { return l.logger.WithField("loop", "BatchRequest") } -func (l *batchRequestLoop) Run(ctx context.Context, injective InjectiveNetwork, priceFeed PriceFeed) error { - return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective, priceFeed)) +func (l *batchRequestLoop) Run(ctx context.Context) error { + return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx)) } -func (l *batchRequestLoop) loopFn(ctx context.Context, injective InjectiveNetwork, priceFeed PriceFeed) func() error { +func (l *batchRequestLoop) loopFn(ctx context.Context) func() error { return func() error { - fees, err := l.getUnbatchedTokenFees(ctx, injective) + fees, err := l.getUnbatchedTokenFees(ctx) if err != nil { // non-fatal, just alert l.Logger().WithError(err).Warningln("unable to get outgoing withdrawal fees") @@ -51,7 +51,7 @@ func (l *batchRequestLoop) loopFn(ctx context.Context, injective InjectiveNetwor } for _, fee := range fees { - l.requestBatch(ctx, injective, priceFeed, fee) + l.requestBatch(ctx, fee) // todo: in case of multiple requests, we should sleep in between (non-continuous nonce) } @@ -60,10 +60,10 @@ func (l *batchRequestLoop) loopFn(ctx context.Context, injective InjectiveNetwor } } -func (l *batchRequestLoop) getUnbatchedTokenFees(ctx context.Context, injective InjectiveNetwork) ([]*types.BatchFees, error) { +func (l *batchRequestLoop) getUnbatchedTokenFees(ctx context.Context) ([]*types.BatchFees, error) { var unbatchedFees []*types.BatchFees getUnbatchedTokenFeesFn := func() (err error) { - unbatchedFees, err = injective.UnbatchedTokenFees(ctx) + unbatchedFees, err = l.inj.UnbatchedTokenFees(ctx) return err } @@ -80,24 +80,19 @@ func (l *batchRequestLoop) getUnbatchedTokenFees(ctx context.Context, injective return unbatchedFees, nil } -func (l *batchRequestLoop) requestBatch( - ctx context.Context, - injective InjectiveNetwork, - feed PriceFeed, - fee *types.BatchFees, -) { +func (l *batchRequestLoop) requestBatch(ctx context.Context, fee *types.BatchFees) { var ( tokenAddr = eth.HexToAddress(fee.Token) tokenDenom = l.tokenDenom(tokenAddr) ) - if thresholdMet := l.checkFeeThreshold(feed, tokenAddr, fee.TotalFees); !thresholdMet { + if thresholdMet := l.checkFeeThreshold(l.pricefeed, tokenAddr, fee.TotalFees); !thresholdMet { return } l.Logger().WithFields(log.Fields{"denom": tokenDenom, "token_contract": tokenAddr.String()}).Infoln("requesting batch on Injective") - _ = injective.SendRequestBatch(ctx, tokenDenom) + _ = l.inj.SendRequestBatch(ctx, tokenDenom) } func (l *batchRequestLoop) tokenDenom(tokenAddr eth.Address) string { diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index e292babb..a60dc58f 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -39,7 +39,7 @@ func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { lastResyncWithInjective: time.Now(), } - return loop.Run(ctx, s.inj, s.eth) + return loop.Run(ctx) } func (s *PeggyOrchestrator) getLastConfirmedEthHeightOnInjective(ctx context.Context) (uint64, error) { @@ -96,13 +96,13 @@ func (l *ethOracleLoop) Logger() log.Logger { return l.logger.WithField("loop", "EthOracle") } -func (l *ethOracleLoop) Run(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { - return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective, ethereum)) +func (l *ethOracleLoop) Run(ctx context.Context) error { + return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx)) } -func (l *ethOracleLoop) loopFn(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) func() error { +func (l *ethOracleLoop) loopFn(ctx context.Context) func() error { return func() error { - newHeight, err := l.relayEvents(ctx, injective, ethereum) + newHeight, err := l.relayEvents(ctx) if err != nil { return err } @@ -118,7 +118,7 @@ func (l *ethOracleLoop) loopFn(ctx context.Context, injective InjectiveNetwork, 2. if validator was in UnBonding state, the claims broadcasted in last iteration are failed. 3. if infura call failed while filtering events, the peggo missed to broadcast claim events occured in last iteration. **/ - if err := l.autoResync(ctx, injective); err != nil { + if err := l.autoResync(ctx); err != nil { return err } } @@ -127,7 +127,7 @@ func (l *ethOracleLoop) loopFn(ctx context.Context, injective InjectiveNetwork, } } -func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) (uint64, error) { +func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { var ( latestHeight uint64 currentHeight = l.lastCheckedEthHeight @@ -138,7 +138,7 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetw doneFn := metrics.ReportFuncTiming(l.svcTags) defer doneFn() - latestHeader, err := ethereum.HeaderByNumber(ctx, nil) + latestHeader, err := l.eth.HeaderByNumber(ctx, nil) if err != nil { return errors.Wrap(err, "failed to get latest ethereum header") } @@ -153,27 +153,27 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetw latestHeight = currentHeight + defaultBlocksToSearch } - legacyDeposits, err := ethereum.GetSendToCosmosEvents(currentHeight, latestHeight) + legacyDeposits, err := l.eth.GetSendToCosmosEvents(currentHeight, latestHeight) if err != nil { return errors.Wrap(err, "failed to get SendToCosmos events") } - deposits, err := ethereum.GetSendToInjectiveEvents(currentHeight, latestHeight) + deposits, err := l.eth.GetSendToInjectiveEvents(currentHeight, latestHeight) if err != nil { return errors.Wrap(err, "failed to get SendToInjective events") } - withdrawals, err := ethereum.GetTransactionBatchExecutedEvents(currentHeight, latestHeight) + withdrawals, err := l.eth.GetTransactionBatchExecutedEvents(currentHeight, latestHeight) if err != nil { return errors.Wrap(err, "failed to get TransactionBatchExecuted events") } - erc20Deployments, err := ethereum.GetPeggyERC20DeployedEvents(currentHeight, latestHeight) + erc20Deployments, err := l.eth.GetPeggyERC20DeployedEvents(currentHeight, latestHeight) if err != nil { return errors.Wrap(err, "failed to get ERC20Deployed events") } - valsetUpdates, err := ethereum.GetValsetUpdatedEvents(currentHeight, latestHeight) + valsetUpdates, err := l.eth.GetValsetUpdatedEvents(currentHeight, latestHeight) if err != nil { return errors.Wrap(err, "failed to get ValsetUpdated events") } @@ -183,7 +183,7 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetw // block, so we also need this routine so make sure we don't send in the first event in this hypothetical // multi event block again. In theory we only send all events for every block and that will pass of fail // atomically but lets not take that risk. - lastClaimEvent, err := injective.LastClaimEvent(ctx) + lastClaimEvent, err := l.inj.LastClaimEvent(ctx) if err != nil { return errors.New("failed to query last claim event from Injective") } @@ -204,7 +204,7 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetw return nil } - if err := injective.SendEthereumClaims(ctx, + if err := l.inj.SendEthereumClaims(ctx, lastClaimEvent.EthereumEventNonce, legacyDeposits, deposits, @@ -241,7 +241,7 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context, injective InjectiveNetw return latestHeight, nil } -func (l *ethOracleLoop) autoResync(ctx context.Context, injective InjectiveNetwork) error { +func (l *ethOracleLoop) autoResync(ctx context.Context) error { var latestHeight uint64 getLastClaimEventFn := func() (err error) { latestHeight, err = l.getLastClaimBlockHeight(ctx) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index 209584ce..1a0c3933 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -29,7 +29,7 @@ func (s *PeggyOrchestrator) RelayerMainLoop(ctx context.Context) (err error) { loopDuration: defaultRelayerLoopDur, } - return loop.Run(ctx, s.inj, s.eth) + return loop.Run(ctx) } type relayerLoop struct { @@ -41,17 +41,17 @@ func (l *relayerLoop) Logger() log.Logger { return l.logger.WithField("loop", "Relayer") } -func (l *relayerLoop) Run(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { - return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective, ethereum)) +func (l *relayerLoop) Run(ctx context.Context) error { + return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx)) } -func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) func() error { +func (l *relayerLoop) loopFn(ctx context.Context) func() error { return func() error { var pg loops.ParanoidGroup if l.valsetRelayEnabled { pg.Go(func() error { - return retry.Do(func() error { return l.relayValset(ctx, injective, ethereum) }, + return retry.Do(func() error { return l.relayValset(ctx) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -63,7 +63,7 @@ func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, et if l.batchRelayEnabled { pg.Go(func() error { - return retry.Do(func() error { return l.relayBatch(ctx, injective, ethereum) }, + return retry.Do(func() error { return l.relayBatch(ctx) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -84,12 +84,12 @@ func (l *relayerLoop) loopFn(ctx context.Context, injective InjectiveNetwork, et } } -func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { +func (l *relayerLoop) relayBatch(ctx context.Context) error { metrics.ReportFuncCall(l.svcTags) doneFn := metrics.ReportFuncTiming(l.svcTags) defer doneFn() - latestBatches, err := injective.LatestTransactionBatches(ctx) + latestBatches, err := l.inj.LatestTransactionBatches(ctx) if err != nil { return err } @@ -100,7 +100,7 @@ func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork ) for _, batch := range latestBatches { - sigs, err := injective.TransactionBatchSignatures(ctx, batch.BatchNonce, common.HexToAddress(batch.TokenContract)) + sigs, err := l.inj.TransactionBatchSignatures(ctx, batch.BatchNonce, common.HexToAddress(batch.TokenContract)) if err != nil { return err } else if len(sigs) == 0 { @@ -116,12 +116,12 @@ func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork return nil } - latestEthereumBatch, err := ethereum.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) + latestEthereumBatch, err := l.eth.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) if err != nil { return err } - currentValset, err := l.findLatestValsetOnEth(ctx, injective, ethereum) + currentValset, err := l.findLatestValsetOnEth(ctx, l.inj, l.eth) if err != nil { return errors.Wrap(err, "failed to find latest valset") } else if currentValset == nil { @@ -132,7 +132,7 @@ func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork return nil } - latestEthereumBatch, err = ethereum.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) + latestEthereumBatch, err = l.eth.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) if err != nil { return err } @@ -143,7 +143,7 @@ func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork } // Check custom time delay offset - blockTime, err := injective.GetBlockCreationTime(ctx, int64(oldestConfirmedBatch.Block)) + blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedBatch.Block)) if err != nil { return errors.Wrap(err, "failed to parse timestamp from block") } @@ -154,13 +154,10 @@ func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork return nil } - l.Logger().WithFields(log.Fields{ - "inj_batch_nonce": oldestConfirmedBatch.BatchNonce, - "eth_batch_nonce": latestEthereumBatch.Uint64(), - }).Infoln("detected new batch on Injective") + l.Logger().WithFields(log.Fields{"inj_batch_nonce": oldestConfirmedBatch.BatchNonce, "eth_batch_nonce": latestEthereumBatch.Uint64()}).Infoln("detected new batch on Injective") // Send SendTransactionBatch to Ethereum - txHash, err := ethereum.SendTransactionBatch(ctx, currentValset, oldestConfirmedBatch, oldestConfirmedBatchSigs) + txHash, err := l.eth.SendTransactionBatch(ctx, currentValset, oldestConfirmedBatch, oldestConfirmedBatchSigs) if err != nil { return err } @@ -170,14 +167,14 @@ func (l *relayerLoop) relayBatch(ctx context.Context, injective InjectiveNetwork return nil } -func (l *relayerLoop) relayValset(ctx context.Context, injective InjectiveNetwork, ethereum EthereumNetwork) error { +func (l *relayerLoop) relayValset(ctx context.Context) error { metrics.ReportFuncCall(l.svcTags) doneFn := metrics.ReportFuncTiming(l.svcTags) defer doneFn() // we should determine if we need to relay one // to Ethereum for that we will find the latest confirmed valset and compare it to the ethereum chain - latestValsets, err := injective.LatestValsets(ctx) + latestValsets, err := l.inj.LatestValsets(ctx) if err != nil { return errors.Wrap(err, "failed to get latest valset updates from Injective") } @@ -188,7 +185,7 @@ func (l *relayerLoop) relayValset(ctx context.Context, injective InjectiveNetwor ) for _, set := range latestValsets { - sigs, err := injective.AllValsetConfirms(ctx, set.Nonce) + sigs, err := l.inj.AllValsetConfirms(ctx, set.Nonce) if err != nil { return errors.Wrapf(err, "failed to get valset confirmations for nonce %d", set.Nonce) } else if len(sigs) == 0 { @@ -205,7 +202,7 @@ func (l *relayerLoop) relayValset(ctx context.Context, injective InjectiveNetwor return nil } - currentEthValset, err := l.findLatestValsetOnEth(ctx, injective, ethereum) + currentEthValset, err := l.findLatestValsetOnEth(ctx, l.inj, l.eth) if err != nil { return errors.Wrap(err, "failed to find latest confirmed valset update on Ethereum") } @@ -214,7 +211,7 @@ func (l *relayerLoop) relayValset(ctx context.Context, injective InjectiveNetwor return nil } - latestEthereumValsetNonce, err := ethereum.GetValsetNonce(ctx) + latestEthereumValsetNonce, err := l.eth.GetValsetNonce(ctx) if err != nil { return errors.Wrap(err, "failed to get latest valset nonce from Ethereum") } @@ -225,7 +222,7 @@ func (l *relayerLoop) relayValset(ctx context.Context, injective InjectiveNetwor } // Check custom time delay offset - blockTime, err := injective.GetBlockCreationTime(ctx, int64(oldestConfirmedValset.Height)) + blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedValset.Height)) if err != nil { return errors.Wrap(err, "failed to parse timestamp from block") } @@ -241,7 +238,7 @@ func (l *relayerLoop) relayValset(ctx context.Context, injective InjectiveNetwor "eth_valset_nonce": latestEthereumValsetNonce.Uint64()}, ).Infoln("detected new valset on Injective") - txHash, err := ethereum.SendEthValsetUpdate( + txHash, err := l.eth.SendEthValsetUpdate( ctx, currentEthValset, oldestConfirmedValset, diff --git a/orchestrator/signer.go b/orchestrator/signer.go index 69a83a46..b1170f44 100644 --- a/orchestrator/signer.go +++ b/orchestrator/signer.go @@ -30,7 +30,7 @@ func (s *PeggyOrchestrator) EthSignerMainLoop(ctx context.Context) error { ethFrom: s.eth.FromAddress(), } - return loop.Run(ctx, s.inj) + return loop.Run(ctx) } func (s *PeggyOrchestrator) getPeggyID(ctx context.Context) (common.Hash, error) { @@ -67,17 +67,17 @@ func (l *ethSignerLoop) Logger() log.Logger { return l.logger.WithField("loop", "EthSigner") } -func (l *ethSignerLoop) Run(ctx context.Context, injective InjectiveNetwork) error { - return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx, injective)) +func (l *ethSignerLoop) Run(ctx context.Context) error { + return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx)) } -func (l *ethSignerLoop) loopFn(ctx context.Context, injective InjectiveNetwork) func() error { +func (l *ethSignerLoop) loopFn(ctx context.Context) func() error { return func() error { - if err := l.signNewValsetUpdates(ctx, injective); err != nil { + if err := l.signNewValsetUpdates(ctx); err != nil { return err } - if err := l.signNewBatch(ctx, injective); err != nil { + if err := l.signNewBatch(ctx); err != nil { return err } @@ -85,8 +85,8 @@ func (l *ethSignerLoop) loopFn(ctx context.Context, injective InjectiveNetwork) } } -func (l *ethSignerLoop) signNewValsetUpdates(ctx context.Context, injective InjectiveNetwork) error { - oldestUnsignedValsets, err := l.getUnsignedValsets(ctx, injective) +func (l *ethSignerLoop) signNewValsetUpdates(ctx context.Context) error { + oldestUnsignedValsets, err := l.getUnsignedValsets(ctx) if err != nil { return err } @@ -97,7 +97,7 @@ func (l *ethSignerLoop) signNewValsetUpdates(ctx context.Context, injective Inje } for _, vs := range oldestUnsignedValsets { - if err := l.signValset(ctx, injective, vs); err != nil { + if err := l.signValset(ctx, vs); err != nil { return err } @@ -107,8 +107,8 @@ func (l *ethSignerLoop) signNewValsetUpdates(ctx context.Context, injective Inje return nil } -func (l *ethSignerLoop) signNewBatch(ctx context.Context, injective InjectiveNetwork) error { - oldestUnsignedTransactionBatch, err := l.getUnsignedBatch(ctx, injective) +func (l *ethSignerLoop) signNewBatch(ctx context.Context) error { + oldestUnsignedTransactionBatch, err := l.getUnsignedBatch(ctx) if err != nil { return err } @@ -118,18 +118,18 @@ func (l *ethSignerLoop) signNewBatch(ctx context.Context, injective InjectiveNet return nil } - if err := l.signBatch(ctx, injective, oldestUnsignedTransactionBatch); err != nil { + if err := l.signBatch(ctx, oldestUnsignedTransactionBatch); err != nil { return err } return nil } -func (l *ethSignerLoop) getUnsignedBatch(ctx context.Context, injective InjectiveNetwork) (*types.OutgoingTxBatch, error) { +func (l *ethSignerLoop) getUnsignedBatch(ctx context.Context) (*types.OutgoingTxBatch, error) { var oldestUnsignedTransactionBatch *types.OutgoingTxBatch retryFn := func() (err error) { // sign the last unsigned batch, TODO check if we already have signed this - oldestUnsignedTransactionBatch, err = injective.OldestUnsignedTransactionBatch(ctx) + oldestUnsignedTransactionBatch, err = l.inj.OldestUnsignedTransactionBatch(ctx) if errors.Is(err, cosmos.ErrNotFound) || oldestUnsignedTransactionBatch == nil { return nil } @@ -151,9 +151,9 @@ func (l *ethSignerLoop) getUnsignedBatch(ctx context.Context, injective Injectiv return oldestUnsignedTransactionBatch, nil } -func (l *ethSignerLoop) signBatch(ctx context.Context, injective InjectiveNetwork, batch *types.OutgoingTxBatch) error { +func (l *ethSignerLoop) signBatch(ctx context.Context, batch *types.OutgoingTxBatch) error { if err := retry.Do( - func() error { return injective.SendBatchConfirm(ctx, l.peggyID, batch, l.ethFrom) }, + func() error { return l.inj.SendBatchConfirm(ctx, l.peggyID, batch, l.ethFrom) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -164,19 +164,15 @@ func (l *ethSignerLoop) signBatch(ctx context.Context, injective InjectiveNetwor return err } - l.Logger().WithFields(log.Fields{ - "token_contract": batch.TokenContract, - "nonce": batch.BatchNonce, - "txs": len(batch.Transactions), - }).Infoln("confirmed batch on Injective") + l.Logger().WithFields(log.Fields{"token_contract": batch.TokenContract, "nonce": batch.BatchNonce, "txs": len(batch.Transactions)}).Infoln("confirmed batch on Injective") return nil } -func (l *ethSignerLoop) getUnsignedValsets(ctx context.Context, injective InjectiveNetwork) ([]*types.Valset, error) { +func (l *ethSignerLoop) getUnsignedValsets(ctx context.Context) ([]*types.Valset, error) { var oldestUnsignedValsets []*types.Valset getOldestUnsignedValsetsFn := func() (err error) { - oldestUnsignedValsets, err = injective.OldestUnsignedValsets(ctx) + oldestUnsignedValsets, err = l.inj.OldestUnsignedValsets(ctx) if errors.Is(err, cosmos.ErrNotFound) || oldestUnsignedValsets == nil { return nil } @@ -198,9 +194,9 @@ func (l *ethSignerLoop) getUnsignedValsets(ctx context.Context, injective Inject return oldestUnsignedValsets, nil } -func (l *ethSignerLoop) signValset(ctx context.Context, injective InjectiveNetwork, vs *types.Valset) error { +func (l *ethSignerLoop) signValset(ctx context.Context, vs *types.Valset) error { if err := retry.Do(func() error { - return injective.SendValsetConfirm(ctx, l.peggyID, vs, l.ethFrom) + return l.inj.SendValsetConfirm(ctx, l.peggyID, vs, l.ethFrom) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), @@ -212,10 +208,7 @@ func (l *ethSignerLoop) signValset(ctx context.Context, injective InjectiveNetwo return err } - l.Logger().WithFields(log.Fields{ - "nonce": vs.Nonce, - "members": len(vs.Members), - }).Infoln("confirmed valset update on Injective") + l.Logger().WithFields(log.Fields{"nonce": vs.Nonce, "members": len(vs.Members)}).Infoln("confirmed valset update on Injective") return nil } From 3c9ae76e7c46d9aafad272b3c6c6f6e8bad4b576 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Tue, 26 Dec 2023 13:33:49 +0100 Subject: [PATCH 20/35] fix batch request loop tests --- orchestrator/batch_request.go | 12 +- orchestrator/batch_request_test.go | 142 +- orchestrator/mocks_test.go | 14 +- orchestrator/oracle_test.go | 511 +++--- orchestrator/relayer_test.go | 2301 ++++++++++++++-------------- orchestrator/signer_test.go | 275 ++-- 6 files changed, 1651 insertions(+), 1604 deletions(-) diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index 340374bc..e2d04fbd 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -86,7 +86,7 @@ func (l *batchRequestLoop) requestBatch(ctx context.Context, fee *types.BatchFee tokenDenom = l.tokenDenom(tokenAddr) ) - if thresholdMet := l.checkFeeThreshold(l.pricefeed, tokenAddr, fee.TotalFees); !thresholdMet { + if thresholdMet := l.checkFeeThreshold(tokenAddr, fee.TotalFees); !thresholdMet { return } @@ -106,12 +106,12 @@ func (l *batchRequestLoop) tokenDenom(tokenAddr eth.Address) string { return types.PeggyDenomString(tokenAddr) } -func (l *batchRequestLoop) checkFeeThreshold(feed PriceFeed, tokenAddr eth.Address, fees cosmtypes.Int) bool { +func (l *batchRequestLoop) checkFeeThreshold(tokenAddr eth.Address, fees cosmtypes.Int) bool { if l.minBatchFeeUSD == 0 { return true } - tokenPriceInUSD, err := feed.QueryUSDPrice(tokenAddr) + tokenPriceInUSD, err := l.pricefeed.QueryUSDPrice(tokenAddr) if err != nil { return false } @@ -121,11 +121,7 @@ func (l *batchRequestLoop) checkFeeThreshold(feed PriceFeed, tokenAddr eth.Addre totalFeeInUSDDec := decimal.NewFromBigInt(fees.BigInt(), -18).Mul(tokenPriceInUSDDec) if totalFeeInUSDDec.LessThan(minFeeInUSDDec) { - l.Logger().WithFields(log.Fields{ - "token_contract": tokenAddr.String(), - "batch_fee": totalFeeInUSDDec.String(), - "min_fee": minFeeInUSDDec.String(), - }).Debugln("insufficient token batch fee") + l.Logger().WithFields(log.Fields{"token_contract": tokenAddr.String(), "batch_fee": totalFeeInUSDDec.String(), "min_fee": minFeeInUSDDec.String()}).Debugln("insufficient token batch fee") return false } diff --git a/orchestrator/batch_request_test.go b/orchestrator/batch_request_test.go index 29fb387a..6f338159 100644 --- a/orchestrator/batch_request_test.go +++ b/orchestrator/batch_request_test.go @@ -5,12 +5,12 @@ import ( "errors" "testing" + cosmtypes "github.com/cosmos/cosmos-sdk/types" eth "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/xlab/suplog" - peggy "github.com/InjectiveLabs/sdk-go/chain/peggy/types" - cosmtypes "github.com/cosmos/cosmos-sdk/types" + peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" ) func TestRequestBatches(t *testing.T) { @@ -19,37 +19,47 @@ func TestRequestBatches(t *testing.T) { t.Run("failed to get unbatched tokens from injective", func(t *testing.T) { t.Parallel() - r := &batchRequester{ - log: suplog.DefaultLogger, - retries: 1, - } - inj := &mockInjective{ - unbatchedTokenFeesFn: func(context.Context) ([]*peggy.BatchFees, error) { + unbatchedTokenFeesFn: func(context.Context) ([]*peggytypes.BatchFees, error) { return nil, errors.New("fail") }, } - feed := mockPriceFeed{} - assert.NoError(t, r.run(context.TODO(), inj, feed)) + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + maxAttempts: 1, + } + + loop := batchRequestLoop{ + PeggyOrchestrator: o, + } + + loopFn := loop.loopFn(context.TODO()) + assert.NoError(t, loopFn()) }) t.Run("no unbatched tokens", func(t *testing.T) { t.Parallel() - r := &batchRequester{ - log: suplog.DefaultLogger, - retries: 1, - } - inj := &mockInjective{ - unbatchedTokenFeesFn: func(context.Context) ([]*peggy.BatchFees, error) { + unbatchedTokenFeesFn: func(context.Context) ([]*peggytypes.BatchFees, error) { return nil, nil }, } - feed := mockPriceFeed{} - assert.NoError(t, r.run(context.TODO(), inj, feed)) + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + maxAttempts: 1, + } + + loop := batchRequestLoop{ + PeggyOrchestrator: o, + } + + loopFn := loop.loopFn(context.TODO()) + assert.NoError(t, loopFn()) }) t.Run("batch does not meet fee threshold", func(t *testing.T) { @@ -57,20 +67,11 @@ func TestRequestBatches(t *testing.T) { tokenAddr := "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30" - r := &batchRequester{ - log: suplog.DefaultLogger, - minBatchFee: 51.0, - retries: 1, - erc20ContractMapping: map[eth.Address]string{ - eth.HexToAddress(tokenAddr): "inj", - }, - } - inj := &mockInjective{ sendRequestBatchFn: func(context.Context, string) error { return nil }, - unbatchedTokenFeesFn: func(context.Context) ([]*peggy.BatchFees, error) { + unbatchedTokenFeesFn: func(context.Context) ([]*peggytypes.BatchFees, error) { fees, _ := cosmtypes.NewIntFromString("50000000000000000000") - return []*peggy.BatchFees{ + return []*peggytypes.BatchFees{ { Token: eth.HexToAddress(tokenAddr).String(), TotalFees: fees, @@ -81,7 +82,23 @@ func TestRequestBatches(t *testing.T) { feed := mockPriceFeed{queryFn: func(_ eth.Address) (float64, error) { return 1, nil }} - assert.NoError(t, r.run(context.TODO(), inj, feed)) + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + pricefeed: feed, + maxAttempts: 1, + minBatchFeeUSD: 51.0, + erc20ContractMapping: map[eth.Address]string{ + eth.HexToAddress(tokenAddr): "inj", + }, + } + + loop := batchRequestLoop{ + PeggyOrchestrator: o, + } + + loopFn := loop.loopFn(context.TODO()) + assert.NoError(t, loopFn()) assert.Equal(t, inj.sendRequestBatchCallCount, 0) }) @@ -90,20 +107,11 @@ func TestRequestBatches(t *testing.T) { tokenAddr := "0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30" - r := &batchRequester{ - log: suplog.DefaultLogger, - minBatchFee: 49.0, - retries: 1, - erc20ContractMapping: map[eth.Address]string{ - eth.HexToAddress(tokenAddr): "inj", - }, - } - inj := &mockInjective{ sendRequestBatchFn: func(context.Context, string) error { return nil }, - unbatchedTokenFeesFn: func(_ context.Context) ([]*peggy.BatchFees, error) { + unbatchedTokenFeesFn: func(_ context.Context) ([]*peggytypes.BatchFees, error) { fees, _ := cosmtypes.NewIntFromString("50000000000000000000") - return []*peggy.BatchFees{ + return []*peggytypes.BatchFees{ { Token: eth.HexToAddress(tokenAddr).String(), TotalFees: fees, @@ -114,7 +122,23 @@ func TestRequestBatches(t *testing.T) { feed := mockPriceFeed{queryFn: func(_ eth.Address) (float64, error) { return 1, nil }} - assert.NoError(t, r.run(context.TODO(), inj, feed)) + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + pricefeed: feed, + maxAttempts: 1, + minBatchFeeUSD: 49.0, + erc20ContractMapping: map[eth.Address]string{ + eth.HexToAddress(tokenAddr): "inj", + }, + } + + loop := batchRequestLoop{ + PeggyOrchestrator: o, + } + + loopFn := loop.loopFn(context.TODO()) + assert.NoError(t, loopFn()) assert.Equal(t, inj.sendRequestBatchCallCount, 1) }) @@ -127,23 +151,34 @@ func TestCheckFeeThreshold(t *testing.T) { t.Parallel() var ( - requester = &batchRequester{minBatchFee: 21} - tokenAddr = eth.HexToAddress("0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30") totalFees, _ = cosmtypes.NewIntFromString("10000000000000000000") // 10inj + tokenAddr = eth.HexToAddress("0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30") feed = mockPriceFeed{queryFn: func(_ eth.Address) (float64, error) { return 2.5, nil }} ) + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + pricefeed: feed, + minBatchFeeUSD: 21, + erc20ContractMapping: map[eth.Address]string{ + tokenAddr: "inj", + }, + } + + loop := batchRequestLoop{ + PeggyOrchestrator: o, + } + // 2.5 * 10 > 21 - assert.True(t, requester.checkFeeThreshold(feed, tokenAddr, totalFees)) + assert.True(t, loop.checkFeeThreshold(tokenAddr, totalFees)) }) t.Run("fee threshold is met", func(t *testing.T) { t.Parallel() var ( - requester = &batchRequester{minBatchFee: 333.333} tokenAddr = eth.HexToAddress("0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30") totalFees, _ = cosmtypes.NewIntFromString("100000000000000000000") // 10inj feed = mockPriceFeed{queryFn: func(_ eth.Address) (float64, error) { @@ -151,7 +186,20 @@ func TestCheckFeeThreshold(t *testing.T) { }} ) + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + pricefeed: feed, + minBatchFeeUSD: 333.333, + erc20ContractMapping: map[eth.Address]string{ + tokenAddr: "inj", + }, + } + + loop := batchRequestLoop{ + PeggyOrchestrator: o, + } + // 2.5 * 100 < 333.333 - assert.False(t, requester.checkFeeThreshold(feed, tokenAddr, totalFees)) + assert.False(t, loop.checkFeeThreshold(tokenAddr, totalFees)) }) } diff --git a/orchestrator/mocks_test.go b/orchestrator/mocks_test.go index e33dedb0..636bf5b6 100644 --- a/orchestrator/mocks_test.go +++ b/orchestrator/mocks_test.go @@ -3,10 +3,10 @@ package orchestrator import ( "context" peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" - tmctypes "github.com/cometbft/cometbft/rpc/core/types" eth "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "math/big" + "time" peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" ) @@ -45,8 +45,8 @@ type mockInjective struct { oldestUnsignedTransactionBatchFn func(context.Context) (*peggytypes.OutgoingTxBatch, error) sendBatchConfirmFn func(context.Context, eth.Hash, *peggytypes.OutgoingTxBatch, eth.Address) error - latestValsetsFn func(context.Context) ([]*peggytypes.Valset, error) - getBlockFn func(context.Context, int64) (*tmctypes.ResultBlock, error) + latestValsetsFn func(context.Context) ([]*peggytypes.Valset, error) + getBlockCreationTimeFn func(context.Context, int64) (time.Time, error) allValsetConfirmsFn func(context.Context, uint64) ([]*peggytypes.MsgValsetConfirm, error) valsetAtFn func(context.Context, uint64) (*peggytypes.Valset, error) @@ -106,10 +106,6 @@ func (i *mockInjective) OldestUnsignedTransactionBatch(ctx context.Context) (*pe return i.oldestUnsignedTransactionBatchFn(ctx) } -func (i *mockInjective) GetBlock(ctx context.Context, height int64) (*tmctypes.ResultBlock, error) { - return i.getBlockFn(ctx, height) -} - func (i *mockInjective) LatestValsets(ctx context.Context) ([]*peggytypes.Valset, error) { return i.latestValsetsFn(ctx) } @@ -134,6 +130,10 @@ func (i *mockInjective) TransactionBatchSignatures(ctx context.Context, nonce ui return i.transactionBatchSignaturesFn(ctx, nonce, tokenContract) } +func (i *mockInjective) GetBlockCreationTime(ctx context.Context, height int64) (time.Time, error) { + return i.getBlockCreationTimeFn(ctx, height) +} + type mockEthereum struct { fromAddressFn func() eth.Address headerByNumberFn func(context.Context, *big.Int) (*ethtypes.Header, error) diff --git a/orchestrator/oracle_test.go b/orchestrator/oracle_test.go index a91e16a1..9b179186 100644 --- a/orchestrator/oracle_test.go +++ b/orchestrator/oracle_test.go @@ -1,257 +1,258 @@ package orchestrator -import ( - "context" - "errors" - "math/big" - "testing" - "time" - - peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/assert" - "github.com/xlab/suplog" - - wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" -) - -func TestEthOracle(t *testing.T) { - t.Parallel() - - t.Run("failed to get latest header from ethereum", func(t *testing.T) { - t.Parallel() - - orch := &PeggyOrchestrator{ - eth: mockEthereum{ - headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { - return nil, errors.New("fail") - }, - }, - } - - assert.Error(t, orch.EthOracleMainLoop(context.TODO())) - }) - - t.Run("latest ethereum header is old", func(t *testing.T) { - t.Parallel() - - ethereum := mockEthereum{ - headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { - return &types.Header{Number: big.NewInt(50)}, nil - }, - } - - o := ðOracle{ - log: suplog.DefaultLogger, - retries: 1, - lastResyncWithInjective: time.Now(), - lastCheckedEthHeight: 100, - } - - assert.NoError(t, o.run(context.TODO(), nil, ethereum)) - assert.Equal(t, o.lastCheckedEthHeight, uint64(38)) - }) - - t.Run("failed to get SendToCosmos events", func(t *testing.T) { - t.Parallel() - - ethereum := mockEthereum{ - headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { - return &types.Header{Number: big.NewInt(200)}, nil - }, - getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { - return nil, errors.New("fail") - }, - } - - o := ðOracle{ - log: suplog.DefaultLogger, - retries: 1, - lastResyncWithInjective: time.Now(), - lastCheckedEthHeight: 100, - } - - assert.Error(t, o.run(context.TODO(), nil, ethereum)) - assert.Equal(t, o.lastCheckedEthHeight, uint64(100)) - }) - - t.Run("failed to get last claim event from injective", func(t *testing.T) { - t.Parallel() - - ethereum := mockEthereum{ - headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { - return &types.Header{Number: big.NewInt(200)}, nil - }, - - // no-ops - getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { - return nil, nil - }, - getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyTransactionBatchExecutedEvent, error) { - return nil, nil - }, - getValsetUpdatedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return nil, nil - }, - getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyERC20DeployedEvent, error) { - return nil, nil - }, - getSendToInjectiveEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToInjectiveEvent, error) { - return nil, nil - }, - } - - injective := &mockInjective{ - lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { - return nil, errors.New("fail") - }, - } - - o := ðOracle{ - log: suplog.DefaultLogger, - retries: 1, - lastResyncWithInjective: time.Now(), - lastCheckedEthHeight: 100, - } - - assert.Error(t, o.run(context.TODO(), injective, ethereum)) - assert.Equal(t, o.lastCheckedEthHeight, uint64(100)) - }) - - t.Run("old events are pruned", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { - return &peggytypes.LastClaimEvent{EthereumEventNonce: 6}, nil - }, - sendEthereumClaimsFn: func( - context.Context, - uint64, - []*wrappers.PeggySendToCosmosEvent, - []*wrappers.PeggySendToInjectiveEvent, - []*wrappers.PeggyTransactionBatchExecutedEvent, - []*wrappers.PeggyERC20DeployedEvent, - []*wrappers.PeggyValsetUpdatedEvent, - ) error { - return nil - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { - return &types.Header{Number: big.NewInt(200)}, nil - }, - getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { - return []*wrappers.PeggySendToCosmosEvent{{EventNonce: big.NewInt(5)}}, nil - }, - - // no-ops - getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyTransactionBatchExecutedEvent, error) { - return nil, nil - }, - getValsetUpdatedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return nil, nil - }, - getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyERC20DeployedEvent, error) { - return nil, nil - }, - getSendToInjectiveEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToInjectiveEvent, error) { - return nil, nil - }, - } - - o := ðOracle{ - log: suplog.DefaultLogger, - retries: 1, - lastResyncWithInjective: time.Now(), - lastCheckedEthHeight: 100, - } - - assert.NoError(t, o.run(context.TODO(), inj, eth)) - assert.Equal(t, o.lastCheckedEthHeight, uint64(120)) - assert.Equal(t, inj.sendEthereumClaimsCallCount, 0) - }) - - t.Run("new events are sent to injective", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { - return &peggytypes.LastClaimEvent{EthereumEventNonce: 6}, nil - }, - sendEthereumClaimsFn: func( - context.Context, - uint64, - []*wrappers.PeggySendToCosmosEvent, - []*wrappers.PeggySendToInjectiveEvent, - []*wrappers.PeggyTransactionBatchExecutedEvent, - []*wrappers.PeggyERC20DeployedEvent, - []*wrappers.PeggyValsetUpdatedEvent, - ) error { - return nil - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { - return &types.Header{Number: big.NewInt(200)}, nil - }, - getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { - return []*wrappers.PeggySendToCosmosEvent{{EventNonce: big.NewInt(10)}}, nil - }, - - // no-ops - getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyTransactionBatchExecutedEvent, error) { - return nil, nil - }, - getValsetUpdatedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return nil, nil - }, - getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyERC20DeployedEvent, error) { - return nil, nil - }, - getSendToInjectiveEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToInjectiveEvent, error) { - return nil, nil - }, - } - - o := ðOracle{ - log: suplog.DefaultLogger, - retries: 1, - lastResyncWithInjective: time.Now(), - lastCheckedEthHeight: 100, - } - - assert.NoError(t, o.run(context.TODO(), inj, eth)) - assert.Equal(t, o.lastCheckedEthHeight, uint64(120)) - assert.Equal(t, inj.sendEthereumClaimsCallCount, 1) - }) - - t.Run("auto resync", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - lastClaimEventFn: func(_ context.Context) (*peggytypes.LastClaimEvent, error) { - return &peggytypes.LastClaimEvent{EthereumEventHeight: 101}, nil - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { - return &types.Header{Number: big.NewInt(50)}, nil - }, - } - - o := ðOracle{ - log: suplog.DefaultLogger, - retries: 1, - lastResyncWithInjective: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), - lastCheckedEthHeight: 100, - } - - assert.NoError(t, o.run(context.TODO(), inj, eth)) - assert.Equal(t, o.lastCheckedEthHeight, uint64(101)) - assert.True(t, time.Since(o.lastResyncWithInjective) < 1*time.Second) - }) -} +// +//import ( +// "context" +// "errors" +// "math/big" +// "testing" +// "time" +// +// peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" +// "github.com/ethereum/go-ethereum/core/types" +// "github.com/stretchr/testify/assert" +// "github.com/xlab/suplog" +// +// wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" +//) +// +//func TestEthOracle(t *testing.T) { +// t.Parallel() +// +// t.Run("failed to get latest header from ethereum", func(t *testing.T) { +// t.Parallel() +// +// orch := &PeggyOrchestrator{ +// eth: mockEthereum{ +// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { +// return nil, errors.New("fail") +// }, +// }, +// } +// +// assert.Error(t, orch.EthOracleMainLoop(context.TODO())) +// }) +// +// t.Run("latest ethereum header is old", func(t *testing.T) { +// t.Parallel() +// +// ethereum := mockEthereum{ +// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { +// return &types.Header{Number: big.NewInt(50)}, nil +// }, +// } +// +// o := ðOracle{ +// log: suplog.DefaultLogger, +// retries: 1, +// lastResyncWithInjective: time.Now(), +// lastCheckedEthHeight: 100, +// } +// +// assert.NoError(t, o.run(context.TODO(), nil, ethereum)) +// assert.Equal(t, o.lastCheckedEthHeight, uint64(38)) +// }) +// +// t.Run("failed to get SendToCosmos events", func(t *testing.T) { +// t.Parallel() +// +// ethereum := mockEthereum{ +// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { +// return &types.Header{Number: big.NewInt(200)}, nil +// }, +// getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { +// return nil, errors.New("fail") +// }, +// } +// +// o := ðOracle{ +// log: suplog.DefaultLogger, +// retries: 1, +// lastResyncWithInjective: time.Now(), +// lastCheckedEthHeight: 100, +// } +// +// assert.Error(t, o.run(context.TODO(), nil, ethereum)) +// assert.Equal(t, o.lastCheckedEthHeight, uint64(100)) +// }) +// +// t.Run("failed to get last claim event from injective", func(t *testing.T) { +// t.Parallel() +// +// ethereum := mockEthereum{ +// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { +// return &types.Header{Number: big.NewInt(200)}, nil +// }, +// +// // no-ops +// getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { +// return nil, nil +// }, +// getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyTransactionBatchExecutedEvent, error) { +// return nil, nil +// }, +// getValsetUpdatedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return nil, nil +// }, +// getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyERC20DeployedEvent, error) { +// return nil, nil +// }, +// getSendToInjectiveEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToInjectiveEvent, error) { +// return nil, nil +// }, +// } +// +// injective := &mockInjective{ +// lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { +// return nil, errors.New("fail") +// }, +// } +// +// o := ðOracle{ +// log: suplog.DefaultLogger, +// retries: 1, +// lastResyncWithInjective: time.Now(), +// lastCheckedEthHeight: 100, +// } +// +// assert.Error(t, o.run(context.TODO(), injective, ethereum)) +// assert.Equal(t, o.lastCheckedEthHeight, uint64(100)) +// }) +// +// t.Run("old events are pruned", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { +// return &peggytypes.LastClaimEvent{EthereumEventNonce: 6}, nil +// }, +// sendEthereumClaimsFn: func( +// context.Context, +// uint64, +// []*wrappers.PeggySendToCosmosEvent, +// []*wrappers.PeggySendToInjectiveEvent, +// []*wrappers.PeggyTransactionBatchExecutedEvent, +// []*wrappers.PeggyERC20DeployedEvent, +// []*wrappers.PeggyValsetUpdatedEvent, +// ) error { +// return nil +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { +// return &types.Header{Number: big.NewInt(200)}, nil +// }, +// getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { +// return []*wrappers.PeggySendToCosmosEvent{{EventNonce: big.NewInt(5)}}, nil +// }, +// +// // no-ops +// getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyTransactionBatchExecutedEvent, error) { +// return nil, nil +// }, +// getValsetUpdatedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return nil, nil +// }, +// getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyERC20DeployedEvent, error) { +// return nil, nil +// }, +// getSendToInjectiveEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToInjectiveEvent, error) { +// return nil, nil +// }, +// } +// +// o := ðOracle{ +// log: suplog.DefaultLogger, +// retries: 1, +// lastResyncWithInjective: time.Now(), +// lastCheckedEthHeight: 100, +// } +// +// assert.NoError(t, o.run(context.TODO(), inj, eth)) +// assert.Equal(t, o.lastCheckedEthHeight, uint64(120)) +// assert.Equal(t, inj.sendEthereumClaimsCallCount, 0) +// }) +// +// t.Run("new events are sent to injective", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { +// return &peggytypes.LastClaimEvent{EthereumEventNonce: 6}, nil +// }, +// sendEthereumClaimsFn: func( +// context.Context, +// uint64, +// []*wrappers.PeggySendToCosmosEvent, +// []*wrappers.PeggySendToInjectiveEvent, +// []*wrappers.PeggyTransactionBatchExecutedEvent, +// []*wrappers.PeggyERC20DeployedEvent, +// []*wrappers.PeggyValsetUpdatedEvent, +// ) error { +// return nil +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { +// return &types.Header{Number: big.NewInt(200)}, nil +// }, +// getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { +// return []*wrappers.PeggySendToCosmosEvent{{EventNonce: big.NewInt(10)}}, nil +// }, +// +// // no-ops +// getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyTransactionBatchExecutedEvent, error) { +// return nil, nil +// }, +// getValsetUpdatedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return nil, nil +// }, +// getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyERC20DeployedEvent, error) { +// return nil, nil +// }, +// getSendToInjectiveEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToInjectiveEvent, error) { +// return nil, nil +// }, +// } +// +// o := ðOracle{ +// log: suplog.DefaultLogger, +// retries: 1, +// lastResyncWithInjective: time.Now(), +// lastCheckedEthHeight: 100, +// } +// +// assert.NoError(t, o.run(context.TODO(), inj, eth)) +// assert.Equal(t, o.lastCheckedEthHeight, uint64(120)) +// assert.Equal(t, inj.sendEthereumClaimsCallCount, 1) +// }) +// +// t.Run("auto resync", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// lastClaimEventFn: func(_ context.Context) (*peggytypes.LastClaimEvent, error) { +// return &peggytypes.LastClaimEvent{EthereumEventHeight: 101}, nil +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { +// return &types.Header{Number: big.NewInt(50)}, nil +// }, +// } +// +// o := ðOracle{ +// log: suplog.DefaultLogger, +// retries: 1, +// lastResyncWithInjective: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), +// lastCheckedEthHeight: 100, +// } +// +// assert.NoError(t, o.run(context.TODO(), inj, eth)) +// assert.Equal(t, o.lastCheckedEthHeight, uint64(101)) +// assert.True(t, time.Since(o.lastResyncWithInjective) < 1*time.Second) +// }) +//} diff --git a/orchestrator/relayer_test.go b/orchestrator/relayer_test.go index 43043ab2..d70778bc 100644 --- a/orchestrator/relayer_test.go +++ b/orchestrator/relayer_test.go @@ -1,1152 +1,1153 @@ package orchestrator -import ( - "context" - "math/big" - "testing" - "time" - - tmctypes "github.com/cometbft/cometbft/rpc/core/types" - tmtypes "github.com/cometbft/cometbft/types" - cosmtypes "github.com/cosmos/cosmos-sdk/types" - "github.com/ethereum/go-ethereum/common" - ctypes "github.com/ethereum/go-ethereum/core/types" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/xlab/suplog" - - wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" - "github.com/InjectiveLabs/sdk-go/chain/peggy/types" -) - -func TestValsetRelaying(t *testing.T) { - t.Parallel() - - t.Run("failed to fetch latest valsets from injective", func(t *testing.T) { - t.Parallel() - - injective := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.Error(t, rel.relayValsets(context.TODO(), injective, nil)) - }) - - t.Run("failed to fetch confirms for a valset", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{{}}, nil // non-empty will do - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.Error(t, rel.relayValsets(context.TODO(), inj, nil)) - }) - - t.Run("no confirms for valset", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{{}}, nil // non-empty will do - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return nil, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.NoError(t, rel.relayValsets(context.TODO(), inj, nil)) - }) - - t.Run("failed to get latest ethereum header", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{{}}, nil // non-empty will do - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) - }) - - t.Run("failed to get latest ethereum header", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{{}}, nil // non-empty will do - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) - }) - - t.Run("failed to get valset nonce from peggy contract", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{{}}, nil // non-empty will do - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(123)}, nil - }, - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) - }) - - t.Run("failed to get specific valset from injective", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{{}}, nil // non-empty will do - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return nil, errors.New("fail") - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(123)}, nil - }, - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) - }) - - t.Run("failed to get valset update events from ethereum", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{{}}, nil // non-empty will do - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{}, nil // non-empty will do - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(123)}, nil - }, - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) - }) - - t.Run("ethereum valset is not higher than injective valset", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{ - { - Nonce: 333, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, - }, nil - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{ - Nonce: 333, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, nil // non-empty will do - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(123)}, nil - }, - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(333), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xfafafafafafafafa"), - }, - }, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.NoError(t, rel.relayValsets(context.TODO(), inj, eth)) - }) - - t.Run("injective valset is higher than ethereum but failed to get block from injective", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{ - { - Nonce: 444, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, - }, nil - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{ - Nonce: 333, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, nil // non-empty will do - }, - getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { - return nil, errors.New("fail") - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(123)}, nil - }, - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(333), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xfafafafafafafafa"), - }, - }, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - } - - assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) - }) - - t.Run("injective valset is higher than ethereum but valsetOffsetDur has not expired", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{ - { - Nonce: 444, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, - }, nil - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{ - Nonce: 333, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, nil // non-empty will do - }, - getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { - return &tmctypes.ResultBlock{ - Block: &tmtypes.Block{ - Header: tmtypes.Header{ - Time: time.Now().Add(time.Hour), - }, - }, - }, nil - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(123)}, nil - }, - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(333), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xfafafafafafafafa"), - }, - }, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - relayValsetOffsetDur: time.Second * 5, - } - - assert.NoError(t, rel.relayValsets(context.TODO(), inj, eth)) - }) - - t.Run("injective valset is higher than ethereum but failed to send update tx to ethereum", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{ - { - Nonce: 444, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, - }, nil - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{ - Nonce: 333, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, nil // non-empty will do - }, - getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { - return &tmctypes.ResultBlock{ - Block: &tmtypes.Block{ - Header: tmtypes.Header{ - Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), - }, - }, - }, nil - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(123)}, nil - }, - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(333), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xfafafafafafafafa"), - }, - }, nil - }, - sendEthValsetUpdateFn: func(_ context.Context, _ *types.Valset, _ *types.Valset, _ []*types.MsgValsetConfirm) (*common.Hash, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - relayValsetOffsetDur: time.Second * 5, - } - - assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) - }) - - t.Run("new valset update is sent to ethereum", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{ - { - Nonce: 444, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, - }, nil - }, - allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { - return []*types.MsgValsetConfirm{ - { - Nonce: 5, - Orchestrator: "orch", - EthAddress: "eth", - Signature: "sig", - }, - }, nil - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{ - Nonce: 333, - RewardAmount: cosmtypes.NewInt(1000), - RewardToken: "0xfafafafafafafafa", - }, nil - }, - getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { - return &tmctypes.ResultBlock{ - Block: &tmtypes.Block{ - Header: tmtypes.Header{ - Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), - }, - }, - }, nil - }, - } - - eth := mockEthereum{ - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(123)}, nil - }, - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(333), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xfafafafafafafafa"), - }, - }, nil - }, - sendEthValsetUpdateFn: func(_ context.Context, _ *types.Valset, _ *types.Valset, _ []*types.MsgValsetConfirm) (*common.Hash, error) { - return &common.Hash{}, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - valsetRelaying: true, - relayValsetOffsetDur: time.Second * 5, - } - - assert.NoError(t, rel.relayValsets(context.TODO(), inj, eth)) - }) -} - -func TestBatchRelaying(t *testing.T) { - t.Parallel() - - t.Run("failed to get latest batches from injective", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.Error(t, rel.relayBatches(context.TODO(), inj, nil)) - }) - - t.Run("failed to get latest batches from injective", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{{}}, nil // non-empty will do - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.Error(t, rel.relayBatches(context.TODO(), inj, nil)) - }) - - t.Run("no batch confirms", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{{}}, nil // non-empty will do - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return nil, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.NoError(t, rel.relayBatches(context.TODO(), inj, nil)) - }) - - t.Run("failed to get batch nonce from ethereum", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{{}}, nil // non-empty will do - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) - }) - - t.Run("failed to get latest ethereum header", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{ - { - TokenContract: "tokenContract", - BatchNonce: 100, - }, - }, nil - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return big.NewInt(99), nil - }, - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) - }) - - t.Run("failed to get valset nonce from ethereum", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{ - { - TokenContract: "tokenContract", - BatchNonce: 100, - }, - }, nil - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return big.NewInt(99), nil - }, - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(100)}, nil - }, - - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) - }) - - t.Run("failed to get specific valset from injective", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{ - { - TokenContract: "tokenContract", - BatchNonce: 100, - }, - }, nil - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return nil, errors.New("fail") - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return big.NewInt(99), nil - }, - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(100)}, nil - }, - - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) - }) - - t.Run("failed to get valset updated events from ethereum", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{ - { - TokenContract: "tokenContract", - BatchNonce: 100, - }, - }, nil - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{}, nil - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return big.NewInt(99), nil - }, - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(100)}, nil - }, - - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) - }) - - t.Run("ethereum batch is not lower than injective batch", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{ - { - TokenContract: "tokenContract", - BatchNonce: 202, - }, - }, nil - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{Nonce: 202}, nil - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return big.NewInt(202), nil - }, - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(100)}, nil - }, - - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(202), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xcafecafecafecafe"), - }, - }, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.NoError(t, rel.relayBatches(context.TODO(), inj, eth)) - }) - - t.Run("ethereum batch is lower than injective batch but failed to get block from injhective", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{ - { - TokenContract: "tokenContract", - BatchNonce: 202, - }, - }, nil - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{Nonce: 202}, nil - }, - getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { - return nil, errors.New("fail") - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return big.NewInt(201), nil - }, - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(100)}, nil - }, - - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(202), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xcafecafecafecafe"), - }, - }, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - } - - assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) - }) - - t.Run("ethereum batch is lower than injective batch but relayBatchOffsetDur has not expired", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{ - { - TokenContract: "tokenContract", - BatchNonce: 202, - }, - }, nil - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{Nonce: 202}, nil - }, - getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { - return &tmctypes.ResultBlock{ - Block: &tmtypes.Block{ - Header: tmtypes.Header{ - Time: time.Now().Add(time.Hour), - }, - }, - }, nil - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return big.NewInt(201), nil - }, - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(100)}, nil - }, - - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(202), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xcafecafecafecafe"), - }, - }, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - relayBatchOffsetDur: 5 * time.Second, - } - - assert.NoError(t, rel.relayBatches(context.TODO(), inj, eth)) - }) - - t.Run("ethereum batch is lower than injective batch but failed to send batch update", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{ - { - TokenContract: "tokenContract", - BatchNonce: 202, - }, - }, nil - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{Nonce: 202}, nil - }, - getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { - return &tmctypes.ResultBlock{ - Block: &tmtypes.Block{ - Header: tmtypes.Header{ - Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), - }, - }, - }, nil - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return big.NewInt(201), nil - }, - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(100)}, nil - }, - - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(202), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xcafecafecafecafe"), - }, - }, nil - }, - sendTransactionBatchFn: func(_ context.Context, _ *types.Valset, _ *types.OutgoingTxBatch, _ []*types.MsgConfirmBatch) (*common.Hash, error) { - return nil, errors.New("fail") - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - relayBatchOffsetDur: 5 * time.Second, - } - - assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) - }) - - t.Run("sending a batch update to ethereum", func(t *testing.T) { - t.Parallel() - - inj := &mockInjective{ - latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { - return []*types.OutgoingTxBatch{ - { - TokenContract: "tokenContract", - BatchNonce: 202, - }, - }, nil - }, - transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { - return []*types.MsgConfirmBatch{{}}, nil // non-nil will do - }, - valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { - return &types.Valset{Nonce: 202}, nil - }, - getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { - return &tmctypes.ResultBlock{ - Block: &tmtypes.Block{ - Header: tmtypes.Header{ - Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), - }, - }, - }, nil - }, - } - - eth := mockEthereum{ - getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { - return big.NewInt(201), nil - }, - headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { - return &ctypes.Header{Number: big.NewInt(100)}, nil - }, - - getValsetNonceFn: func(_ context.Context) (*big.Int, error) { - return big.NewInt(100), nil - }, - getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { - return []*wrappers.PeggyValsetUpdatedEvent{ - { - NewValsetNonce: big.NewInt(202), - RewardAmount: big.NewInt(1000), - RewardToken: common.HexToAddress("0xcafecafecafecafe"), - }, - }, nil - }, - sendTransactionBatchFn: func(_ context.Context, _ *types.Valset, _ *types.OutgoingTxBatch, _ []*types.MsgConfirmBatch) (*common.Hash, error) { - return &common.Hash{}, nil - }, - } - - rel := &relayer{ - log: suplog.DefaultLogger, - retries: 1, - batchRelaying: true, - relayBatchOffsetDur: 5 * time.Second, - } - - assert.NoError(t, rel.relayBatches(context.TODO(), inj, eth)) - }) -} +// +//import ( +// "context" +// "math/big" +// "testing" +// "time" +// +// tmctypes "github.com/cometbft/cometbft/rpc/core/types" +// tmtypes "github.com/cometbft/cometbft/types" +// cosmtypes "github.com/cosmos/cosmos-sdk/types" +// "github.com/ethereum/go-ethereum/common" +// ctypes "github.com/ethereum/go-ethereum/core/types" +// "github.com/pkg/errors" +// "github.com/stretchr/testify/assert" +// "github.com/xlab/suplog" +// +// wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" +// "github.com/InjectiveLabs/sdk-go/chain/peggy/types" +//) +// +//func TestValsetRelaying(t *testing.T) { +// t.Parallel() +// +// t.Run("failed to fetch latest valsets from injective", func(t *testing.T) { +// t.Parallel() +// +// injective := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.Error(t, rel.relayValsets(context.TODO(), injective, nil)) +// }) +// +// t.Run("failed to fetch confirms for a valset", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{{}}, nil // non-empty will do +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.Error(t, rel.relayValsets(context.TODO(), inj, nil)) +// }) +// +// t.Run("no confirms for valset", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{{}}, nil // non-empty will do +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return nil, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.NoError(t, rel.relayValsets(context.TODO(), inj, nil)) +// }) +// +// t.Run("failed to get latest ethereum header", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{{}}, nil // non-empty will do +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +// +// t.Run("failed to get latest ethereum header", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{{}}, nil // non-empty will do +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +// +// t.Run("failed to get valset nonce from peggy contract", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{{}}, nil // non-empty will do +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(123)}, nil +// }, +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +// +// t.Run("failed to get specific valset from injective", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{{}}, nil // non-empty will do +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return nil, errors.New("fail") +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(123)}, nil +// }, +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +// +// t.Run("failed to get valset update events from ethereum", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{{}}, nil // non-empty will do +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{}, nil // non-empty will do +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(123)}, nil +// }, +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +// +// t.Run("ethereum valset is not higher than injective valset", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{ +// { +// Nonce: 333, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, +// }, nil +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{ +// Nonce: 333, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, nil // non-empty will do +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(123)}, nil +// }, +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(333), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xfafafafafafafafa"), +// }, +// }, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.NoError(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +// +// t.Run("injective valset is higher than ethereum but failed to get block from injective", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{ +// { +// Nonce: 444, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, +// }, nil +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{ +// Nonce: 333, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, nil // non-empty will do +// }, +// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { +// return nil, errors.New("fail") +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(123)}, nil +// }, +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(333), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xfafafafafafafafa"), +// }, +// }, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// } +// +// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +// +// t.Run("injective valset is higher than ethereum but valsetOffsetDur has not expired", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{ +// { +// Nonce: 444, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, +// }, nil +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{ +// Nonce: 333, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, nil // non-empty will do +// }, +// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { +// return &tmctypes.ResultBlock{ +// Block: &tmtypes.Block{ +// Header: tmtypes.Header{ +// Time: time.Now().Add(time.Hour), +// }, +// }, +// }, nil +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(123)}, nil +// }, +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(333), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xfafafafafafafafa"), +// }, +// }, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// relayValsetOffsetDur: time.Second * 5, +// } +// +// assert.NoError(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +// +// t.Run("injective valset is higher than ethereum but failed to send update tx to ethereum", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{ +// { +// Nonce: 444, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, +// }, nil +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{ +// Nonce: 333, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, nil // non-empty will do +// }, +// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { +// return &tmctypes.ResultBlock{ +// Block: &tmtypes.Block{ +// Header: tmtypes.Header{ +// Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), +// }, +// }, +// }, nil +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(123)}, nil +// }, +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(333), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xfafafafafafafafa"), +// }, +// }, nil +// }, +// sendEthValsetUpdateFn: func(_ context.Context, _ *types.Valset, _ *types.Valset, _ []*types.MsgValsetConfirm) (*common.Hash, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// relayValsetOffsetDur: time.Second * 5, +// } +// +// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +// +// t.Run("new valset update is sent to ethereum", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{ +// { +// Nonce: 444, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, +// }, nil +// }, +// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { +// return []*types.MsgValsetConfirm{ +// { +// Nonce: 5, +// Orchestrator: "orch", +// EthAddress: "eth", +// Signature: "sig", +// }, +// }, nil +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{ +// Nonce: 333, +// RewardAmount: cosmtypes.NewInt(1000), +// RewardToken: "0xfafafafafafafafa", +// }, nil +// }, +// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { +// return &tmctypes.ResultBlock{ +// Block: &tmtypes.Block{ +// Header: tmtypes.Header{ +// Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), +// }, +// }, +// }, nil +// }, +// } +// +// eth := mockEthereum{ +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(123)}, nil +// }, +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(333), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xfafafafafafafafa"), +// }, +// }, nil +// }, +// sendEthValsetUpdateFn: func(_ context.Context, _ *types.Valset, _ *types.Valset, _ []*types.MsgValsetConfirm) (*common.Hash, error) { +// return &common.Hash{}, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// valsetRelaying: true, +// relayValsetOffsetDur: time.Second * 5, +// } +// +// assert.NoError(t, rel.relayValsets(context.TODO(), inj, eth)) +// }) +//} +// +//func TestBatchRelaying(t *testing.T) { +// t.Parallel() +// +// t.Run("failed to get latest batches from injective", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.Error(t, rel.relayBatches(context.TODO(), inj, nil)) +// }) +// +// t.Run("failed to get latest batches from injective", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{{}}, nil // non-empty will do +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.Error(t, rel.relayBatches(context.TODO(), inj, nil)) +// }) +// +// t.Run("no batch confirms", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{{}}, nil // non-empty will do +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return nil, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.NoError(t, rel.relayBatches(context.TODO(), inj, nil)) +// }) +// +// t.Run("failed to get batch nonce from ethereum", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{{}}, nil // non-empty will do +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +// +// t.Run("failed to get latest ethereum header", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{ +// { +// TokenContract: "tokenContract", +// BatchNonce: 100, +// }, +// }, nil +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return big.NewInt(99), nil +// }, +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +// +// t.Run("failed to get valset nonce from ethereum", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{ +// { +// TokenContract: "tokenContract", +// BatchNonce: 100, +// }, +// }, nil +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return big.NewInt(99), nil +// }, +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(100)}, nil +// }, +// +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +// +// t.Run("failed to get specific valset from injective", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{ +// { +// TokenContract: "tokenContract", +// BatchNonce: 100, +// }, +// }, nil +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return nil, errors.New("fail") +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return big.NewInt(99), nil +// }, +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(100)}, nil +// }, +// +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +// +// t.Run("failed to get valset updated events from ethereum", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{ +// { +// TokenContract: "tokenContract", +// BatchNonce: 100, +// }, +// }, nil +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{}, nil +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return big.NewInt(99), nil +// }, +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(100)}, nil +// }, +// +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +// +// t.Run("ethereum batch is not lower than injective batch", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{ +// { +// TokenContract: "tokenContract", +// BatchNonce: 202, +// }, +// }, nil +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{Nonce: 202}, nil +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return big.NewInt(202), nil +// }, +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(100)}, nil +// }, +// +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(202), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xcafecafecafecafe"), +// }, +// }, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.NoError(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +// +// t.Run("ethereum batch is lower than injective batch but failed to get block from injhective", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{ +// { +// TokenContract: "tokenContract", +// BatchNonce: 202, +// }, +// }, nil +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{Nonce: 202}, nil +// }, +// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { +// return nil, errors.New("fail") +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return big.NewInt(201), nil +// }, +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(100)}, nil +// }, +// +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(202), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xcafecafecafecafe"), +// }, +// }, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// } +// +// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +// +// t.Run("ethereum batch is lower than injective batch but relayBatchOffsetDur has not expired", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{ +// { +// TokenContract: "tokenContract", +// BatchNonce: 202, +// }, +// }, nil +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{Nonce: 202}, nil +// }, +// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { +// return &tmctypes.ResultBlock{ +// Block: &tmtypes.Block{ +// Header: tmtypes.Header{ +// Time: time.Now().Add(time.Hour), +// }, +// }, +// }, nil +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return big.NewInt(201), nil +// }, +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(100)}, nil +// }, +// +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(202), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xcafecafecafecafe"), +// }, +// }, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// relayBatchOffsetDur: 5 * time.Second, +// } +// +// assert.NoError(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +// +// t.Run("ethereum batch is lower than injective batch but failed to send batch update", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{ +// { +// TokenContract: "tokenContract", +// BatchNonce: 202, +// }, +// }, nil +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{Nonce: 202}, nil +// }, +// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { +// return &tmctypes.ResultBlock{ +// Block: &tmtypes.Block{ +// Header: tmtypes.Header{ +// Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), +// }, +// }, +// }, nil +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return big.NewInt(201), nil +// }, +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(100)}, nil +// }, +// +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(202), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xcafecafecafecafe"), +// }, +// }, nil +// }, +// sendTransactionBatchFn: func(_ context.Context, _ *types.Valset, _ *types.OutgoingTxBatch, _ []*types.MsgConfirmBatch) (*common.Hash, error) { +// return nil, errors.New("fail") +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// relayBatchOffsetDur: 5 * time.Second, +// } +// +// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +// +// t.Run("sending a batch update to ethereum", func(t *testing.T) { +// t.Parallel() +// +// inj := &mockInjective{ +// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { +// return []*types.OutgoingTxBatch{ +// { +// TokenContract: "tokenContract", +// BatchNonce: 202, +// }, +// }, nil +// }, +// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { +// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do +// }, +// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { +// return &types.Valset{Nonce: 202}, nil +// }, +// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { +// return &tmctypes.ResultBlock{ +// Block: &tmtypes.Block{ +// Header: tmtypes.Header{ +// Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), +// }, +// }, +// }, nil +// }, +// } +// +// eth := mockEthereum{ +// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { +// return big.NewInt(201), nil +// }, +// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { +// return &ctypes.Header{Number: big.NewInt(100)}, nil +// }, +// +// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { +// return big.NewInt(100), nil +// }, +// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { +// return []*wrappers.PeggyValsetUpdatedEvent{ +// { +// NewValsetNonce: big.NewInt(202), +// RewardAmount: big.NewInt(1000), +// RewardToken: common.HexToAddress("0xcafecafecafecafe"), +// }, +// }, nil +// }, +// sendTransactionBatchFn: func(_ context.Context, _ *types.Valset, _ *types.OutgoingTxBatch, _ []*types.MsgConfirmBatch) (*common.Hash, error) { +// return &common.Hash{}, nil +// }, +// } +// +// rel := &relayer{ +// log: suplog.DefaultLogger, +// retries: 1, +// batchRelaying: true, +// relayBatchOffsetDur: 5 * time.Second, +// } +// +// assert.NoError(t, rel.relayBatches(context.TODO(), inj, eth)) +// }) +//} diff --git a/orchestrator/signer_test.go b/orchestrator/signer_test.go index 286b871b..56f1ada9 100644 --- a/orchestrator/signer_test.go +++ b/orchestrator/signer_test.go @@ -1,139 +1,140 @@ package orchestrator -import ( - "context" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - log "github.com/xlab/suplog" - - "github.com/InjectiveLabs/sdk-go/chain/peggy/types" - cosmtypes "github.com/cosmos/cosmos-sdk/types" -) - -func TestEthSignerLoop(t *testing.T) { - t.Parallel() - - t.Run("failed to fetch peggy id from contract", func(t *testing.T) { - t.Parallel() - - orch := &PeggyOrchestrator{ - maxAttempts: 1, - eth: mockEthereum{ - getPeggyIDFn: func(context.Context) (common.Hash, error) { - return [32]byte{}, errors.New("fail") - }, - }, - } - - assert.Error(t, orch.EthSignerMainLoop(context.TODO())) - }) - - t.Run("no valset to sign", func(t *testing.T) { - t.Parallel() - - injective := &mockInjective{ - oldestUnsignedValsetsFn: func(context.Context) ([]*types.Valset, error) { - return nil, errors.New("fail") - }, - sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { - return nil - }, - oldestUnsignedTransactionBatchFn: func(context.Context) (*types.OutgoingTxBatch, error) { - return nil, nil - }, - sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { - return nil - }, - } - - sig := ðSigner{log: log.DefaultLogger, retries: 1} - - assert.NoError(t, sig.run(context.TODO(), injective)) - }) - - t.Run("failed to send valset confirm", func(t *testing.T) { - t.Parallel() - - injective := &mockInjective{ - oldestUnsignedValsetsFn: func(context.Context) ([]*types.Valset, error) { - return []*types.Valset{ - { - Nonce: 5, - Members: []*types.BridgeValidator{ - { - Power: 100, - EthereumAddress: "abcd", - }, - }, - Height: 500, - RewardAmount: cosmtypes.NewInt(123), - RewardToken: "dusanToken", - }, - }, nil - }, - sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { - return errors.New("fail") - }, - } - - sig := ðSigner{log: log.DefaultLogger, retries: 1} - - assert.Error(t, sig.run(context.TODO(), injective)) - }) - - t.Run("no transaction batch sign", func(t *testing.T) { - t.Parallel() - - injective := &mockInjective{ - oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { return nil, nil }, - sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, - oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { return nil, errors.New("fail") }, - sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { return nil }, - } - - sig := ðSigner{log: log.DefaultLogger, retries: 1} - - assert.NoError(t, sig.run(context.TODO(), injective)) - }) - - t.Run("failed to send batch confirm", func(t *testing.T) { - t.Parallel() - - injective := &mockInjective{ - oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { return nil, nil }, - sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, - oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { - return &types.OutgoingTxBatch{}, nil // non-empty will do - }, - sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { - return errors.New("fail") - }, - } - - sig := ðSigner{log: log.DefaultLogger, retries: 1} - - assert.Error(t, sig.run(context.TODO(), injective)) - }) - - t.Run("valset update and transaction batch are confirmed", func(t *testing.T) { - t.Parallel() - - injective := &mockInjective{ - oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { - return []*types.Valset{}, nil // non-empty will do - }, - oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { - return &types.OutgoingTxBatch{}, nil // non-empty will do - }, - sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, - sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { return nil }, - } - - sig := ðSigner{log: log.DefaultLogger, retries: 1} - - assert.NoError(t, sig.run(context.TODO(), injective)) - }) -} +// +//import ( +// "context" +// "testing" +// +// "github.com/ethereum/go-ethereum/common" +// "github.com/pkg/errors" +// "github.com/stretchr/testify/assert" +// log "github.com/xlab/suplog" +// +// "github.com/InjectiveLabs/sdk-go/chain/peggy/types" +// cosmtypes "github.com/cosmos/cosmos-sdk/types" +//) +// +//func TestEthSignerLoop(t *testing.T) { +// t.Parallel() +// +// t.Run("failed to fetch peggy id from contract", func(t *testing.T) { +// t.Parallel() +// +// orch := &PeggyOrchestrator{ +// maxAttempts: 1, +// eth: mockEthereum{ +// getPeggyIDFn: func(context.Context) (common.Hash, error) { +// return [32]byte{}, errors.New("fail") +// }, +// }, +// } +// +// assert.Error(t, orch.EthSignerMainLoop(context.TODO())) +// }) +// +// t.Run("no valset to sign", func(t *testing.T) { +// t.Parallel() +// +// injective := &mockInjective{ +// oldestUnsignedValsetsFn: func(context.Context) ([]*types.Valset, error) { +// return nil, errors.New("fail") +// }, +// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { +// return nil +// }, +// oldestUnsignedTransactionBatchFn: func(context.Context) (*types.OutgoingTxBatch, error) { +// return nil, nil +// }, +// sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { +// return nil +// }, +// } +// +// sig := ðSigner{log: log.DefaultLogger, retries: 1} +// +// assert.NoError(t, sig.run(context.TODO(), injective)) +// }) +// +// t.Run("failed to send valset confirm", func(t *testing.T) { +// t.Parallel() +// +// injective := &mockInjective{ +// oldestUnsignedValsetsFn: func(context.Context) ([]*types.Valset, error) { +// return []*types.Valset{ +// { +// Nonce: 5, +// Members: []*types.BridgeValidator{ +// { +// Power: 100, +// EthereumAddress: "abcd", +// }, +// }, +// Height: 500, +// RewardAmount: cosmtypes.NewInt(123), +// RewardToken: "dusanToken", +// }, +// }, nil +// }, +// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { +// return errors.New("fail") +// }, +// } +// +// sig := ðSigner{log: log.DefaultLogger, retries: 1} +// +// assert.Error(t, sig.run(context.TODO(), injective)) +// }) +// +// t.Run("no transaction batch sign", func(t *testing.T) { +// t.Parallel() +// +// injective := &mockInjective{ +// oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { return nil, nil }, +// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, +// oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { return nil, errors.New("fail") }, +// sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { return nil }, +// } +// +// sig := ðSigner{log: log.DefaultLogger, retries: 1} +// +// assert.NoError(t, sig.run(context.TODO(), injective)) +// }) +// +// t.Run("failed to send batch confirm", func(t *testing.T) { +// t.Parallel() +// +// injective := &mockInjective{ +// oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { return nil, nil }, +// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, +// oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { +// return &types.OutgoingTxBatch{}, nil // non-empty will do +// }, +// sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { +// return errors.New("fail") +// }, +// } +// +// sig := ðSigner{log: log.DefaultLogger, retries: 1} +// +// assert.Error(t, sig.run(context.TODO(), injective)) +// }) +// +// t.Run("valset update and transaction batch are confirmed", func(t *testing.T) { +// t.Parallel() +// +// injective := &mockInjective{ +// oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { +// return []*types.Valset{}, nil // non-empty will do +// }, +// oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { +// return &types.OutgoingTxBatch{}, nil // non-empty will do +// }, +// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, +// sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { return nil }, +// } +// +// sig := ðSigner{log: log.DefaultLogger, retries: 1} +// +// assert.NoError(t, sig.run(context.TODO(), injective)) +// }) +//} From 77d8835bb3731318e2c2cd1c011c1006e833025f Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Tue, 26 Dec 2023 15:55:12 +0100 Subject: [PATCH 21/35] fix oracle loop tests --- orchestrator/oracle.go | 21 +- orchestrator/oracle_test.go | 569 ++++++++++++++++++++---------------- 2 files changed, 328 insertions(+), 262 deletions(-) diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index a60dc58f..38d5951d 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -129,8 +129,8 @@ func (l *ethOracleLoop) loopFn(ctx context.Context) func() error { func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { var ( - latestHeight uint64 currentHeight = l.lastCheckedEthHeight + latestHeight uint64 ) scanEthBlocksAndRelayEventsFn := func() error { @@ -143,13 +143,22 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { return errors.Wrap(err, "failed to get latest ethereum header") } + latestHeight = latestHeader.Number.Uint64() + + if latestHeight < ethBlockConfirmationDelay { + latestHeight = currentHeight // no blocks scanned + return nil + } + // add delay to ensure minimum confirmations are received and block is finalised - latestHeight = latestHeader.Number.Uint64() - ethBlockConfirmationDelay - if latestHeight < currentHeight { + latestHeight = latestHeight - ethBlockConfirmationDelay + if latestHeight <= currentHeight { + latestHeight = currentHeight // no blocks scanned return nil } - if latestHeight > currentHeight+defaultBlocksToSearch { + // calculate right bound of block search + if currentHeight+defaultBlocksToSearch < latestHeight { latestHeight = currentHeight + defaultBlocksToSearch } @@ -185,7 +194,7 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { // atomically but lets not take that risk. lastClaimEvent, err := l.inj.LastClaimEvent(ctx) if err != nil { - return errors.New("failed to query last claim event from Injective") + return errors.Wrap(err, "failed to query last claim event from Injective") } legacyDeposits = filterSendToCosmosEventsByNonce(legacyDeposits, lastClaimEvent.EthereumEventNonce) @@ -199,8 +208,8 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { len(withdrawals) == 0 && len(erc20Deployments) == 0 && len(valsetUpdates) == 0 { - l.Logger().Debugln("no new events on Ethereum") + l.Logger().Debugln("no new events on Ethereum") return nil } diff --git a/orchestrator/oracle_test.go b/orchestrator/oracle_test.go index 9b179186..aa092d86 100644 --- a/orchestrator/oracle_test.go +++ b/orchestrator/oracle_test.go @@ -1,258 +1,315 @@ package orchestrator -// -//import ( -// "context" -// "errors" -// "math/big" -// "testing" -// "time" -// -// peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" -// "github.com/ethereum/go-ethereum/core/types" -// "github.com/stretchr/testify/assert" -// "github.com/xlab/suplog" -// -// wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" -//) -// -//func TestEthOracle(t *testing.T) { -// t.Parallel() -// -// t.Run("failed to get latest header from ethereum", func(t *testing.T) { -// t.Parallel() -// -// orch := &PeggyOrchestrator{ -// eth: mockEthereum{ -// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { -// return nil, errors.New("fail") -// }, -// }, -// } -// -// assert.Error(t, orch.EthOracleMainLoop(context.TODO())) -// }) -// -// t.Run("latest ethereum header is old", func(t *testing.T) { -// t.Parallel() -// -// ethereum := mockEthereum{ -// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { -// return &types.Header{Number: big.NewInt(50)}, nil -// }, -// } -// -// o := ðOracle{ -// log: suplog.DefaultLogger, -// retries: 1, -// lastResyncWithInjective: time.Now(), -// lastCheckedEthHeight: 100, -// } -// -// assert.NoError(t, o.run(context.TODO(), nil, ethereum)) -// assert.Equal(t, o.lastCheckedEthHeight, uint64(38)) -// }) -// -// t.Run("failed to get SendToCosmos events", func(t *testing.T) { -// t.Parallel() -// -// ethereum := mockEthereum{ -// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { -// return &types.Header{Number: big.NewInt(200)}, nil -// }, -// getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { -// return nil, errors.New("fail") -// }, -// } -// -// o := ðOracle{ -// log: suplog.DefaultLogger, -// retries: 1, -// lastResyncWithInjective: time.Now(), -// lastCheckedEthHeight: 100, -// } -// -// assert.Error(t, o.run(context.TODO(), nil, ethereum)) -// assert.Equal(t, o.lastCheckedEthHeight, uint64(100)) -// }) -// -// t.Run("failed to get last claim event from injective", func(t *testing.T) { -// t.Parallel() -// -// ethereum := mockEthereum{ -// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { -// return &types.Header{Number: big.NewInt(200)}, nil -// }, -// -// // no-ops -// getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { -// return nil, nil -// }, -// getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyTransactionBatchExecutedEvent, error) { -// return nil, nil -// }, -// getValsetUpdatedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return nil, nil -// }, -// getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyERC20DeployedEvent, error) { -// return nil, nil -// }, -// getSendToInjectiveEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToInjectiveEvent, error) { -// return nil, nil -// }, -// } -// -// injective := &mockInjective{ -// lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { -// return nil, errors.New("fail") -// }, -// } -// -// o := ðOracle{ -// log: suplog.DefaultLogger, -// retries: 1, -// lastResyncWithInjective: time.Now(), -// lastCheckedEthHeight: 100, -// } -// -// assert.Error(t, o.run(context.TODO(), injective, ethereum)) -// assert.Equal(t, o.lastCheckedEthHeight, uint64(100)) -// }) -// -// t.Run("old events are pruned", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { -// return &peggytypes.LastClaimEvent{EthereumEventNonce: 6}, nil -// }, -// sendEthereumClaimsFn: func( -// context.Context, -// uint64, -// []*wrappers.PeggySendToCosmosEvent, -// []*wrappers.PeggySendToInjectiveEvent, -// []*wrappers.PeggyTransactionBatchExecutedEvent, -// []*wrappers.PeggyERC20DeployedEvent, -// []*wrappers.PeggyValsetUpdatedEvent, -// ) error { -// return nil -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { -// return &types.Header{Number: big.NewInt(200)}, nil -// }, -// getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { -// return []*wrappers.PeggySendToCosmosEvent{{EventNonce: big.NewInt(5)}}, nil -// }, -// -// // no-ops -// getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyTransactionBatchExecutedEvent, error) { -// return nil, nil -// }, -// getValsetUpdatedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return nil, nil -// }, -// getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyERC20DeployedEvent, error) { -// return nil, nil -// }, -// getSendToInjectiveEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToInjectiveEvent, error) { -// return nil, nil -// }, -// } -// -// o := ðOracle{ -// log: suplog.DefaultLogger, -// retries: 1, -// lastResyncWithInjective: time.Now(), -// lastCheckedEthHeight: 100, -// } -// -// assert.NoError(t, o.run(context.TODO(), inj, eth)) -// assert.Equal(t, o.lastCheckedEthHeight, uint64(120)) -// assert.Equal(t, inj.sendEthereumClaimsCallCount, 0) -// }) -// -// t.Run("new events are sent to injective", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { -// return &peggytypes.LastClaimEvent{EthereumEventNonce: 6}, nil -// }, -// sendEthereumClaimsFn: func( -// context.Context, -// uint64, -// []*wrappers.PeggySendToCosmosEvent, -// []*wrappers.PeggySendToInjectiveEvent, -// []*wrappers.PeggyTransactionBatchExecutedEvent, -// []*wrappers.PeggyERC20DeployedEvent, -// []*wrappers.PeggyValsetUpdatedEvent, -// ) error { -// return nil -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { -// return &types.Header{Number: big.NewInt(200)}, nil -// }, -// getSendToCosmosEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToCosmosEvent, error) { -// return []*wrappers.PeggySendToCosmosEvent{{EventNonce: big.NewInt(10)}}, nil -// }, -// -// // no-ops -// getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyTransactionBatchExecutedEvent, error) { -// return nil, nil -// }, -// getValsetUpdatedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return nil, nil -// }, -// getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*wrappers.PeggyERC20DeployedEvent, error) { -// return nil, nil -// }, -// getSendToInjectiveEventsFn: func(uint64, uint64) ([]*wrappers.PeggySendToInjectiveEvent, error) { -// return nil, nil -// }, -// } -// -// o := ðOracle{ -// log: suplog.DefaultLogger, -// retries: 1, -// lastResyncWithInjective: time.Now(), -// lastCheckedEthHeight: 100, -// } -// -// assert.NoError(t, o.run(context.TODO(), inj, eth)) -// assert.Equal(t, o.lastCheckedEthHeight, uint64(120)) -// assert.Equal(t, inj.sendEthereumClaimsCallCount, 1) -// }) -// -// t.Run("auto resync", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// lastClaimEventFn: func(_ context.Context) (*peggytypes.LastClaimEvent, error) { -// return &peggytypes.LastClaimEvent{EthereumEventHeight: 101}, nil -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { -// return &types.Header{Number: big.NewInt(50)}, nil -// }, -// } -// -// o := ðOracle{ -// log: suplog.DefaultLogger, -// retries: 1, -// lastResyncWithInjective: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), -// lastCheckedEthHeight: 100, -// } -// -// assert.NoError(t, o.run(context.TODO(), inj, eth)) -// assert.Equal(t, o.lastCheckedEthHeight, uint64(101)) -// assert.True(t, time.Since(o.lastResyncWithInjective) < 1*time.Second) -// }) -//} +import ( + "context" + "errors" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" + "github.com/xlab/suplog" + + peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" + peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" +) + +func TestEthOracle(t *testing.T) { + t.Parallel() + + t.Run("failed to get latest header from ethereum", func(t *testing.T) { + t.Parallel() + + orch := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + eth: mockEthereum{ + headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { + return nil, errors.New("fail") + }, + }, + } + + assert.Error(t, orch.EthOracleMainLoop(context.TODO())) + }) + + t.Run("latest ethereum header is old", func(t *testing.T) { + t.Parallel() + + ethereum := mockEthereum{ + headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { + return &types.Header{Number: big.NewInt(50)}, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + eth: ethereum, + maxAttempts: 1, + } + + loop := ethOracleLoop{ + PeggyOrchestrator: o, + lastResyncWithInjective: time.Now(), + lastCheckedEthHeight: 100, + } + + loopFn := loop.loopFn(context.TODO()) + + assert.NoError(t, loopFn()) + assert.Equal(t, loop.lastCheckedEthHeight, uint64(100)) + }) + + t.Run("failed to get SendToCosmos events", func(t *testing.T) { + t.Parallel() + + ethereum := mockEthereum{ + headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { + return &types.Header{Number: big.NewInt(200)}, nil + }, + getSendToCosmosEventsFn: func(uint64, uint64) ([]*peggyevents.PeggySendToCosmosEvent, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + eth: ethereum, + maxAttempts: 1, + } + + loop := ethOracleLoop{ + PeggyOrchestrator: o, + lastResyncWithInjective: time.Now(), + lastCheckedEthHeight: 100, + } + + loopFn := loop.loopFn(context.TODO()) + + assert.Error(t, loopFn()) + assert.Equal(t, loop.lastCheckedEthHeight, uint64(100)) + }) + + t.Run("failed to get last claim event from injective", func(t *testing.T) { + t.Parallel() + + ethereum := mockEthereum{ + headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { + return &types.Header{Number: big.NewInt(200)}, nil + }, + + // no-ops + getSendToCosmosEventsFn: func(uint64, uint64) ([]*peggyevents.PeggySendToCosmosEvent, error) { + return nil, nil + }, + getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*peggyevents.PeggyTransactionBatchExecutedEvent, error) { + return nil, nil + }, + getValsetUpdatedEventsFn: func(uint64, uint64) ([]*peggyevents.PeggyValsetUpdatedEvent, error) { + return nil, nil + }, + getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*peggyevents.PeggyERC20DeployedEvent, error) { + return nil, nil + }, + getSendToInjectiveEventsFn: func(uint64, uint64) ([]*peggyevents.PeggySendToInjectiveEvent, error) { + return nil, nil + }, + } + + injective := &mockInjective{ + lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + eth: ethereum, + inj: injective, + maxAttempts: 1, + } + + loop := ethOracleLoop{ + PeggyOrchestrator: o, + lastResyncWithInjective: time.Now(), + lastCheckedEthHeight: 100, + } + + loopFn := loop.loopFn(context.TODO()) + + assert.Error(t, loopFn()) + assert.Equal(t, loop.lastCheckedEthHeight, uint64(100)) + }) + + t.Run("old events are pruned", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { + return &peggytypes.LastClaimEvent{EthereumEventNonce: 6}, nil + }, + sendEthereumClaimsFn: func( + context.Context, + uint64, + []*peggyevents.PeggySendToCosmosEvent, + []*peggyevents.PeggySendToInjectiveEvent, + []*peggyevents.PeggyTransactionBatchExecutedEvent, + []*peggyevents.PeggyERC20DeployedEvent, + []*peggyevents.PeggyValsetUpdatedEvent, + ) error { + return nil + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { + return &types.Header{Number: big.NewInt(200)}, nil + }, + getSendToCosmosEventsFn: func(uint64, uint64) ([]*peggyevents.PeggySendToCosmosEvent, error) { + return []*peggyevents.PeggySendToCosmosEvent{{EventNonce: big.NewInt(5)}}, nil + }, + + // no-ops + getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*peggyevents.PeggyTransactionBatchExecutedEvent, error) { + return nil, nil + }, + getValsetUpdatedEventsFn: func(uint64, uint64) ([]*peggyevents.PeggyValsetUpdatedEvent, error) { + return nil, nil + }, + getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*peggyevents.PeggyERC20DeployedEvent, error) { + return nil, nil + }, + getSendToInjectiveEventsFn: func(uint64, uint64) ([]*peggyevents.PeggySendToInjectiveEvent, error) { + return nil, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + eth: eth, + inj: inj, + maxAttempts: 1, + } + + loop := ethOracleLoop{ + PeggyOrchestrator: o, + lastResyncWithInjective: time.Now(), + lastCheckedEthHeight: 100, + } + + loopFn := loop.loopFn(context.TODO()) + + assert.NoError(t, loopFn()) + assert.Equal(t, loop.lastCheckedEthHeight, uint64(104)) + assert.Equal(t, inj.sendEthereumClaimsCallCount, 0) + }) + + t.Run("new events are sent to injective", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + lastClaimEventFn: func(context.Context) (*peggytypes.LastClaimEvent, error) { + return &peggytypes.LastClaimEvent{EthereumEventNonce: 6}, nil + }, + sendEthereumClaimsFn: func( + context.Context, + uint64, + []*peggyevents.PeggySendToCosmosEvent, + []*peggyevents.PeggySendToInjectiveEvent, + []*peggyevents.PeggyTransactionBatchExecutedEvent, + []*peggyevents.PeggyERC20DeployedEvent, + []*peggyevents.PeggyValsetUpdatedEvent, + ) error { + return nil + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { + return &types.Header{Number: big.NewInt(200)}, nil + }, + getSendToCosmosEventsFn: func(uint64, uint64) ([]*peggyevents.PeggySendToCosmosEvent, error) { + return []*peggyevents.PeggySendToCosmosEvent{{EventNonce: big.NewInt(10)}}, nil + }, + + // no-ops + getTransactionBatchExecutedEventsFn: func(uint64, uint64) ([]*peggyevents.PeggyTransactionBatchExecutedEvent, error) { + return nil, nil + }, + getValsetUpdatedEventsFn: func(uint64, uint64) ([]*peggyevents.PeggyValsetUpdatedEvent, error) { + return nil, nil + }, + getPeggyERC20DeployedEventsFn: func(uint64, uint64) ([]*peggyevents.PeggyERC20DeployedEvent, error) { + return nil, nil + }, + getSendToInjectiveEventsFn: func(uint64, uint64) ([]*peggyevents.PeggySendToInjectiveEvent, error) { + return nil, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + eth: eth, + inj: inj, + maxAttempts: 1, + } + + loop := ethOracleLoop{ + PeggyOrchestrator: o, + lastResyncWithInjective: time.Now(), + lastCheckedEthHeight: 100, + } + + loopFn := loop.loopFn(context.TODO()) + + assert.NoError(t, loopFn()) + assert.Equal(t, loop.lastCheckedEthHeight, uint64(104)) + assert.Equal(t, inj.sendEthereumClaimsCallCount, 1) + }) + + t.Run("auto resync", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + lastClaimEventFn: func(_ context.Context) (*peggytypes.LastClaimEvent, error) { + return &peggytypes.LastClaimEvent{EthereumEventHeight: 101}, nil + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(context.Context, *big.Int) (*types.Header, error) { + return &types.Header{Number: big.NewInt(50)}, nil + }, + } + + //o := ðOracle{ + // log: suplog.DefaultLogger, + // retries: 1, + // lastResyncWithInjective: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), + // lastCheckedEthHeight: 100, + //} + // + //assert.NoError(t, o.run(context.TODO(), inj, eth)) + //assert.Equal(t, o.lastCheckedEthHeight, uint64(101)) + //assert.True(t, time.Since(o.lastResyncWithInjective) < 1*time.Second) + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + eth: eth, + inj: inj, + maxAttempts: 1, + } + + loop := ethOracleLoop{ + PeggyOrchestrator: o, + lastResyncWithInjective: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), + lastCheckedEthHeight: 100, + } + + loopFn := loop.loopFn(context.TODO()) + + assert.NoError(t, loopFn()) + assert.Equal(t, loop.lastCheckedEthHeight, uint64(101)) + assert.True(t, time.Since(loop.lastResyncWithInjective) < 1*time.Second) + }) +} From b9d7ec2578cc22fad6eb36679a7180b3e2d737e9 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Wed, 27 Dec 2023 10:50:30 +0100 Subject: [PATCH 22/35] fix relayer loop tests --- orchestrator/relayer_test.go | 2439 ++++++++++++++++++---------------- 1 file changed, 1288 insertions(+), 1151 deletions(-) diff --git a/orchestrator/relayer_test.go b/orchestrator/relayer_test.go index d70778bc..ea0d2f50 100644 --- a/orchestrator/relayer_test.go +++ b/orchestrator/relayer_test.go @@ -1,1153 +1,1290 @@ package orchestrator -// -//import ( -// "context" -// "math/big" -// "testing" -// "time" -// -// tmctypes "github.com/cometbft/cometbft/rpc/core/types" -// tmtypes "github.com/cometbft/cometbft/types" -// cosmtypes "github.com/cosmos/cosmos-sdk/types" -// "github.com/ethereum/go-ethereum/common" -// ctypes "github.com/ethereum/go-ethereum/core/types" -// "github.com/pkg/errors" -// "github.com/stretchr/testify/assert" -// "github.com/xlab/suplog" -// -// wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" -// "github.com/InjectiveLabs/sdk-go/chain/peggy/types" -//) -// -//func TestValsetRelaying(t *testing.T) { -// t.Parallel() -// -// t.Run("failed to fetch latest valsets from injective", func(t *testing.T) { -// t.Parallel() -// -// injective := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.Error(t, rel.relayValsets(context.TODO(), injective, nil)) -// }) -// -// t.Run("failed to fetch confirms for a valset", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{{}}, nil // non-empty will do -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.Error(t, rel.relayValsets(context.TODO(), inj, nil)) -// }) -// -// t.Run("no confirms for valset", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{{}}, nil // non-empty will do -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return nil, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.NoError(t, rel.relayValsets(context.TODO(), inj, nil)) -// }) -// -// t.Run("failed to get latest ethereum header", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{{}}, nil // non-empty will do -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -// -// t.Run("failed to get latest ethereum header", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{{}}, nil // non-empty will do -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -// -// t.Run("failed to get valset nonce from peggy contract", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{{}}, nil // non-empty will do -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(123)}, nil -// }, -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -// -// t.Run("failed to get specific valset from injective", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{{}}, nil // non-empty will do -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return nil, errors.New("fail") -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(123)}, nil -// }, -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -// -// t.Run("failed to get valset update events from ethereum", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{{}}, nil // non-empty will do -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{}, nil // non-empty will do -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(123)}, nil -// }, -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -// -// t.Run("ethereum valset is not higher than injective valset", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{ -// { -// Nonce: 333, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, -// }, nil -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{ -// Nonce: 333, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, nil // non-empty will do -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(123)}, nil -// }, -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(333), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xfafafafafafafafa"), -// }, -// }, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.NoError(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -// -// t.Run("injective valset is higher than ethereum but failed to get block from injective", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{ -// { -// Nonce: 444, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, -// }, nil -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{ -// Nonce: 333, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, nil // non-empty will do -// }, -// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { -// return nil, errors.New("fail") -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(123)}, nil -// }, -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(333), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xfafafafafafafafa"), -// }, -// }, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// } -// -// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -// -// t.Run("injective valset is higher than ethereum but valsetOffsetDur has not expired", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{ -// { -// Nonce: 444, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, -// }, nil -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{ -// Nonce: 333, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, nil // non-empty will do -// }, -// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { -// return &tmctypes.ResultBlock{ -// Block: &tmtypes.Block{ -// Header: tmtypes.Header{ -// Time: time.Now().Add(time.Hour), -// }, -// }, -// }, nil -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(123)}, nil -// }, -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(333), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xfafafafafafafafa"), -// }, -// }, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// relayValsetOffsetDur: time.Second * 5, -// } -// -// assert.NoError(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -// -// t.Run("injective valset is higher than ethereum but failed to send update tx to ethereum", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{ -// { -// Nonce: 444, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, -// }, nil -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{ -// Nonce: 333, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, nil // non-empty will do -// }, -// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { -// return &tmctypes.ResultBlock{ -// Block: &tmtypes.Block{ -// Header: tmtypes.Header{ -// Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), -// }, -// }, -// }, nil -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(123)}, nil -// }, -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(333), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xfafafafafafafafa"), -// }, -// }, nil -// }, -// sendEthValsetUpdateFn: func(_ context.Context, _ *types.Valset, _ *types.Valset, _ []*types.MsgValsetConfirm) (*common.Hash, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// relayValsetOffsetDur: time.Second * 5, -// } -// -// assert.Error(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -// -// t.Run("new valset update is sent to ethereum", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{ -// { -// Nonce: 444, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, -// }, nil -// }, -// allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { -// return []*types.MsgValsetConfirm{ -// { -// Nonce: 5, -// Orchestrator: "orch", -// EthAddress: "eth", -// Signature: "sig", -// }, -// }, nil -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{ -// Nonce: 333, -// RewardAmount: cosmtypes.NewInt(1000), -// RewardToken: "0xfafafafafafafafa", -// }, nil -// }, -// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { -// return &tmctypes.ResultBlock{ -// Block: &tmtypes.Block{ -// Header: tmtypes.Header{ -// Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), -// }, -// }, -// }, nil -// }, -// } -// -// eth := mockEthereum{ -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(123)}, nil -// }, -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(333), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xfafafafafafafafa"), -// }, -// }, nil -// }, -// sendEthValsetUpdateFn: func(_ context.Context, _ *types.Valset, _ *types.Valset, _ []*types.MsgValsetConfirm) (*common.Hash, error) { -// return &common.Hash{}, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// valsetRelaying: true, -// relayValsetOffsetDur: time.Second * 5, -// } -// -// assert.NoError(t, rel.relayValsets(context.TODO(), inj, eth)) -// }) -//} -// -//func TestBatchRelaying(t *testing.T) { -// t.Parallel() -// -// t.Run("failed to get latest batches from injective", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.Error(t, rel.relayBatches(context.TODO(), inj, nil)) -// }) -// -// t.Run("failed to get latest batches from injective", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{{}}, nil // non-empty will do -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.Error(t, rel.relayBatches(context.TODO(), inj, nil)) -// }) -// -// t.Run("no batch confirms", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{{}}, nil // non-empty will do -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return nil, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.NoError(t, rel.relayBatches(context.TODO(), inj, nil)) -// }) -// -// t.Run("failed to get batch nonce from ethereum", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{{}}, nil // non-empty will do -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -// -// t.Run("failed to get latest ethereum header", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{ -// { -// TokenContract: "tokenContract", -// BatchNonce: 100, -// }, -// }, nil -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return big.NewInt(99), nil -// }, -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -// -// t.Run("failed to get valset nonce from ethereum", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{ -// { -// TokenContract: "tokenContract", -// BatchNonce: 100, -// }, -// }, nil -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return big.NewInt(99), nil -// }, -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(100)}, nil -// }, -// -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -// -// t.Run("failed to get specific valset from injective", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{ -// { -// TokenContract: "tokenContract", -// BatchNonce: 100, -// }, -// }, nil -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return nil, errors.New("fail") -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return big.NewInt(99), nil -// }, -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(100)}, nil -// }, -// -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -// -// t.Run("failed to get valset updated events from ethereum", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{ -// { -// TokenContract: "tokenContract", -// BatchNonce: 100, -// }, -// }, nil -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{}, nil -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return big.NewInt(99), nil -// }, -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(100)}, nil -// }, -// -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -// -// t.Run("ethereum batch is not lower than injective batch", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{ -// { -// TokenContract: "tokenContract", -// BatchNonce: 202, -// }, -// }, nil -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{Nonce: 202}, nil -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return big.NewInt(202), nil -// }, -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(100)}, nil -// }, -// -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(202), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xcafecafecafecafe"), -// }, -// }, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.NoError(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -// -// t.Run("ethereum batch is lower than injective batch but failed to get block from injhective", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{ -// { -// TokenContract: "tokenContract", -// BatchNonce: 202, -// }, -// }, nil -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{Nonce: 202}, nil -// }, -// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { -// return nil, errors.New("fail") -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return big.NewInt(201), nil -// }, -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(100)}, nil -// }, -// -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(202), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xcafecafecafecafe"), -// }, -// }, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// } -// -// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -// -// t.Run("ethereum batch is lower than injective batch but relayBatchOffsetDur has not expired", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{ -// { -// TokenContract: "tokenContract", -// BatchNonce: 202, -// }, -// }, nil -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{Nonce: 202}, nil -// }, -// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { -// return &tmctypes.ResultBlock{ -// Block: &tmtypes.Block{ -// Header: tmtypes.Header{ -// Time: time.Now().Add(time.Hour), -// }, -// }, -// }, nil -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return big.NewInt(201), nil -// }, -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(100)}, nil -// }, -// -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(202), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xcafecafecafecafe"), -// }, -// }, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// relayBatchOffsetDur: 5 * time.Second, -// } -// -// assert.NoError(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -// -// t.Run("ethereum batch is lower than injective batch but failed to send batch update", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{ -// { -// TokenContract: "tokenContract", -// BatchNonce: 202, -// }, -// }, nil -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{Nonce: 202}, nil -// }, -// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { -// return &tmctypes.ResultBlock{ -// Block: &tmtypes.Block{ -// Header: tmtypes.Header{ -// Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), -// }, -// }, -// }, nil -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return big.NewInt(201), nil -// }, -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(100)}, nil -// }, -// -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(202), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xcafecafecafecafe"), -// }, -// }, nil -// }, -// sendTransactionBatchFn: func(_ context.Context, _ *types.Valset, _ *types.OutgoingTxBatch, _ []*types.MsgConfirmBatch) (*common.Hash, error) { -// return nil, errors.New("fail") -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// relayBatchOffsetDur: 5 * time.Second, -// } -// -// assert.Error(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -// -// t.Run("sending a batch update to ethereum", func(t *testing.T) { -// t.Parallel() -// -// inj := &mockInjective{ -// latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { -// return []*types.OutgoingTxBatch{ -// { -// TokenContract: "tokenContract", -// BatchNonce: 202, -// }, -// }, nil -// }, -// transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { -// return []*types.MsgConfirmBatch{{}}, nil // non-nil will do -// }, -// valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { -// return &types.Valset{Nonce: 202}, nil -// }, -// getBlockFn: func(_ context.Context, _ int64) (*tmctypes.ResultBlock, error) { -// return &tmctypes.ResultBlock{ -// Block: &tmtypes.Block{ -// Header: tmtypes.Header{ -// Time: time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), -// }, -// }, -// }, nil -// }, -// } -// -// eth := mockEthereum{ -// getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { -// return big.NewInt(201), nil -// }, -// headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { -// return &ctypes.Header{Number: big.NewInt(100)}, nil -// }, -// -// getValsetNonceFn: func(_ context.Context) (*big.Int, error) { -// return big.NewInt(100), nil -// }, -// getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { -// return []*wrappers.PeggyValsetUpdatedEvent{ -// { -// NewValsetNonce: big.NewInt(202), -// RewardAmount: big.NewInt(1000), -// RewardToken: common.HexToAddress("0xcafecafecafecafe"), -// }, -// }, nil -// }, -// sendTransactionBatchFn: func(_ context.Context, _ *types.Valset, _ *types.OutgoingTxBatch, _ []*types.MsgConfirmBatch) (*common.Hash, error) { -// return &common.Hash{}, nil -// }, -// } -// -// rel := &relayer{ -// log: suplog.DefaultLogger, -// retries: 1, -// batchRelaying: true, -// relayBatchOffsetDur: 5 * time.Second, -// } -// -// assert.NoError(t, rel.relayBatches(context.TODO(), inj, eth)) -// }) -//} +import ( + "context" + wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" + cosmtypes "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" + ctypes "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/xlab/suplog" + "math/big" + "testing" + "time" + + "github.com/InjectiveLabs/sdk-go/chain/peggy/types" +) + +func TestValsetRelaying(t *testing.T) { + t.Parallel() + + t.Run("failed to fetch latest valsets from injective", func(t *testing.T) { + t.Parallel() + + injective := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: injective, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayValset(context.TODO())) + }) + + t.Run("failed to fetch confirms for a valset", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{{}}, nil // non-empty will do + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayValset(context.TODO())) + }) + + t.Run("no confirms for valset", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{{}}, nil // non-empty will do + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return nil, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.NoError(t, l.relayValset(context.TODO())) + }) + + t.Run("failed to get latest ethereum header", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{{}}, nil // non-empty will do + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayValset(context.TODO())) + }) + + t.Run("failed to get latest ethereum header", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{{}}, nil // non-empty will do + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayValset(context.TODO())) + }) + + t.Run("failed to get valset nonce from peggy contract", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{{}}, nil // non-empty will do + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(123)}, nil + }, + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayValset(context.TODO())) + }) + + t.Run("failed to get specific valset from injective", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{{}}, nil // non-empty will do + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return nil, errors.New("fail") + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(123)}, nil + }, + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayValset(context.TODO())) + }) + + t.Run("failed to get valset update events from ethereum", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{{}}, nil // non-empty will do + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{}, nil // non-empty will do + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(123)}, nil + }, + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayValset(context.TODO())) + }) + + t.Run("ethereum valset is not higher than injective valset", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{ + { + Nonce: 333, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, + }, nil + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{ + Nonce: 333, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, nil // non-empty will do + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(123)}, nil + }, + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(333), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xfafafafafafafafa"), + }, + }, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.NoError(t, l.relayValset(context.TODO())) + }) + + t.Run("injective valset is higher than ethereum but failed to get block from injective", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{ + { + Nonce: 444, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, + }, nil + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{ + Nonce: 333, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, nil // non-empty will do + }, + getBlockCreationTimeFn: func(_ context.Context, _ int64) (time.Time, error) { + return time.Time{}, errors.New("fail") + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(123)}, nil + }, + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(333), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xfafafafafafafafa"), + }, + }, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayValset(context.TODO())) + }) + + t.Run("injective valset is higher than ethereum but valsetOffsetDur has not expired", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{ + { + Nonce: 444, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, + }, nil + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{ + Nonce: 333, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, nil // non-empty will do + }, + getBlockCreationTimeFn: func(_ context.Context, _ int64) (time.Time, error) { + return time.Now().Add(time.Hour), nil + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(123)}, nil + }, + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(333), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xfafafafafafafafa"), + }, + }, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + relayValsetOffsetDur: time.Second * 5, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.NoError(t, l.relayValset(context.TODO())) + }) + + t.Run("injective valset is higher than ethereum but failed to send update tx to ethereum", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{ + { + Nonce: 444, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, + }, nil + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{ + Nonce: 333, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, nil // non-empty will do + }, + getBlockCreationTimeFn: func(_ context.Context, _ int64) (time.Time, error) { + return time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), nil + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(123)}, nil + }, + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(333), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xfafafafafafafafa"), + }, + }, nil + }, + sendEthValsetUpdateFn: func(_ context.Context, _ *types.Valset, _ *types.Valset, _ []*types.MsgValsetConfirm) (*common.Hash, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + relayValsetOffsetDur: time.Second * 5, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayValset(context.TODO())) + }) + + t.Run("new valset update is sent to ethereum", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{ + { + Nonce: 444, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, + }, nil + }, + allValsetConfirmsFn: func(_ context.Context, _ uint64) ([]*types.MsgValsetConfirm, error) { + return []*types.MsgValsetConfirm{ + { + Nonce: 5, + Orchestrator: "orch", + EthAddress: "eth", + Signature: "sig", + }, + }, nil + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{ + Nonce: 333, + RewardAmount: cosmtypes.NewInt(1000), + RewardToken: "0xfafafafafafafafa", + }, nil + }, + getBlockCreationTimeFn: func(_ context.Context, _ int64) (time.Time, error) { + return time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), nil + }, + } + + eth := mockEthereum{ + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(123)}, nil + }, + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(333), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xfafafafafafafafa"), + }, + }, nil + }, + sendEthValsetUpdateFn: func(_ context.Context, _ *types.Valset, _ *types.Valset, _ []*types.MsgValsetConfirm) (*common.Hash, error) { + return &common.Hash{}, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + valsetRelayEnabled: true, + relayValsetOffsetDur: time.Second * 5, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.NoError(t, l.relayValset(context.TODO())) + }) +} + +func TestBatchRelaying(t *testing.T) { + t.Parallel() + + t.Run("failed to get latest batches from injective", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayBatch(context.TODO())) + }) + + t.Run("failed to get latest batches from injective", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{{}}, nil // non-empty will do + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayBatch(context.TODO())) + }) + + t.Run("no batch confirms", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{{}}, nil // non-empty will do + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return nil, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.NoError(t, l.relayBatch(context.TODO())) + }) + + t.Run("failed to get batch nonce from ethereum", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{{}}, nil // non-empty will do + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayBatch(context.TODO())) + }) + + t.Run("failed to get latest ethereum header", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{ + { + TokenContract: "tokenContract", + BatchNonce: 100, + }, + }, nil + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(99), nil + }, + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayBatch(context.TODO())) + }) + + t.Run("failed to get valset nonce from ethereum", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{ + { + TokenContract: "tokenContract", + BatchNonce: 100, + }, + }, nil + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(99), nil + }, + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(100)}, nil + }, + + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayBatch(context.TODO())) + }) + + t.Run("failed to get specific valset from injective", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{ + { + TokenContract: "tokenContract", + BatchNonce: 100, + }, + }, nil + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return nil, errors.New("fail") + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(99), nil + }, + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(100)}, nil + }, + + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayBatch(context.TODO())) + }) + + t.Run("failed to get valset updated events from ethereum", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{ + { + TokenContract: "tokenContract", + BatchNonce: 100, + }, + }, nil + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{}, nil + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(99), nil + }, + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(100)}, nil + }, + + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayBatch(context.TODO())) + }) + + t.Run("ethereum batch is not lower than injective batch", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{ + { + TokenContract: "tokenContract", + BatchNonce: 202, + }, + }, nil + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{Nonce: 202}, nil + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(202), nil + }, + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(100)}, nil + }, + + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(202), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xcafecafecafecafe"), + }, + }, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.NoError(t, l.relayBatch(context.TODO())) + }) + + t.Run("ethereum batch is lower than injective batch but failed to get block from injhective", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{ + { + TokenContract: "tokenContract", + BatchNonce: 202, + }, + }, nil + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{Nonce: 202}, nil + }, + getBlockCreationTimeFn: func(_ context.Context, _ int64) (time.Time, error) { + return time.Time{}, errors.New("fail") + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(201), nil + }, + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(100)}, nil + }, + + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(202), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xcafecafecafecafe"), + }, + }, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayBatch(context.TODO())) + }) + + t.Run("ethereum batch is lower than injective batch but relayBatchOffsetDur has not expired", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{ + { + TokenContract: "tokenContract", + BatchNonce: 202, + }, + }, nil + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{Nonce: 202}, nil + }, + getBlockCreationTimeFn: func(_ context.Context, _ int64) (time.Time, error) { + return time.Now().Add(time.Hour), nil + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(201), nil + }, + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(100)}, nil + }, + + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(202), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xcafecafecafecafe"), + }, + }, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + relayBatchOffsetDur: time.Second * 5, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.NoError(t, l.relayBatch(context.TODO())) + }) + + t.Run("ethereum batch is lower than injective batch but failed to send batch update", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{ + { + TokenContract: "tokenContract", + BatchNonce: 202, + }, + }, nil + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{Nonce: 202}, nil + }, + getBlockCreationTimeFn: func(_ context.Context, _ int64) (time.Time, error) { + return time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), nil + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(201), nil + }, + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(100)}, nil + }, + + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(202), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xcafecafecafecafe"), + }, + }, nil + }, + sendTransactionBatchFn: func(_ context.Context, _ *types.Valset, _ *types.OutgoingTxBatch, _ []*types.MsgConfirmBatch) (*common.Hash, error) { + return nil, errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + relayBatchOffsetDur: time.Second * 5, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.Error(t, l.relayBatch(context.TODO())) + + }) + + t.Run("sending a batch update to ethereum", func(t *testing.T) { + t.Parallel() + + inj := &mockInjective{ + latestTransactionBatchesFn: func(_ context.Context) ([]*types.OutgoingTxBatch, error) { + return []*types.OutgoingTxBatch{ + { + TokenContract: "tokenContract", + BatchNonce: 202, + }, + }, nil + }, + transactionBatchSignaturesFn: func(_ context.Context, _ uint64, _ common.Address) ([]*types.MsgConfirmBatch, error) { + return []*types.MsgConfirmBatch{{}}, nil // non-nil will do + }, + valsetAtFn: func(_ context.Context, _ uint64) (*types.Valset, error) { + return &types.Valset{Nonce: 202}, nil + }, + getBlockCreationTimeFn: func(_ context.Context, _ int64) (time.Time, error) { + return time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC), nil + }, + } + + eth := mockEthereum{ + getTxBatchNonceFn: func(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(201), nil + }, + headerByNumberFn: func(_ context.Context, _ *big.Int) (*ctypes.Header, error) { + return &ctypes.Header{Number: big.NewInt(100)}, nil + }, + + getValsetNonceFn: func(_ context.Context) (*big.Int, error) { + return big.NewInt(100), nil + }, + getValsetUpdatedEventsFn: func(_ uint64, _ uint64) ([]*wrappers.PeggyValsetUpdatedEvent, error) { + return []*wrappers.PeggyValsetUpdatedEvent{ + { + NewValsetNonce: big.NewInt(202), + RewardAmount: big.NewInt(1000), + RewardToken: common.HexToAddress("0xcafecafecafecafe"), + }, + }, nil + }, + sendTransactionBatchFn: func(_ context.Context, _ *types.Valset, _ *types.OutgoingTxBatch, _ []*types.MsgConfirmBatch) (*common.Hash, error) { + return &common.Hash{}, nil + }, + } + + o := &PeggyOrchestrator{ + logger: suplog.DefaultLogger, + inj: inj, + eth: eth, + maxAttempts: 1, + batchRelayEnabled: true, + relayBatchOffsetDur: time.Second * 5, + } + + l := relayerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultRelayerLoopDur, + } + + assert.NoError(t, l.relayBatch(context.TODO())) + }) +} From 1e648c572abdfbf9679153d9c074549bde24a268 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Wed, 27 Dec 2023 10:56:14 +0100 Subject: [PATCH 23/35] fix signer loop tests --- orchestrator/signer_test.go | 329 +++++++++++++++++++++--------------- 1 file changed, 191 insertions(+), 138 deletions(-) diff --git a/orchestrator/signer_test.go b/orchestrator/signer_test.go index 56f1ada9..43d42e0f 100644 --- a/orchestrator/signer_test.go +++ b/orchestrator/signer_test.go @@ -1,140 +1,193 @@ package orchestrator -// -//import ( -// "context" -// "testing" -// -// "github.com/ethereum/go-ethereum/common" -// "github.com/pkg/errors" -// "github.com/stretchr/testify/assert" -// log "github.com/xlab/suplog" -// -// "github.com/InjectiveLabs/sdk-go/chain/peggy/types" -// cosmtypes "github.com/cosmos/cosmos-sdk/types" -//) -// -//func TestEthSignerLoop(t *testing.T) { -// t.Parallel() -// -// t.Run("failed to fetch peggy id from contract", func(t *testing.T) { -// t.Parallel() -// -// orch := &PeggyOrchestrator{ -// maxAttempts: 1, -// eth: mockEthereum{ -// getPeggyIDFn: func(context.Context) (common.Hash, error) { -// return [32]byte{}, errors.New("fail") -// }, -// }, -// } -// -// assert.Error(t, orch.EthSignerMainLoop(context.TODO())) -// }) -// -// t.Run("no valset to sign", func(t *testing.T) { -// t.Parallel() -// -// injective := &mockInjective{ -// oldestUnsignedValsetsFn: func(context.Context) ([]*types.Valset, error) { -// return nil, errors.New("fail") -// }, -// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { -// return nil -// }, -// oldestUnsignedTransactionBatchFn: func(context.Context) (*types.OutgoingTxBatch, error) { -// return nil, nil -// }, -// sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { -// return nil -// }, -// } -// -// sig := ðSigner{log: log.DefaultLogger, retries: 1} -// -// assert.NoError(t, sig.run(context.TODO(), injective)) -// }) -// -// t.Run("failed to send valset confirm", func(t *testing.T) { -// t.Parallel() -// -// injective := &mockInjective{ -// oldestUnsignedValsetsFn: func(context.Context) ([]*types.Valset, error) { -// return []*types.Valset{ -// { -// Nonce: 5, -// Members: []*types.BridgeValidator{ -// { -// Power: 100, -// EthereumAddress: "abcd", -// }, -// }, -// Height: 500, -// RewardAmount: cosmtypes.NewInt(123), -// RewardToken: "dusanToken", -// }, -// }, nil -// }, -// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { -// return errors.New("fail") -// }, -// } -// -// sig := ðSigner{log: log.DefaultLogger, retries: 1} -// -// assert.Error(t, sig.run(context.TODO(), injective)) -// }) -// -// t.Run("no transaction batch sign", func(t *testing.T) { -// t.Parallel() -// -// injective := &mockInjective{ -// oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { return nil, nil }, -// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, -// oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { return nil, errors.New("fail") }, -// sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { return nil }, -// } -// -// sig := ðSigner{log: log.DefaultLogger, retries: 1} -// -// assert.NoError(t, sig.run(context.TODO(), injective)) -// }) -// -// t.Run("failed to send batch confirm", func(t *testing.T) { -// t.Parallel() -// -// injective := &mockInjective{ -// oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { return nil, nil }, -// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, -// oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { -// return &types.OutgoingTxBatch{}, nil // non-empty will do -// }, -// sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { -// return errors.New("fail") -// }, -// } -// -// sig := ðSigner{log: log.DefaultLogger, retries: 1} -// -// assert.Error(t, sig.run(context.TODO(), injective)) -// }) -// -// t.Run("valset update and transaction batch are confirmed", func(t *testing.T) { -// t.Parallel() -// -// injective := &mockInjective{ -// oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { -// return []*types.Valset{}, nil // non-empty will do -// }, -// oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { -// return &types.OutgoingTxBatch{}, nil // non-empty will do -// }, -// sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, -// sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { return nil }, -// } -// -// sig := ðSigner{log: log.DefaultLogger, retries: 1} -// -// assert.NoError(t, sig.run(context.TODO(), injective)) -// }) -//} +import ( + "context" + "github.com/InjectiveLabs/sdk-go/chain/peggy/types" + cosmtypes "github.com/cosmos/cosmos-sdk/types" + log "github.com/xlab/suplog" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" +) + +func TestEthSignerLoop(t *testing.T) { + t.Parallel() + + t.Run("failed to fetch peggy id from contract", func(t *testing.T) { + t.Parallel() + + orch := &PeggyOrchestrator{ + maxAttempts: 1, + eth: mockEthereum{ + getPeggyIDFn: func(context.Context) (common.Hash, error) { + return [32]byte{}, errors.New("fail") + }, + }, + } + + assert.Error(t, orch.EthSignerMainLoop(context.TODO())) + }) + + t.Run("no valset to sign", func(t *testing.T) { + t.Parallel() + + injective := &mockInjective{ + oldestUnsignedValsetsFn: func(context.Context) ([]*types.Valset, error) { + return nil, errors.New("fail") + }, + sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { + return nil + }, + oldestUnsignedTransactionBatchFn: func(context.Context) (*types.OutgoingTxBatch, error) { + return nil, nil + }, + sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { + return nil + }, + } + + o := &PeggyOrchestrator{ + logger: log.DefaultLogger, + inj: injective, + maxAttempts: 1, + } + + l := ethSignerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultLoopDur, + } + + loopFn := l.loopFn(context.TODO()) + + assert.NoError(t, loopFn()) + }) + + t.Run("failed to send valset confirm", func(t *testing.T) { + t.Parallel() + + injective := &mockInjective{ + oldestUnsignedValsetsFn: func(context.Context) ([]*types.Valset, error) { + return []*types.Valset{ + { + Nonce: 5, + Members: []*types.BridgeValidator{ + { + Power: 100, + EthereumAddress: "abcd", + }, + }, + Height: 500, + RewardAmount: cosmtypes.NewInt(123), + RewardToken: "dusanToken", + }, + }, nil + }, + sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { + return errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: log.DefaultLogger, + inj: injective, + maxAttempts: 1, + } + + l := ethSignerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultLoopDur, + } + + loopFn := l.loopFn(context.TODO()) + + assert.Error(t, loopFn()) + }) + + t.Run("no transaction batch sign", func(t *testing.T) { + t.Parallel() + + injective := &mockInjective{ + oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { return nil, nil }, + sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, + oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { return nil, errors.New("fail") }, + sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { return nil }, + } + + o := &PeggyOrchestrator{ + logger: log.DefaultLogger, + inj: injective, + maxAttempts: 1, + } + + l := ethSignerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultLoopDur, + } + + loopFn := l.loopFn(context.TODO()) + + assert.NoError(t, loopFn()) + }) + + t.Run("failed to send batch confirm", func(t *testing.T) { + t.Parallel() + + injective := &mockInjective{ + oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { return nil, nil }, + sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, + oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { + return &types.OutgoingTxBatch{}, nil // non-empty will do + }, + sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { + return errors.New("fail") + }, + } + + o := &PeggyOrchestrator{ + logger: log.DefaultLogger, + inj: injective, + maxAttempts: 1, + } + + l := ethSignerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultLoopDur, + } + + loopFn := l.loopFn(context.TODO()) + + assert.Error(t, loopFn()) + }) + + t.Run("valset update and transaction batch are confirmed", func(t *testing.T) { + t.Parallel() + + injective := &mockInjective{ + oldestUnsignedValsetsFn: func(_ context.Context) ([]*types.Valset, error) { + return []*types.Valset{}, nil // non-empty will do + }, + oldestUnsignedTransactionBatchFn: func(_ context.Context) (*types.OutgoingTxBatch, error) { + return &types.OutgoingTxBatch{}, nil // non-empty will do + }, + sendValsetConfirmFn: func(context.Context, common.Hash, *types.Valset, common.Address) error { return nil }, + sendBatchConfirmFn: func(context.Context, common.Hash, *types.OutgoingTxBatch, common.Address) error { return nil }, + } + + o := &PeggyOrchestrator{ + logger: log.DefaultLogger, + inj: injective, + maxAttempts: 1, + } + + l := ethSignerLoop{ + PeggyOrchestrator: o, + loopDuration: defaultLoopDur, + } + + loopFn := l.loopFn(context.TODO()) + + assert.NoError(t, loopFn()) + }) +} From e6e421f9b03a28ebcdc3f69591fbb8cf6241e1a3 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Wed, 27 Dec 2023 12:34:09 +0100 Subject: [PATCH 24/35] refactor --- orchestrator/batch_request.go | 38 ++++++------- orchestrator/batch_request_test.go | 13 ++--- orchestrator/oracle.go | 86 ++++++++++++++---------------- orchestrator/oracle_test.go | 35 +++--------- orchestrator/relayer.go | 45 ++++++++++++++-- orchestrator/signer.go | 22 ++++---- orchestrator/signer_test.go | 27 ++++------ 7 files changed, 133 insertions(+), 133 deletions(-) diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index e2d04fbd..5512b9d0 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -33,31 +33,31 @@ func (l *batchRequestLoop) Logger() log.Logger { } func (l *batchRequestLoop) Run(ctx context.Context) error { - return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx)) + return loops.RunLoop(ctx, l.loopDuration, func() error { + return l.requestBatches(ctx) + }) } -func (l *batchRequestLoop) loopFn(ctx context.Context) func() error { - return func() error { - fees, err := l.getUnbatchedTokenFees(ctx) - if err != nil { - // non-fatal, just alert - l.Logger().WithError(err).Warningln("unable to get outgoing withdrawal fees") - return nil - } - - if len(fees) == 0 { - l.Logger().Debugln("no outgoing withdrawals to batch") - return nil - } +func (l *batchRequestLoop) requestBatches(ctx context.Context) error { + fees, err := l.getUnbatchedTokenFees(ctx) + if err != nil { + // non-fatal, just alert + l.Logger().WithError(err).Warningln("unable to get outgoing withdrawal fees") + return nil + } - for _, fee := range fees { - l.requestBatch(ctx, fee) + if len(fees) == 0 { + l.Logger().Debugln("no outgoing withdrawals to batch") + return nil + } - // todo: in case of multiple requests, we should sleep in between (non-continuous nonce) - } + for _, fee := range fees { + l.requestBatch(ctx, fee) - return nil + // todo: in case of multiple requests, we should sleep in between (non-continuous nonce) } + + return nil } func (l *batchRequestLoop) getUnbatchedTokenFees(ctx context.Context) ([]*types.BatchFees, error) { diff --git a/orchestrator/batch_request_test.go b/orchestrator/batch_request_test.go index 6f338159..3ae46e36 100644 --- a/orchestrator/batch_request_test.go +++ b/orchestrator/batch_request_test.go @@ -35,8 +35,7 @@ func TestRequestBatches(t *testing.T) { PeggyOrchestrator: o, } - loopFn := loop.loopFn(context.TODO()) - assert.NoError(t, loopFn()) + assert.NoError(t, loop.requestBatches(context.TODO())) }) t.Run("no unbatched tokens", func(t *testing.T) { @@ -58,8 +57,8 @@ func TestRequestBatches(t *testing.T) { PeggyOrchestrator: o, } - loopFn := loop.loopFn(context.TODO()) - assert.NoError(t, loopFn()) + assert.NoError(t, loop.requestBatches(context.TODO())) + }) t.Run("batch does not meet fee threshold", func(t *testing.T) { @@ -97,8 +96,7 @@ func TestRequestBatches(t *testing.T) { PeggyOrchestrator: o, } - loopFn := loop.loopFn(context.TODO()) - assert.NoError(t, loopFn()) + assert.NoError(t, loop.requestBatches(context.TODO())) assert.Equal(t, inj.sendRequestBatchCallCount, 0) }) @@ -137,8 +135,7 @@ func TestRequestBatches(t *testing.T) { PeggyOrchestrator: o, } - loopFn := loop.loopFn(context.TODO()) - assert.NoError(t, loopFn()) + assert.NoError(t, loop.requestBatches(context.TODO())) assert.Equal(t, inj.sendRequestBatchCallCount, 1) }) diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index 38d5951d..9112e89b 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -10,7 +10,7 @@ import ( "github.com/InjectiveLabs/metrics" "github.com/InjectiveLabs/peggo/orchestrator/loops" - wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" + peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" ) // todo: this is outdated, need to update @@ -97,34 +97,34 @@ func (l *ethOracleLoop) Logger() log.Logger { } func (l *ethOracleLoop) Run(ctx context.Context) error { - return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx)) + return loops.RunLoop(ctx, l.loopDuration, func() error { + return l.observeEthEvents(ctx) + }) } -func (l *ethOracleLoop) loopFn(ctx context.Context) func() error { - return func() error { - newHeight, err := l.relayEvents(ctx) - if err != nil { - return err - } +func (l *ethOracleLoop) observeEthEvents(ctx context.Context) error { + newHeight, err := l.relayEvents(ctx) + if err != nil { + return err + } - l.Logger().WithFields(log.Fields{"block_start": l.lastCheckedEthHeight, "block_end": newHeight}).Debugln("scanned Ethereum blocks for events") - l.lastCheckedEthHeight = newHeight - - if time.Since(l.lastResyncWithInjective) >= 48*time.Hour { - /** - Auto re-sync to catch up the nonce. Reasons why event nonce fall behind. - 1. It takes some time for events to be indexed on Ethereum. So if peggo queried events immediately as block produced, there is a chance the event is missed. - we need to re-scan this block to ensure events are not missed due to indexing delay. - 2. if validator was in UnBonding state, the claims broadcasted in last iteration are failed. - 3. if infura call failed while filtering events, the peggo missed to broadcast claim events occured in last iteration. - **/ - if err := l.autoResync(ctx); err != nil { - return err - } + l.Logger().WithFields(log.Fields{"block_start": l.lastCheckedEthHeight, "block_end": newHeight}).Debugln("scanned Ethereum blocks for events") + l.lastCheckedEthHeight = newHeight + + if time.Since(l.lastResyncWithInjective) >= 48*time.Hour { + /** + Auto re-sync to catch up the nonce. Reasons why event nonce fall behind. + 1. It takes some time for events to be indexed on Ethereum. So if peggo queried events immediately as block produced, there is a chance the event is missed. + we need to re-scan this block to ensure events are not missed due to indexing delay. + 2. if validator was in UnBonding state, the claims broadcasted in last iteration are failed. + 3. if infura call failed while filtering events, the peggo missed to broadcast claim events occured in last iteration. + **/ + if err := l.autoResync(ctx); err != nil { + return err } - - return nil } + + return nil } func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { @@ -203,12 +203,8 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { erc20Deployments = filterERC20DeployedEventsByNonce(erc20Deployments, lastClaimEvent.EthereumEventNonce) valsetUpdates = filterValsetUpdateEventsByNonce(valsetUpdates, lastClaimEvent.EthereumEventNonce) - if len(legacyDeposits) == 0 && - len(deposits) == 0 && - len(withdrawals) == 0 && - len(erc20Deployments) == 0 && - len(valsetUpdates) == 0 { - + if noEvents := len(legacyDeposits) == 0 && len(deposits) == 0 && len(withdrawals) == 0 && + len(erc20Deployments) == 0 && len(valsetUpdates) == 0; noEvents { l.Logger().Debugln("no new events on Ethereum") return nil } @@ -277,10 +273,10 @@ func (l *ethOracleLoop) autoResync(ctx context.Context) error { } func filterSendToCosmosEventsByNonce( - events []*wrappers.PeggySendToCosmosEvent, + events []*peggyevents.PeggySendToCosmosEvent, nonce uint64, -) []*wrappers.PeggySendToCosmosEvent { - res := make([]*wrappers.PeggySendToCosmosEvent, 0, len(events)) +) []*peggyevents.PeggySendToCosmosEvent { + res := make([]*peggyevents.PeggySendToCosmosEvent, 0, len(events)) for _, ev := range events { if ev.EventNonce.Uint64() > nonce { @@ -292,10 +288,10 @@ func filterSendToCosmosEventsByNonce( } func filterSendToInjectiveEventsByNonce( - events []*wrappers.PeggySendToInjectiveEvent, + events []*peggyevents.PeggySendToInjectiveEvent, nonce uint64, -) []*wrappers.PeggySendToInjectiveEvent { - res := make([]*wrappers.PeggySendToInjectiveEvent, 0, len(events)) +) []*peggyevents.PeggySendToInjectiveEvent { + res := make([]*peggyevents.PeggySendToInjectiveEvent, 0, len(events)) for _, ev := range events { if ev.EventNonce.Uint64() > nonce { @@ -307,10 +303,10 @@ func filterSendToInjectiveEventsByNonce( } func filterTransactionBatchExecutedEventsByNonce( - events []*wrappers.PeggyTransactionBatchExecutedEvent, + events []*peggyevents.PeggyTransactionBatchExecutedEvent, nonce uint64, -) []*wrappers.PeggyTransactionBatchExecutedEvent { - res := make([]*wrappers.PeggyTransactionBatchExecutedEvent, 0, len(events)) +) []*peggyevents.PeggyTransactionBatchExecutedEvent { + res := make([]*peggyevents.PeggyTransactionBatchExecutedEvent, 0, len(events)) for _, ev := range events { if ev.EventNonce.Uint64() > nonce { @@ -322,10 +318,10 @@ func filterTransactionBatchExecutedEventsByNonce( } func filterERC20DeployedEventsByNonce( - events []*wrappers.PeggyERC20DeployedEvent, + events []*peggyevents.PeggyERC20DeployedEvent, nonce uint64, -) []*wrappers.PeggyERC20DeployedEvent { - res := make([]*wrappers.PeggyERC20DeployedEvent, 0, len(events)) +) []*peggyevents.PeggyERC20DeployedEvent { + res := make([]*peggyevents.PeggyERC20DeployedEvent, 0, len(events)) for _, ev := range events { if ev.EventNonce.Uint64() > nonce { @@ -337,10 +333,10 @@ func filterERC20DeployedEventsByNonce( } func filterValsetUpdateEventsByNonce( - events []*wrappers.PeggyValsetUpdatedEvent, + events []*peggyevents.PeggyValsetUpdatedEvent, nonce uint64, -) []*wrappers.PeggyValsetUpdatedEvent { - res := make([]*wrappers.PeggyValsetUpdatedEvent, 0, len(events)) +) []*peggyevents.PeggyValsetUpdatedEvent { + res := make([]*peggyevents.PeggyValsetUpdatedEvent, 0, len(events)) for _, ev := range events { if ev.EventNonce.Uint64() > nonce { diff --git a/orchestrator/oracle_test.go b/orchestrator/oracle_test.go index aa092d86..2d24fa87 100644 --- a/orchestrator/oracle_test.go +++ b/orchestrator/oracle_test.go @@ -54,9 +54,7 @@ func TestEthOracle(t *testing.T) { lastCheckedEthHeight: 100, } - loopFn := loop.loopFn(context.TODO()) - - assert.NoError(t, loopFn()) + assert.NoError(t, loop.observeEthEvents(context.TODO())) assert.Equal(t, loop.lastCheckedEthHeight, uint64(100)) }) @@ -84,9 +82,7 @@ func TestEthOracle(t *testing.T) { lastCheckedEthHeight: 100, } - loopFn := loop.loopFn(context.TODO()) - - assert.Error(t, loopFn()) + assert.Error(t, loop.observeEthEvents(context.TODO())) assert.Equal(t, loop.lastCheckedEthHeight, uint64(100)) }) @@ -135,9 +131,7 @@ func TestEthOracle(t *testing.T) { lastCheckedEthHeight: 100, } - loopFn := loop.loopFn(context.TODO()) - - assert.Error(t, loopFn()) + assert.Error(t, loop.observeEthEvents(context.TODO())) assert.Equal(t, loop.lastCheckedEthHeight, uint64(100)) }) @@ -197,9 +191,7 @@ func TestEthOracle(t *testing.T) { lastCheckedEthHeight: 100, } - loopFn := loop.loopFn(context.TODO()) - - assert.NoError(t, loopFn()) + assert.NoError(t, loop.observeEthEvents(context.TODO())) assert.Equal(t, loop.lastCheckedEthHeight, uint64(104)) assert.Equal(t, inj.sendEthereumClaimsCallCount, 0) }) @@ -260,9 +252,7 @@ func TestEthOracle(t *testing.T) { lastCheckedEthHeight: 100, } - loopFn := loop.loopFn(context.TODO()) - - assert.NoError(t, loopFn()) + assert.NoError(t, loop.observeEthEvents(context.TODO())) assert.Equal(t, loop.lastCheckedEthHeight, uint64(104)) assert.Equal(t, inj.sendEthereumClaimsCallCount, 1) }) @@ -282,17 +272,6 @@ func TestEthOracle(t *testing.T) { }, } - //o := ðOracle{ - // log: suplog.DefaultLogger, - // retries: 1, - // lastResyncWithInjective: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), - // lastCheckedEthHeight: 100, - //} - // - //assert.NoError(t, o.run(context.TODO(), inj, eth)) - //assert.Equal(t, o.lastCheckedEthHeight, uint64(101)) - //assert.True(t, time.Since(o.lastResyncWithInjective) < 1*time.Second) - o := &PeggyOrchestrator{ logger: suplog.DefaultLogger, eth: eth, @@ -306,9 +285,7 @@ func TestEthOracle(t *testing.T) { lastCheckedEthHeight: 100, } - loopFn := loop.loopFn(context.TODO()) - - assert.NoError(t, loopFn()) + assert.NoError(t, loop.observeEthEvents(context.TODO())) assert.Equal(t, loop.lastCheckedEthHeight, uint64(101)) assert.True(t, time.Since(loop.lastResyncWithInjective) < 1*time.Second) }) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index 1a0c3933..1d8d84df 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -14,7 +14,7 @@ import ( "github.com/InjectiveLabs/metrics" "github.com/InjectiveLabs/peggo/orchestrator/ethereum/util" "github.com/InjectiveLabs/peggo/orchestrator/loops" - wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" + peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" "github.com/InjectiveLabs/sdk-go/chain/peggy/types" ) @@ -42,7 +42,46 @@ func (l *relayerLoop) Logger() log.Logger { } func (l *relayerLoop) Run(ctx context.Context) error { - return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx)) + return loops.RunLoop(ctx, l.loopDuration, func() error { + return l.relayValsetsAndBatches(ctx) + }) +} + +func (l *relayerLoop) relayValsetsAndBatches(ctx context.Context) error { + var pg loops.ParanoidGroup + + if l.valsetRelayEnabled { + pg.Go(func() error { + return retry.Do(func() error { return l.relayValset(ctx) }, + retry.Context(ctx), + retry.Attempts(l.maxAttempts), + retry.OnRetry(func(n uint, err error) { + l.Logger().WithError(err).Warningf("failed to relay valsets, will retry (%d)", n) + }), + ) + }) + } + + if l.batchRelayEnabled { + pg.Go(func() error { + return retry.Do(func() error { return l.relayBatch(ctx) }, + retry.Context(ctx), + retry.Attempts(l.maxAttempts), + retry.OnRetry(func(n uint, err error) { + l.Logger().WithError(err).Warningf("failed to relay batches, will retry (%d)", n) + }), + ) + }) + } + + if pg.Initialized() { + if err := pg.Wait(); err != nil { + l.Logger().WithError(err).Errorln("got error, loop exits") + return err + } + } + + return nil } func (l *relayerLoop) loopFn(ctx context.Context) func() error { @@ -327,7 +366,7 @@ func (l *relayerLoop) findLatestValsetOnEth(ctx context.Context, injective Injec var ErrNotFound = errors.New("not found") -type PeggyValsetUpdatedEvents []*wrappers.PeggyValsetUpdatedEvent +type PeggyValsetUpdatedEvents []*peggyevents.PeggyValsetUpdatedEvent func (a PeggyValsetUpdatedEvents) Len() int { return len(a) } func (a PeggyValsetUpdatedEvents) Less(i, j int) bool { diff --git a/orchestrator/signer.go b/orchestrator/signer.go index b1170f44..6aa3b8d9 100644 --- a/orchestrator/signer.go +++ b/orchestrator/signer.go @@ -68,21 +68,21 @@ func (l *ethSignerLoop) Logger() log.Logger { } func (l *ethSignerLoop) Run(ctx context.Context) error { - return loops.RunLoop(ctx, l.loopDuration, l.loopFn(ctx)) + return loops.RunLoop(ctx, l.loopDuration, func() error { + return l.signBatchesAndValsets(ctx) + }) } -func (l *ethSignerLoop) loopFn(ctx context.Context) func() error { - return func() error { - if err := l.signNewValsetUpdates(ctx); err != nil { - return err - } - - if err := l.signNewBatch(ctx); err != nil { - return err - } +func (l *ethSignerLoop) signBatchesAndValsets(ctx context.Context) error { + if err := l.signNewValsetUpdates(ctx); err != nil { + return err + } - return nil + if err := l.signNewBatch(ctx); err != nil { + return err } + + return nil } func (l *ethSignerLoop) signNewValsetUpdates(ctx context.Context) error { diff --git a/orchestrator/signer_test.go b/orchestrator/signer_test.go index 43d42e0f..bf530ce6 100644 --- a/orchestrator/signer_test.go +++ b/orchestrator/signer_test.go @@ -2,14 +2,15 @@ package orchestrator import ( "context" - "github.com/InjectiveLabs/sdk-go/chain/peggy/types" - cosmtypes "github.com/cosmos/cosmos-sdk/types" - log "github.com/xlab/suplog" "testing" + cosmtypes "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + log "github.com/xlab/suplog" + + "github.com/InjectiveLabs/sdk-go/chain/peggy/types" ) func TestEthSignerLoop(t *testing.T) { @@ -59,9 +60,7 @@ func TestEthSignerLoop(t *testing.T) { loopDuration: defaultLoopDur, } - loopFn := l.loopFn(context.TODO()) - - assert.NoError(t, loopFn()) + assert.NoError(t, l.signBatchesAndValsets(context.TODO())) }) t.Run("failed to send valset confirm", func(t *testing.T) { @@ -100,9 +99,7 @@ func TestEthSignerLoop(t *testing.T) { loopDuration: defaultLoopDur, } - loopFn := l.loopFn(context.TODO()) - - assert.Error(t, loopFn()) + assert.Error(t, l.signBatchesAndValsets(context.TODO())) }) t.Run("no transaction batch sign", func(t *testing.T) { @@ -126,9 +123,7 @@ func TestEthSignerLoop(t *testing.T) { loopDuration: defaultLoopDur, } - loopFn := l.loopFn(context.TODO()) - - assert.NoError(t, loopFn()) + assert.NoError(t, l.signBatchesAndValsets(context.TODO())) }) t.Run("failed to send batch confirm", func(t *testing.T) { @@ -156,9 +151,7 @@ func TestEthSignerLoop(t *testing.T) { loopDuration: defaultLoopDur, } - loopFn := l.loopFn(context.TODO()) - - assert.Error(t, loopFn()) + assert.Error(t, l.signBatchesAndValsets(context.TODO())) }) t.Run("valset update and transaction batch are confirmed", func(t *testing.T) { @@ -186,8 +179,6 @@ func TestEthSignerLoop(t *testing.T) { loopDuration: defaultLoopDur, } - loopFn := l.loopFn(context.TODO()) - - assert.NoError(t, loopFn()) + assert.NoError(t, l.signBatchesAndValsets(context.TODO())) }) } From f017ed385b85865aef678a558dce7a9f2dd04079 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 28 Dec 2023 12:45:08 +0100 Subject: [PATCH 25/35] expand cosmos network to 2 types --- cmd/peggo/options.go | 2 - cmd/peggo/orchestrator.go | 88 +++++--- orchestrator/cosmos/custom_rpc.go | 203 ++++++++++++++++++ .../cosmos/{network.go => load_balanced.go} | 63 +++--- 4 files changed, 297 insertions(+), 59 deletions(-) create mode 100644 orchestrator/cosmos/custom_rpc.go rename orchestrator/cosmos/{network.go => load_balanced.go} (69%) diff --git a/cmd/peggo/options.go b/cmd/peggo/options.go index 271baeca..94181ad0 100644 --- a/cmd/peggo/options.go +++ b/cmd/peggo/options.go @@ -290,14 +290,12 @@ func initConfig(cmd *cli.Cmd) Config { Name: "cosmos-grpc", Desc: "Cosmos GRPC querying endpoint", EnvVar: "PEGGO_COSMOS_GRPC", - Value: "tcp://localhost:9090", }) cfg.tendermintRPC = cmd.String(cli.StringOpt{ Name: "tendermint-rpc", Desc: "Tendermint RPC endpoint", EnvVar: "PEGGO_TENDERMINT_RPC", - Value: "http://localhost:26657", }) cfg.cosmosGasPrices = cmd.String(cli.StringOpt{ diff --git a/cmd/peggo/orchestrator.go b/cmd/peggo/orchestrator.go index 7aac5956..8ca45cf8 100644 --- a/cmd/peggo/orchestrator.go +++ b/cmd/peggo/orchestrator.go @@ -2,12 +2,10 @@ package main import ( "context" - "github.com/InjectiveLabs/peggo/orchestrator/version" "os" "time" - ctypes "github.com/InjectiveLabs/sdk-go/chain/types" - ethcmn "github.com/ethereum/go-ethereum/common" + gethcommon "github.com/ethereum/go-ethereum/common" cli "github.com/jawher/mow.cli" "github.com/xlab/closer" log "github.com/xlab/suplog" @@ -16,6 +14,8 @@ import ( "github.com/InjectiveLabs/peggo/orchestrator/coingecko" "github.com/InjectiveLabs/peggo/orchestrator/cosmos" "github.com/InjectiveLabs/peggo/orchestrator/ethereum" + "github.com/InjectiveLabs/peggo/orchestrator/version" + chaintypes "github.com/InjectiveLabs/sdk-go/chain/types" ) // startOrchestrator action runs an infinite loop, @@ -24,7 +24,6 @@ import ( // $ peggo orchestrator func orchestratorCmd(cmd *cli.Cmd) { // orchestrator-specific CLI options - cfg := initConfig(cmd) cmd.Before = func() { initMetrics(cmd) @@ -34,6 +33,8 @@ func orchestratorCmd(cmd *cli.Cmd) { // ensure a clean exit defer closer.Close() + cfg := initConfig(cmd) + log.WithFields(log.Fields{ "version": version.AppVersion, "git": version.GitCommit, @@ -42,6 +43,7 @@ func orchestratorCmd(cmd *cli.Cmd) { "go_arch": version.GoArch, }).Infoln("peggo - peggy binary for Ethereum bridge") + // todo: remove if *cfg.cosmosUseLedger || *cfg.ethUseLedger { log.Fatalln("cannot use Ledger for peggo, since signatures must be realtime") } @@ -76,39 +78,68 @@ func orchestratorCmd(cmd *cli.Cmd) { "eth_addr": ethKeyFromAddress.String(), }).Infoln("starting peggo service") - // Connect to Injective network - injNetwork, err := cosmos.NewNetwork( - *cfg.cosmosChainID, - valAddress.String(), - *cfg.cosmosGRPC, - *cfg.cosmosGasPrices, - *cfg.tendermintRPC, - cosmosKeyring, - signerFn, - personalSignFn, - ) + var injective orchestrator.InjectiveNetwork + if customEndpointRPCs := *cfg.cosmosGRPC != "" && *cfg.tendermintRPC != ""; customEndpointRPCs { + injective, err = cosmos.NewCustomRPCNetwork( + *cfg.cosmosChainID, + valAddress.String(), + *cfg.cosmosGRPC, + *cfg.cosmosGasPrices, + *cfg.tendermintRPC, + cosmosKeyring, + signerFn, + personalSignFn, + ) + } else { + // load balanced connection + injective, err = cosmos.NewLoadBalancedNetwork( + *cfg.cosmosChainID, + valAddress.String(), + *cfg.cosmosGRPC, + *cfg.cosmosGasPrices, + *cfg.tendermintRPC, + cosmosKeyring, + signerFn, + personalSignFn, + ) + } + orShutdown(err) + // Connect to Injective network + //injNetwork, err := cosmos.NewLoadBalancedNetwork( + // *cfg.cosmosChainID, + // valAddress.String(), + // *cfg.cosmosGRPC, + // *cfg.cosmosGasPrices, + // *cfg.tendermintRPC, + // cosmosKeyring, + // signerFn, + // personalSignFn, + //) + //orShutdown(err) + + // todo // See if the provided ETH address belongs to a validator and determine in which mode peggo should run - isValidator, err := isValidatorAddress(injNetwork.PeggyQueryClient, ethKeyFromAddress) - if err != nil { - log.WithError(err).Fatalln("failed to query current validator set on Injective") - } + //isValidator, err := isValidatorAddress(injNetwork.PeggyQueryClient, ethKeyFromAddress) + //if err != nil { + // log.WithError(err).Fatalln("failed to query current validator set on Injective") + //} ctx, cancelFn := context.WithCancel(context.Background()) closer.Bind(cancelFn) // Construct erc20 token mapping - peggyParams, err := injNetwork.PeggyParams(ctx) + peggyParams, err := injective.PeggyParams(ctx) if err != nil { log.WithError(err).Fatalln("failed to query peggy params, is injectived running?") } - peggyContractAddr := ethcmn.HexToAddress(peggyParams.BridgeEthereumAddress) - injTokenAddr := ethcmn.HexToAddress(peggyParams.CosmosCoinErc20Contract) + peggyContractAddr := gethcommon.HexToAddress(peggyParams.BridgeEthereumAddress) + injTokenAddr := gethcommon.HexToAddress(peggyParams.CosmosCoinErc20Contract) - erc20ContractMapping := make(map[ethcmn.Address]string) - erc20ContractMapping[injTokenAddr] = ctypes.InjectiveCoin + erc20ContractMapping := make(map[gethcommon.Address]string) + erc20ContractMapping[injTokenAddr] = chaintypes.InjectiveCoin // Connect to ethereum network ethNetwork, err := ethereum.NewNetwork( @@ -127,7 +158,7 @@ func orchestratorCmd(cmd *cli.Cmd) { // Create peggo and run it peggo, err := orchestrator.NewPeggyOrchestrator( - injNetwork, + injective, ethNetwork, coingeckoFeed, erc20ContractMapping, @@ -140,7 +171,7 @@ func orchestratorCmd(cmd *cli.Cmd) { orShutdown(err) go func() { - if err := peggo.Run(ctx, isValidator); err != nil { + if err := peggo.Run(ctx, true); err != nil { //todo log.Errorln(err) os.Exit(1) } @@ -150,7 +181,8 @@ func orchestratorCmd(cmd *cli.Cmd) { } } -func isValidatorAddress(peggyQuery cosmos.PeggyQueryClient, addr ethcmn.Address) (bool, error) { +// todo: change check to GetDelegateKeyByEth +func isValidatorAddress(peggyQuery cosmos.PeggyQueryClient, addr gethcommon.Address) (bool, error) { ctx, cancelFn := context.WithTimeout(context.Background(), time.Second*30) defer cancelFn() @@ -161,7 +193,7 @@ func isValidatorAddress(peggyQuery cosmos.PeggyQueryClient, addr ethcmn.Address) var isValidator bool for _, validator := range currentValset.Members { - if ethcmn.HexToAddress(validator.EthereumAddress) == addr { + if gethcommon.HexToAddress(validator.EthereumAddress) == addr { isValidator = true } } diff --git a/orchestrator/cosmos/custom_rpc.go b/orchestrator/cosmos/custom_rpc.go new file mode 100644 index 00000000..1f9cbf1e --- /dev/null +++ b/orchestrator/cosmos/custom_rpc.go @@ -0,0 +1,203 @@ +package cosmos + +import ( + "context" + "github.com/InjectiveLabs/peggo/orchestrator/cosmos/tmclient" + "github.com/InjectiveLabs/peggo/orchestrator/ethereum/keystore" + peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" + "github.com/InjectiveLabs/sdk-go/chain/peggy/types" + peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" + chainclient "github.com/InjectiveLabs/sdk-go/client/chain" + "github.com/InjectiveLabs/sdk-go/client/common" + rpchttp "github.com/cometbft/cometbft/rpc/client/http" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + log "github.com/xlab/suplog" + "time" +) + +type CustomRPCNetwork struct { + tmclient.TendermintClient + PeggyQueryClient + PeggyBroadcastClient +} + +func loadCustomNetworkConfig(chainID, feeDenom, cosmosGRPC, tendermintRPC string) common.Network { + cfg := common.LoadNetwork("devnet", "") + cfg.Name = "custom" + cfg.ChainId = chainID + cfg.Fee_denom = feeDenom + cfg.TmEndpoint = tendermintRPC + cfg.ChainGrpcEndpoint = cosmosGRPC + cfg.ExplorerGrpcEndpoint = "" + cfg.LcdEndpoint = "" + cfg.ExplorerGrpcEndpoint = "" + + return cfg +} + +// NewCustomRPCNetwork creates a single endpoint connection to the Injective network +func NewCustomRPCNetwork( + chainID, + validatorAddress, + injectiveGRPC, + injectiveGasPrices, + tendermintRPC string, + keyring keyring.Keyring, + signerFn bind.SignerFn, + personalSignerFn keystore.PersonalSignFn, +) (*CustomRPCNetwork, error) { + clientCtx, err := chainclient.NewClientContext(chainID, validatorAddress, keyring) + if err != nil { + return nil, errors.Wrapf(err, "failed to create client context for Injective chain") + } + + tmRPC, err := rpchttp.New(tendermintRPC, "/websocket") + if err != nil { + return nil, errors.Wrapf(err, "failed to connect to Tendermint RPC %s", tendermintRPC) + } + + clientCtx = clientCtx.WithNodeURI(tendermintRPC) + clientCtx = clientCtx.WithClient(tmRPC) + + netCfg := loadCustomNetworkConfig(chainID, "inj", injectiveGRPC, tendermintRPC) + daemonClient, err := chainclient.NewChainClient(clientCtx, netCfg, common.OptionGasPrices(injectiveGasPrices)) + if err != nil { + return nil, errors.Wrapf(err, "failed to connect to Injective GRPC %s", injectiveGRPC) + } + + time.Sleep(1 * time.Second) + + daemonWaitCtx, cancelWait := context.WithTimeout(context.Background(), time.Minute) + defer cancelWait() + + grpcConn := daemonClient.QueryClient() + waitForService(daemonWaitCtx, grpcConn) + peggyQuerier := types.NewQueryClient(grpcConn) + + n := &CustomRPCNetwork{ + TendermintClient: tmclient.NewRPCClient(tendermintRPC), + PeggyQueryClient: NewPeggyQueryClient(peggyQuerier), + PeggyBroadcastClient: NewPeggyBroadcastClient(peggyQuerier, daemonClient, signerFn, personalSignerFn), + } + + log.WithFields(log.Fields{ + "chain_id": chainID, + "injective": injectiveGRPC, + "tendermint": tendermintRPC, + }).Infoln("connected to Injective network") + + return n, nil +} + +func (n *CustomRPCNetwork) GetBlockCreationTime(ctx context.Context, height int64) (time.Time, error) { + block, err := n.TendermintClient.GetBlock(ctx, height) + if err != nil { + return time.Time{}, err + } + + return block.Block.Time, nil +} + +//func (n *LoadBalancedNetwork) PeggyParams(ctx context.Context) (*peggytypes.Params, error) { +// return n.PeggyQueryClient.PeggyParams(ctx) +//} + +func (n *CustomRPCNetwork) LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) { + return n.LastClaimEventByAddr(ctx, n.AccFromAddress()) +} + +func (n *CustomRPCNetwork) SendEthereumClaims( + ctx context.Context, + lastClaimEvent uint64, + oldDeposits []*peggyevents.PeggySendToCosmosEvent, + deposits []*peggyevents.PeggySendToInjectiveEvent, + withdraws []*peggyevents.PeggyTransactionBatchExecutedEvent, + erc20Deployed []*peggyevents.PeggyERC20DeployedEvent, + valsetUpdates []*peggyevents.PeggyValsetUpdatedEvent, +) error { + return n.PeggyBroadcastClient.SendEthereumClaims(ctx, + lastClaimEvent, + oldDeposits, + deposits, + withdraws, + erc20Deployed, + valsetUpdates, + ) +} + +func (n *CustomRPCNetwork) UnbatchedTokenFees(ctx context.Context) ([]*peggytypes.BatchFees, error) { + return n.PeggyQueryClient.UnbatchedTokensWithFees(ctx) +} + +func (n *CustomRPCNetwork) SendRequestBatch(ctx context.Context, denom string) error { + return n.PeggyBroadcastClient.SendRequestBatch(ctx, denom) +} + +func (n *CustomRPCNetwork) OldestUnsignedValsets(ctx context.Context) ([]*peggytypes.Valset, error) { + return n.PeggyQueryClient.OldestUnsignedValsets(ctx, n.AccFromAddress()) +} + +func (n *CustomRPCNetwork) LatestValsets(ctx context.Context) ([]*peggytypes.Valset, error) { + return n.PeggyQueryClient.LatestValsets(ctx) +} + +func (n *CustomRPCNetwork) AllValsetConfirms(ctx context.Context, nonce uint64) ([]*peggytypes.MsgValsetConfirm, error) { + return n.PeggyQueryClient.AllValsetConfirms(ctx, nonce) +} + +func (n *CustomRPCNetwork) ValsetAt(ctx context.Context, nonce uint64) (*peggytypes.Valset, error) { + return n.PeggyQueryClient.ValsetAt(ctx, nonce) +} + +func (n *CustomRPCNetwork) SendValsetConfirm( + ctx context.Context, + peggyID gethcommon.Hash, + valset *peggytypes.Valset, + ethFrom gethcommon.Address, +) error { + return n.PeggyBroadcastClient.SendValsetConfirm(ctx, ethFrom, peggyID, valset) +} + +func (n *CustomRPCNetwork) OldestUnsignedTransactionBatch(ctx context.Context) (*peggytypes.OutgoingTxBatch, error) { + return n.PeggyQueryClient.OldestUnsignedTransactionBatch(ctx, n.AccFromAddress()) +} + +func (n *CustomRPCNetwork) LatestTransactionBatches(ctx context.Context) ([]*peggytypes.OutgoingTxBatch, error) { + return n.PeggyQueryClient.LatestTransactionBatches(ctx) +} + +func (n *CustomRPCNetwork) TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract gethcommon.Address) ([]*peggytypes.MsgConfirmBatch, error) { + return n.PeggyQueryClient.TransactionBatchSignatures(ctx, nonce, tokenContract) +} + +func (n *CustomRPCNetwork) SendBatchConfirm( + ctx context.Context, + peggyID gethcommon.Hash, + batch *peggytypes.OutgoingTxBatch, + ethFrom gethcommon.Address, +) error { + return n.PeggyBroadcastClient.SendBatchConfirm(ctx, ethFrom, peggyID, batch) +} + +// waitForService awaits an active ClientConn to a GRPC service. +//func waitForService(ctx context.Context, clientconn *grpc.ClientConn) { +// for { +// select { +// case <-ctx.Done(): +// log.Fatalln("GRPC service wait timed out") +// default: +// state := clientconn.GetState() +// +// if state != connectivity.Ready { +// log.WithField("state", state.String()).Warningln("state of GRPC connection not ready") +// time.Sleep(5 * time.Second) +// continue +// } +// +// return +// } +// } +//} diff --git a/orchestrator/cosmos/network.go b/orchestrator/cosmos/load_balanced.go similarity index 69% rename from orchestrator/cosmos/network.go rename to orchestrator/cosmos/load_balanced.go index 9ea64978..a2efe79d 100644 --- a/orchestrator/cosmos/network.go +++ b/orchestrator/cosmos/load_balanced.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/ethereum/go-ethereum/accounts/abi/bind" - ethcmn "github.com/ethereum/go-ethereum/common" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" log "github.com/xlab/suplog" "google.golang.org/grpc" @@ -16,20 +16,25 @@ import ( "github.com/InjectiveLabs/peggo/orchestrator/ethereum/keystore" peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" "github.com/InjectiveLabs/sdk-go/chain/peggy/types" - peggy "github.com/InjectiveLabs/sdk-go/chain/peggy/types" + peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" chainclient "github.com/InjectiveLabs/sdk-go/client/chain" "github.com/InjectiveLabs/sdk-go/client/common" explorerclient "github.com/InjectiveLabs/sdk-go/client/explorer" ) -type Network struct { +type LoadBalancedNetwork struct { //tmclient.TendermintClient PeggyQueryClient PeggyBroadcastClient explorerclient.ExplorerClient } -func NewNetwork( +// NewLoadBalancedNetwork creates a load balanced connection to the Injective network. +// The chainID argument decides which network Peggo will be connecting to: +// - injective-1 (mainnet) +// - injective-777 (devnet) +// - injective-888 (testnet) +func NewLoadBalancedNetwork( chainID, validatorAddress, injectiveGRPC, @@ -38,7 +43,7 @@ func NewNetwork( keyring keyring.Keyring, signerFn bind.SignerFn, personalSignerFn keystore.PersonalSignFn, -) (*Network, error) { +) (*LoadBalancedNetwork, error) { clientCtx, err := chainclient.NewClientContext(chainID, validatorAddress, keyring) if err != nil { return nil, errors.Wrapf(err, "failed to create client context for Injective chain") @@ -87,7 +92,7 @@ func NewNetwork( waitForService(daemonWaitCtx, grpcConn) peggyQuerier := types.NewQueryClient(grpcConn) - n := &Network{ + n := &LoadBalancedNetwork{ //TendermintClient: tmclient.NewRPCClient(tendermintRPC), PeggyQueryClient: NewPeggyQueryClient(peggyQuerier), PeggyBroadcastClient: NewPeggyBroadcastClient(peggyQuerier, daemonClient, signerFn, personalSignerFn), @@ -103,7 +108,7 @@ func NewNetwork( return n, nil } -func (n *Network) GetBlockCreationTime(ctx context.Context, height int64) (time.Time, error) { +func (n *LoadBalancedNetwork) GetBlockCreationTime(ctx context.Context, height int64) (time.Time, error) { block, err := n.ExplorerClient.GetBlock(ctx, strconv.FormatInt(height, 10)) if err != nil { return time.Time{}, err @@ -118,15 +123,15 @@ func (n *Network) GetBlockCreationTime(ctx context.Context, height int64) (time. //return n.TendermintClient.GetBlock(ctx, height) } -func (n *Network) PeggyParams(ctx context.Context) (*peggy.Params, error) { - return n.PeggyQueryClient.PeggyParams(ctx) -} +//func (n *LoadBalancedNetwork) PeggyParams(ctx context.Context) (*peggytypes.Params, error) { +// return n.PeggyQueryClient.PeggyParams(ctx) +//} -func (n *Network) LastClaimEvent(ctx context.Context) (*peggy.LastClaimEvent, error) { +func (n *LoadBalancedNetwork) LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) { return n.LastClaimEventByAddr(ctx, n.AccFromAddress()) } -func (n *Network) SendEthereumClaims( +func (n *LoadBalancedNetwork) SendEthereumClaims( ctx context.Context, lastClaimEvent uint64, oldDeposits []*peggyevents.PeggySendToCosmosEvent, @@ -145,56 +150,56 @@ func (n *Network) SendEthereumClaims( ) } -func (n *Network) UnbatchedTokenFees(ctx context.Context) ([]*peggy.BatchFees, error) { +func (n *LoadBalancedNetwork) UnbatchedTokenFees(ctx context.Context) ([]*peggytypes.BatchFees, error) { return n.PeggyQueryClient.UnbatchedTokensWithFees(ctx) } -func (n *Network) SendRequestBatch(ctx context.Context, denom string) error { +func (n *LoadBalancedNetwork) SendRequestBatch(ctx context.Context, denom string) error { return n.PeggyBroadcastClient.SendRequestBatch(ctx, denom) } -func (n *Network) OldestUnsignedValsets(ctx context.Context) ([]*peggy.Valset, error) { +func (n *LoadBalancedNetwork) OldestUnsignedValsets(ctx context.Context) ([]*peggytypes.Valset, error) { return n.PeggyQueryClient.OldestUnsignedValsets(ctx, n.AccFromAddress()) } -func (n *Network) LatestValsets(ctx context.Context) ([]*peggy.Valset, error) { +func (n *LoadBalancedNetwork) LatestValsets(ctx context.Context) ([]*peggytypes.Valset, error) { return n.PeggyQueryClient.LatestValsets(ctx) } -func (n *Network) AllValsetConfirms(ctx context.Context, nonce uint64) ([]*peggy.MsgValsetConfirm, error) { +func (n *LoadBalancedNetwork) AllValsetConfirms(ctx context.Context, nonce uint64) ([]*peggytypes.MsgValsetConfirm, error) { return n.PeggyQueryClient.AllValsetConfirms(ctx, nonce) } -func (n *Network) ValsetAt(ctx context.Context, nonce uint64) (*peggy.Valset, error) { +func (n *LoadBalancedNetwork) ValsetAt(ctx context.Context, nonce uint64) (*peggytypes.Valset, error) { return n.PeggyQueryClient.ValsetAt(ctx, nonce) } -func (n *Network) SendValsetConfirm( +func (n *LoadBalancedNetwork) SendValsetConfirm( ctx context.Context, - peggyID ethcmn.Hash, - valset *peggy.Valset, - ethFrom ethcmn.Address, + peggyID gethcommon.Hash, + valset *peggytypes.Valset, + ethFrom gethcommon.Address, ) error { return n.PeggyBroadcastClient.SendValsetConfirm(ctx, ethFrom, peggyID, valset) } -func (n *Network) OldestUnsignedTransactionBatch(ctx context.Context) (*peggy.OutgoingTxBatch, error) { +func (n *LoadBalancedNetwork) OldestUnsignedTransactionBatch(ctx context.Context) (*peggytypes.OutgoingTxBatch, error) { return n.PeggyQueryClient.OldestUnsignedTransactionBatch(ctx, n.AccFromAddress()) } -func (n *Network) LatestTransactionBatches(ctx context.Context) ([]*peggy.OutgoingTxBatch, error) { +func (n *LoadBalancedNetwork) LatestTransactionBatches(ctx context.Context) ([]*peggytypes.OutgoingTxBatch, error) { return n.PeggyQueryClient.LatestTransactionBatches(ctx) } -func (n *Network) TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract ethcmn.Address) ([]*peggy.MsgConfirmBatch, error) { +func (n *LoadBalancedNetwork) TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract gethcommon.Address) ([]*peggytypes.MsgConfirmBatch, error) { return n.PeggyQueryClient.TransactionBatchSignatures(ctx, nonce, tokenContract) } -func (n *Network) SendBatchConfirm( +func (n *LoadBalancedNetwork) SendBatchConfirm( ctx context.Context, - peggyID ethcmn.Hash, - batch *peggy.OutgoingTxBatch, - ethFrom ethcmn.Address, + peggyID gethcommon.Hash, + batch *peggytypes.OutgoingTxBatch, + ethFrom gethcommon.Address, ) error { return n.PeggyBroadcastClient.SendBatchConfirm(ctx, ethFrom, peggyID, batch) } From 3cb1440ceb3ddbacc76efc277f6f636ecc974b66 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 28 Dec 2023 14:12:41 +0100 Subject: [PATCH 26/35] run peggo relayer mode if eth addr isn't registered with peggy --- cmd/peggo/orchestrator.go | 26 ++------------------------ orchestrator/cosmos/custom_rpc.go | 1 + orchestrator/cosmos/load_balanced.go | 26 ++++---------------------- orchestrator/cosmos/query.go | 26 ++++++++++++++++++++++++++ orchestrator/injective.go | 9 +++++---- orchestrator/orchestrator.go | 12 ++++++++++-- 6 files changed, 48 insertions(+), 52 deletions(-) diff --git a/cmd/peggo/orchestrator.go b/cmd/peggo/orchestrator.go index 8ca45cf8..e9903d5d 100644 --- a/cmd/peggo/orchestrator.go +++ b/cmd/peggo/orchestrator.go @@ -2,13 +2,11 @@ package main import ( "context" - "os" - "time" - gethcommon "github.com/ethereum/go-ethereum/common" cli "github.com/jawher/mow.cli" "github.com/xlab/closer" log "github.com/xlab/suplog" + "os" "github.com/InjectiveLabs/peggo/orchestrator" "github.com/InjectiveLabs/peggo/orchestrator/coingecko" @@ -171,7 +169,7 @@ func orchestratorCmd(cmd *cli.Cmd) { orShutdown(err) go func() { - if err := peggo.Run(ctx, true); err != nil { //todo + if err := peggo.Run(ctx); err != nil { log.Errorln(err) os.Exit(1) } @@ -180,23 +178,3 @@ func orchestratorCmd(cmd *cli.Cmd) { closer.Hold() } } - -// todo: change check to GetDelegateKeyByEth -func isValidatorAddress(peggyQuery cosmos.PeggyQueryClient, addr gethcommon.Address) (bool, error) { - ctx, cancelFn := context.WithTimeout(context.Background(), time.Second*30) - defer cancelFn() - - currentValset, err := peggyQuery.CurrentValset(ctx) - if err != nil { - return false, err - } - - var isValidator bool - for _, validator := range currentValset.Members { - if gethcommon.HexToAddress(validator.EthereumAddress) == addr { - isValidator = true - } - } - - return isValidator, nil -} diff --git a/orchestrator/cosmos/custom_rpc.go b/orchestrator/cosmos/custom_rpc.go index 1f9cbf1e..0429dd3e 100644 --- a/orchestrator/cosmos/custom_rpc.go +++ b/orchestrator/cosmos/custom_rpc.go @@ -85,6 +85,7 @@ func NewCustomRPCNetwork( log.WithFields(log.Fields{ "chain_id": chainID, + "connection": "custom_rpc", "injective": injectiveGRPC, "tendermint": tendermintRPC, }).Infoln("connected to Injective network") diff --git a/orchestrator/cosmos/load_balanced.go b/orchestrator/cosmos/load_balanced.go index a2efe79d..3f17e3ea 100644 --- a/orchestrator/cosmos/load_balanced.go +++ b/orchestrator/cosmos/load_balanced.go @@ -23,7 +23,6 @@ import ( ) type LoadBalancedNetwork struct { - //tmclient.TendermintClient PeggyQueryClient PeggyBroadcastClient explorerclient.ExplorerClient @@ -49,17 +48,7 @@ func NewLoadBalancedNetwork( return nil, errors.Wrapf(err, "failed to create client context for Injective chain") } - //clientCtx = clientCtx.WithNodeURI(tendermintRPC) - - //tmRPC, err := rpchttp.New(tendermintRPC, "/websocket") - //if err != nil { - // return nil, errors.Wrapf(err, "failed to connect to Tendermint RPC %s", tendermintRPC) - //} - - //clientCtx = clientCtx.WithClient(tmRPC) - var networkName string - switch chainID { case "injective-1": networkName = "mainnet" @@ -72,7 +61,6 @@ func NewLoadBalancedNetwork( } netCfg := common.LoadNetwork(networkName, "lb") - explorer, err := explorerclient.NewExplorerClient(netCfg) if err != nil { return nil, err @@ -93,17 +81,12 @@ func NewLoadBalancedNetwork( peggyQuerier := types.NewQueryClient(grpcConn) n := &LoadBalancedNetwork{ - //TendermintClient: tmclient.NewRPCClient(tendermintRPC), PeggyQueryClient: NewPeggyQueryClient(peggyQuerier), PeggyBroadcastClient: NewPeggyBroadcastClient(peggyQuerier, daemonClient, signerFn, personalSignerFn), ExplorerClient: explorer, } - log.WithFields(log.Fields{ - "chain_id": chainID, - "injective": injectiveGRPC, - "tendermint": tendermintRPC, - }).Infoln("connected to Injective network") + log.WithFields(log.Fields{"chain_id": chainID, "connection": "load_balanced"}).Infoln("connected to Injective network") return n, nil } @@ -120,12 +103,11 @@ func (n *LoadBalancedNetwork) GetBlockCreationTime(ctx context.Context, height i } return blockTime, nil - //return n.TendermintClient.GetBlock(ctx, height) } -//func (n *LoadBalancedNetwork) PeggyParams(ctx context.Context) (*peggytypes.Params, error) { -// return n.PeggyQueryClient.PeggyParams(ctx) -//} +func (n *LoadBalancedNetwork) PeggyParams(ctx context.Context) (*peggytypes.Params, error) { + return n.PeggyQueryClient.PeggyParams(ctx) +} func (n *LoadBalancedNetwork) LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) { return n.LastClaimEventByAddr(ctx, n.AccFromAddress()) diff --git a/orchestrator/cosmos/query.go b/orchestrator/cosmos/query.go index 0140cb18..f37b6879 100644 --- a/orchestrator/cosmos/query.go +++ b/orchestrator/cosmos/query.go @@ -25,6 +25,7 @@ type PeggyQueryClient interface { LastClaimEventByAddr(ctx context.Context, validatorAccountAddress sdk.AccAddress) (*types.LastClaimEvent, error) PeggyParams(ctx context.Context) (*types.Params, error) + HasRegisteredEthAddress(ctx context.Context, addr ethcmn.Address) (bool, error) } func NewPeggyQueryClient(client types.QueryClient) PeggyQueryClient { @@ -43,6 +44,31 @@ type peggyQueryClient struct { var ErrNotFound = errors.New("not found") +func (s *peggyQueryClient) HasRegisteredEthAddress(ctx context.Context, addr ethcmn.Address) (bool, error) { + metrics.ReportFuncCall(s.svcTags) + doneFn := metrics.ReportFuncTiming(s.svcTags) + defer doneFn() + + req := &types.QueryDelegateKeysByEthAddress{EthAddress: addr.Hex()} + resp, err := s.daemonQueryClient.GetDelegateKeyByEth(ctx, req) + + if errors.Is(err, types.ErrInvalid) { + // no record found + return false, nil + } + + if err != nil { + metrics.ReportFuncError(s.svcTags) + return false, errors.Wrap(err, "failed to query GetDelegateKeyByEth from daemon") + } + + if resp == nil { + return false, nil + } + + return true, nil +} + func (s *peggyQueryClient) ValsetAt(ctx context.Context, nonce uint64) (*types.Valset, error) { metrics.ReportFuncCall(s.svcTags) doneFn := metrics.ReportFuncTiming(s.svcTags) diff --git a/orchestrator/injective.go b/orchestrator/injective.go index fda9cb67..66209d27 100644 --- a/orchestrator/injective.go +++ b/orchestrator/injective.go @@ -4,7 +4,7 @@ import ( "context" "time" - eth "github.com/ethereum/go-ethereum/common" + gethcommon "github.com/ethereum/go-ethereum/common" peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" @@ -14,6 +14,7 @@ import ( type InjectiveNetwork interface { PeggyParams(ctx context.Context) (*peggytypes.Params, error) GetBlockCreationTime(ctx context.Context, height int64) (time.Time, error) + HasRegisteredEthAddress(ctx context.Context, addr gethcommon.Address) (bool, error) LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) SendEthereumClaims(ctx context.Context, @@ -28,12 +29,12 @@ type InjectiveNetwork interface { UnbatchedTokenFees(ctx context.Context) ([]*peggytypes.BatchFees, error) SendRequestBatch(ctx context.Context, denom string) error OldestUnsignedTransactionBatch(ctx context.Context) (*peggytypes.OutgoingTxBatch, error) - SendBatchConfirm(ctx context.Context, peggyID eth.Hash, batch *peggytypes.OutgoingTxBatch, ethFrom eth.Address) error + SendBatchConfirm(ctx context.Context, peggyID gethcommon.Hash, batch *peggytypes.OutgoingTxBatch, ethFrom gethcommon.Address) error LatestTransactionBatches(ctx context.Context) ([]*peggytypes.OutgoingTxBatch, error) - TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract eth.Address) ([]*peggytypes.MsgConfirmBatch, error) + TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract gethcommon.Address) ([]*peggytypes.MsgConfirmBatch, error) OldestUnsignedValsets(ctx context.Context) ([]*peggytypes.Valset, error) - SendValsetConfirm(ctx context.Context, peggyID eth.Hash, valset *peggytypes.Valset, ethFrom eth.Address) error + SendValsetConfirm(ctx context.Context, peggyID gethcommon.Hash, valset *peggytypes.Valset, ethFrom gethcommon.Address) error LatestValsets(ctx context.Context) ([]*peggytypes.Valset, error) AllValsetConfirms(ctx context.Context, nonce uint64) ([]*peggytypes.MsgValsetConfirm, error) ValsetAt(ctx context.Context, nonce uint64) (*peggytypes.Valset, error) diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index 26cee586..89f71481 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -80,14 +80,22 @@ func NewPeggyOrchestrator( // Run starts all major loops required to make // up the Orchestrator, all of these are async loops. -func (s *PeggyOrchestrator) Run(ctx context.Context, validatorMode bool) error { - if !validatorMode { +func (s *PeggyOrchestrator) Run(ctx context.Context) error { + if !s.hasRegisteredETHAddress(ctx) { return s.startRelayerMode(ctx) } return s.startValidatorMode(ctx) } +func (s *PeggyOrchestrator) hasRegisteredETHAddress(ctx context.Context) bool { + subCtx, cancelFn := context.WithTimeout(ctx, 5*time.Second) + defer cancelFn() + + ok, _ := s.inj.HasRegisteredEthAddress(subCtx, s.eth.FromAddress()) + return ok +} + // startValidatorMode runs all orchestrator processes. This is called // when peggo is run alongside a validator injective node. func (s *PeggyOrchestrator) startValidatorMode(ctx context.Context) error { From 345375bff12763df692d4caa5d91fe09f652d3fd Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 28 Dec 2023 14:22:08 +0100 Subject: [PATCH 27/35] remove redundant parameters --- cmd/peggo/orchestrator.go | 49 ++++++++-------------------- cmd/peggo/tx.go | 1 - orchestrator/cosmos/broadcast.go | 2 -- orchestrator/cosmos/custom_rpc.go | 6 ++-- orchestrator/cosmos/load_balanced.go | 10 ++---- 5 files changed, 18 insertions(+), 50 deletions(-) diff --git a/cmd/peggo/orchestrator.go b/cmd/peggo/orchestrator.go index e9903d5d..060f7069 100644 --- a/cmd/peggo/orchestrator.go +++ b/cmd/peggo/orchestrator.go @@ -71,64 +71,41 @@ func orchestratorCmd(cmd *cli.Cmd) { log.WithError(err).Fatalln("failed to initialize Ethereum account") } - log.WithFields(log.Fields{ - "inj_addr": valAddress.String(), - "eth_addr": ethKeyFromAddress.String(), - }).Infoln("starting peggo service") + log.WithFields(log.Fields{"inj_addr": valAddress.String(), "eth_addr": ethKeyFromAddress.String()}).Infoln("starting peggo service") + + var ( + injectiveNet orchestrator.InjectiveNetwork + customEndpointRPCs = *cfg.cosmosGRPC != "" && *cfg.tendermintRPC != "" + ) - var injective orchestrator.InjectiveNetwork - if customEndpointRPCs := *cfg.cosmosGRPC != "" && *cfg.tendermintRPC != ""; customEndpointRPCs { - injective, err = cosmos.NewCustomRPCNetwork( + if customEndpointRPCs { + injectiveNet, err = cosmos.NewCustomRPCNetwork( *cfg.cosmosChainID, valAddress.String(), *cfg.cosmosGRPC, *cfg.cosmosGasPrices, *cfg.tendermintRPC, cosmosKeyring, - signerFn, personalSignFn, ) } else { // load balanced connection - injective, err = cosmos.NewLoadBalancedNetwork( + injectiveNet, err = cosmos.NewLoadBalancedNetwork( *cfg.cosmosChainID, valAddress.String(), - *cfg.cosmosGRPC, *cfg.cosmosGasPrices, - *cfg.tendermintRPC, cosmosKeyring, - signerFn, personalSignFn, ) } orShutdown(err) - // Connect to Injective network - //injNetwork, err := cosmos.NewLoadBalancedNetwork( - // *cfg.cosmosChainID, - // valAddress.String(), - // *cfg.cosmosGRPC, - // *cfg.cosmosGasPrices, - // *cfg.tendermintRPC, - // cosmosKeyring, - // signerFn, - // personalSignFn, - //) - //orShutdown(err) - - // todo - // See if the provided ETH address belongs to a validator and determine in which mode peggo should run - //isValidator, err := isValidatorAddress(injNetwork.PeggyQueryClient, ethKeyFromAddress) - //if err != nil { - // log.WithError(err).Fatalln("failed to query current validator set on Injective") - //} - ctx, cancelFn := context.WithCancel(context.Background()) closer.Bind(cancelFn) // Construct erc20 token mapping - peggyParams, err := injective.PeggyParams(ctx) + peggyParams, err := injectiveNet.PeggyParams(ctx) if err != nil { log.WithError(err).Fatalln("failed to query peggy params, is injectived running?") } @@ -140,7 +117,7 @@ func orchestratorCmd(cmd *cli.Cmd) { erc20ContractMapping[injTokenAddr] = chaintypes.InjectiveCoin // Connect to ethereum network - ethNetwork, err := ethereum.NewNetwork( + ethereumNet, err := ethereum.NewNetwork( *cfg.ethNodeRPC, peggyContractAddr, ethKeyFromAddress, @@ -156,8 +133,8 @@ func orchestratorCmd(cmd *cli.Cmd) { // Create peggo and run it peggo, err := orchestrator.NewPeggyOrchestrator( - injective, - ethNetwork, + injectiveNet, + ethereumNet, coingeckoFeed, erc20ContractMapping, *cfg.minBatchFeeUSD, diff --git a/cmd/peggo/tx.go b/cmd/peggo/tx.go index 39c30855..dc52f792 100644 --- a/cmd/peggo/tx.go +++ b/cmd/peggo/tx.go @@ -177,7 +177,6 @@ func registerEthKeyCmd(cmd *cli.Cmd) { peggyBroadcaster := cosmos.NewPeggyBroadcastClient( peggyQuerier, daemonClient, - nil, personalSignFn, ) cancelWait() diff --git a/orchestrator/cosmos/broadcast.go b/orchestrator/cosmos/broadcast.go index 9d4ae931..533c670b 100644 --- a/orchestrator/cosmos/broadcast.go +++ b/orchestrator/cosmos/broadcast.go @@ -79,13 +79,11 @@ type PeggyBroadcastClient interface { func NewPeggyBroadcastClient( queryClient types.QueryClient, broadcastClient chainclient.ChainClient, - ethSignerFn keystore.SignerFn, ethPersonalSignFn keystore.PersonalSignFn, ) PeggyBroadcastClient { return &peggyBroadcastClient{ daemonQueryClient: queryClient, broadcastClient: broadcastClient, - ethSignerFn: ethSignerFn, ethPersonalSignFn: ethPersonalSignFn, svcTags: metrics.Tags{ diff --git a/orchestrator/cosmos/custom_rpc.go b/orchestrator/cosmos/custom_rpc.go index 0429dd3e..5bf35412 100644 --- a/orchestrator/cosmos/custom_rpc.go +++ b/orchestrator/cosmos/custom_rpc.go @@ -11,7 +11,6 @@ import ( "github.com/InjectiveLabs/sdk-go/client/common" rpchttp "github.com/cometbft/cometbft/rpc/client/http" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/ethereum/go-ethereum/accounts/abi/bind" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" log "github.com/xlab/suplog" @@ -46,7 +45,6 @@ func NewCustomRPCNetwork( injectiveGasPrices, tendermintRPC string, keyring keyring.Keyring, - signerFn bind.SignerFn, personalSignerFn keystore.PersonalSignFn, ) (*CustomRPCNetwork, error) { clientCtx, err := chainclient.NewClientContext(chainID, validatorAddress, keyring) @@ -80,12 +78,12 @@ func NewCustomRPCNetwork( n := &CustomRPCNetwork{ TendermintClient: tmclient.NewRPCClient(tendermintRPC), PeggyQueryClient: NewPeggyQueryClient(peggyQuerier), - PeggyBroadcastClient: NewPeggyBroadcastClient(peggyQuerier, daemonClient, signerFn, personalSignerFn), + PeggyBroadcastClient: NewPeggyBroadcastClient(peggyQuerier, daemonClient, personalSignerFn), } log.WithFields(log.Fields{ "chain_id": chainID, - "connection": "custom_rpc", + "connection": "custom", "injective": injectiveGRPC, "tendermint": tendermintRPC, }).Infoln("connected to Injective network") diff --git a/orchestrator/cosmos/load_balanced.go b/orchestrator/cosmos/load_balanced.go index 3f17e3ea..c3c79680 100644 --- a/orchestrator/cosmos/load_balanced.go +++ b/orchestrator/cosmos/load_balanced.go @@ -6,7 +6,6 @@ import ( "time" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/ethereum/go-ethereum/accounts/abi/bind" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" log "github.com/xlab/suplog" @@ -36,11 +35,8 @@ type LoadBalancedNetwork struct { func NewLoadBalancedNetwork( chainID, validatorAddress, - injectiveGRPC, - injectiveGasPrices, - tendermintRPC string, + injectiveGasPrices string, keyring keyring.Keyring, - signerFn bind.SignerFn, personalSignerFn keystore.PersonalSignFn, ) (*LoadBalancedNetwork, error) { clientCtx, err := chainclient.NewClientContext(chainID, validatorAddress, keyring) @@ -68,7 +64,7 @@ func NewLoadBalancedNetwork( daemonClient, err := chainclient.NewChainClient(clientCtx, netCfg, common.OptionGasPrices(injectiveGasPrices)) if err != nil { - return nil, errors.Wrapf(err, "failed to connect to Injective GRPC %s", injectiveGRPC) + return nil, errors.Wrapf(err, "failed to connect to Injective network: %s", networkName) } time.Sleep(1 * time.Second) @@ -82,7 +78,7 @@ func NewLoadBalancedNetwork( n := &LoadBalancedNetwork{ PeggyQueryClient: NewPeggyQueryClient(peggyQuerier), - PeggyBroadcastClient: NewPeggyBroadcastClient(peggyQuerier, daemonClient, signerFn, personalSignerFn), + PeggyBroadcastClient: NewPeggyBroadcastClient(peggyQuerier, daemonClient, personalSignerFn), ExplorerClient: explorer, } From f8896ee56dc9a9865e19a08b70c6465a43e4459d Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 28 Dec 2023 16:04:54 +0100 Subject: [PATCH 28/35] logs --- orchestrator/orchestrator.go | 19 +++++++++---------- orchestrator/relayer.go | 11 ++++------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index 89f71481..0b0582ae 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -100,11 +100,12 @@ func (s *PeggyOrchestrator) hasRegisteredETHAddress(ctx context.Context) bool { // when peggo is run alongside a validator injective node. func (s *PeggyOrchestrator) startValidatorMode(ctx context.Context) error { log.WithFields(log.Fields{ - "BatchRequesterEnabled": true, - "EthOracleEnabled": true, - "EthSignerEnabled": true, - "ValsetRelayerEnabled": s.valsetRelayEnabled, - "BatchRelayerEnabled": s.batchRelayEnabled, + "batch_requesting": true, + "eth_event_tracking": true, + "batch_signing": true, + "valset_signing": true, + "valset_relaying": s.valsetRelayEnabled, + "batch_relaying": s.batchRelayEnabled, }).Infoln("running in validator mode") var pg loops.ParanoidGroup @@ -122,11 +123,9 @@ func (s *PeggyOrchestrator) startValidatorMode(ctx context.Context) error { // alongside a non-validator injective node func (s *PeggyOrchestrator) startRelayerMode(ctx context.Context) error { log.WithFields(log.Fields{ - "BatchRequesterEnabled": true, - "EthOracleEnabled": false, - "EthSignerEnabled": false, - "ValsetRelayerEnabled": s.valsetRelayEnabled, - "BatchRelayerEnabled": s.batchRelayEnabled, + "batch_requesting": true, + "valset_relaying": s.valsetRelayEnabled, + "batch_relaying": s.batchRelayEnabled, }).Infoln("running in relayer mode") var pg loops.ParanoidGroup diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index 1d8d84df..505761e9 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -181,6 +181,8 @@ func (l *relayerLoop) relayBatch(ctx context.Context) error { return nil } + l.Logger().WithFields(log.Fields{"inj_batch_nonce": oldestConfirmedBatch.BatchNonce, "eth_batch_nonce": latestEthereumBatch.Uint64()}).Infoln("latest batch updates") + // Check custom time delay offset blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedBatch.Block)) if err != nil { @@ -193,8 +195,6 @@ func (l *relayerLoop) relayBatch(ctx context.Context) error { return nil } - l.Logger().WithFields(log.Fields{"inj_batch_nonce": oldestConfirmedBatch.BatchNonce, "eth_batch_nonce": latestEthereumBatch.Uint64()}).Infoln("detected new batch on Injective") - // Send SendTransactionBatch to Ethereum txHash, err := l.eth.SendTransactionBatch(ctx, currentValset, oldestConfirmedBatch, oldestConfirmedBatchSigs) if err != nil { @@ -260,6 +260,8 @@ func (l *relayerLoop) relayValset(ctx context.Context) error { return nil } + l.Logger().WithFields(log.Fields{"inj_valset_nonce": oldestConfirmedValset.Nonce, "eth_valset_nonce": latestEthereumValsetNonce.Uint64()}).Infoln("latest valset updates") + // Check custom time delay offset blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedValset.Height)) if err != nil { @@ -272,11 +274,6 @@ func (l *relayerLoop) relayValset(ctx context.Context) error { return nil } - l.Logger().WithFields(log.Fields{ - "inj_valset_nonce": oldestConfirmedValset.Nonce, - "eth_valset_nonce": latestEthereumValsetNonce.Uint64()}, - ).Infoln("detected new valset on Injective") - txHash, err := l.eth.SendEthValsetUpdate( ctx, currentEthValset, From a7db8ced436f873d5da6d4f6ceb7a4c56d112453 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Fri, 29 Dec 2023 12:26:18 +0100 Subject: [PATCH 29/35] remove redundant network methods --- Makefile | 2 +- cmd/peggo/orchestrator.go | 1 - orchestrator/batch_request.go | 2 +- orchestrator/cosmos/custom_rpc.go | 108 +++------------------------ orchestrator/cosmos/load_balanced.go | 77 +------------------ orchestrator/injective.go | 6 +- orchestrator/mocks_test.go | 12 ++- orchestrator/oracle.go | 16 ++-- orchestrator/signer.go | 4 +- 9 files changed, 38 insertions(+), 190 deletions(-) diff --git a/Makefile b/Makefile index d1be7dca..40b5cd70 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ push: install: export GOPROXY=direct install: export VERSION_FLAGS="-X $(VERSION_PKG).GitCommit=$(GIT_COMMIT) -X $(VERSION_PKG).BuildDate=$(BUILD_DATE)" install: - $(DOCKER) && go install -tags muslc -ldflags $(VERSION_FLAGS) ./cmd/... || go install -ldflags $(VERSION_FLAGS) ./cmd/... + docker=$(DOCKER) && go install -tags muslc -ldflags $(VERSION_FLAGS) ./cmd/... || go install -ldflags $(VERSION_FLAGS) ./cmd/... .PHONY: install image push test gen diff --git a/cmd/peggo/orchestrator.go b/cmd/peggo/orchestrator.go index 060f7069..bc6d729e 100644 --- a/cmd/peggo/orchestrator.go +++ b/cmd/peggo/orchestrator.go @@ -41,7 +41,6 @@ func orchestratorCmd(cmd *cli.Cmd) { "go_arch": version.GoArch, }).Infoln("peggo - peggy binary for Ethereum bridge") - // todo: remove if *cfg.cosmosUseLedger || *cfg.ethUseLedger { log.Fatalln("cannot use Ledger for peggo, since signatures must be realtime") } diff --git a/orchestrator/batch_request.go b/orchestrator/batch_request.go index 5512b9d0..72f628d4 100644 --- a/orchestrator/batch_request.go +++ b/orchestrator/batch_request.go @@ -63,7 +63,7 @@ func (l *batchRequestLoop) requestBatches(ctx context.Context) error { func (l *batchRequestLoop) getUnbatchedTokenFees(ctx context.Context) ([]*types.BatchFees, error) { var unbatchedFees []*types.BatchFees getUnbatchedTokenFeesFn := func() (err error) { - unbatchedFees, err = l.inj.UnbatchedTokenFees(ctx) + unbatchedFees, err = l.inj.UnbatchedTokensWithFees(ctx) return err } diff --git a/orchestrator/cosmos/custom_rpc.go b/orchestrator/cosmos/custom_rpc.go index 5bf35412..079a4d8e 100644 --- a/orchestrator/cosmos/custom_rpc.go +++ b/orchestrator/cosmos/custom_rpc.go @@ -2,19 +2,18 @@ package cosmos import ( "context" - "github.com/InjectiveLabs/peggo/orchestrator/cosmos/tmclient" - "github.com/InjectiveLabs/peggo/orchestrator/ethereum/keystore" - peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" - "github.com/InjectiveLabs/sdk-go/chain/peggy/types" - peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" - chainclient "github.com/InjectiveLabs/sdk-go/client/chain" + "time" + "github.com/InjectiveLabs/sdk-go/client/common" rpchttp "github.com/cometbft/cometbft/rpc/client/http" "github.com/cosmos/cosmos-sdk/crypto/keyring" - gethcommon "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" log "github.com/xlab/suplog" - "time" + + "github.com/InjectiveLabs/peggo/orchestrator/cosmos/tmclient" + "github.com/InjectiveLabs/peggo/orchestrator/ethereum/keystore" + peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" + chainclient "github.com/InjectiveLabs/sdk-go/client/chain" ) type CustomRPCNetwork struct { @@ -73,7 +72,7 @@ func NewCustomRPCNetwork( grpcConn := daemonClient.QueryClient() waitForService(daemonWaitCtx, grpcConn) - peggyQuerier := types.NewQueryClient(grpcConn) + peggyQuerier := peggytypes.NewQueryClient(grpcConn) n := &CustomRPCNetwork{ TendermintClient: tmclient.NewRPCClient(tendermintRPC), @@ -83,7 +82,7 @@ func NewCustomRPCNetwork( log.WithFields(log.Fields{ "chain_id": chainID, - "connection": "custom", + "conn": "custom", "injective": injectiveGRPC, "tendermint": tendermintRPC, }).Infoln("connected to Injective network") @@ -100,103 +99,14 @@ func (n *CustomRPCNetwork) GetBlockCreationTime(ctx context.Context, height int6 return block.Block.Time, nil } -//func (n *LoadBalancedNetwork) PeggyParams(ctx context.Context) (*peggytypes.Params, error) { -// return n.PeggyQueryClient.PeggyParams(ctx) -//} - func (n *CustomRPCNetwork) LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) { return n.LastClaimEventByAddr(ctx, n.AccFromAddress()) } -func (n *CustomRPCNetwork) SendEthereumClaims( - ctx context.Context, - lastClaimEvent uint64, - oldDeposits []*peggyevents.PeggySendToCosmosEvent, - deposits []*peggyevents.PeggySendToInjectiveEvent, - withdraws []*peggyevents.PeggyTransactionBatchExecutedEvent, - erc20Deployed []*peggyevents.PeggyERC20DeployedEvent, - valsetUpdates []*peggyevents.PeggyValsetUpdatedEvent, -) error { - return n.PeggyBroadcastClient.SendEthereumClaims(ctx, - lastClaimEvent, - oldDeposits, - deposits, - withdraws, - erc20Deployed, - valsetUpdates, - ) -} - -func (n *CustomRPCNetwork) UnbatchedTokenFees(ctx context.Context) ([]*peggytypes.BatchFees, error) { - return n.PeggyQueryClient.UnbatchedTokensWithFees(ctx) -} - -func (n *CustomRPCNetwork) SendRequestBatch(ctx context.Context, denom string) error { - return n.PeggyBroadcastClient.SendRequestBatch(ctx, denom) -} - func (n *CustomRPCNetwork) OldestUnsignedValsets(ctx context.Context) ([]*peggytypes.Valset, error) { return n.PeggyQueryClient.OldestUnsignedValsets(ctx, n.AccFromAddress()) } -func (n *CustomRPCNetwork) LatestValsets(ctx context.Context) ([]*peggytypes.Valset, error) { - return n.PeggyQueryClient.LatestValsets(ctx) -} - -func (n *CustomRPCNetwork) AllValsetConfirms(ctx context.Context, nonce uint64) ([]*peggytypes.MsgValsetConfirm, error) { - return n.PeggyQueryClient.AllValsetConfirms(ctx, nonce) -} - -func (n *CustomRPCNetwork) ValsetAt(ctx context.Context, nonce uint64) (*peggytypes.Valset, error) { - return n.PeggyQueryClient.ValsetAt(ctx, nonce) -} - -func (n *CustomRPCNetwork) SendValsetConfirm( - ctx context.Context, - peggyID gethcommon.Hash, - valset *peggytypes.Valset, - ethFrom gethcommon.Address, -) error { - return n.PeggyBroadcastClient.SendValsetConfirm(ctx, ethFrom, peggyID, valset) -} - func (n *CustomRPCNetwork) OldestUnsignedTransactionBatch(ctx context.Context) (*peggytypes.OutgoingTxBatch, error) { return n.PeggyQueryClient.OldestUnsignedTransactionBatch(ctx, n.AccFromAddress()) } - -func (n *CustomRPCNetwork) LatestTransactionBatches(ctx context.Context) ([]*peggytypes.OutgoingTxBatch, error) { - return n.PeggyQueryClient.LatestTransactionBatches(ctx) -} - -func (n *CustomRPCNetwork) TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract gethcommon.Address) ([]*peggytypes.MsgConfirmBatch, error) { - return n.PeggyQueryClient.TransactionBatchSignatures(ctx, nonce, tokenContract) -} - -func (n *CustomRPCNetwork) SendBatchConfirm( - ctx context.Context, - peggyID gethcommon.Hash, - batch *peggytypes.OutgoingTxBatch, - ethFrom gethcommon.Address, -) error { - return n.PeggyBroadcastClient.SendBatchConfirm(ctx, ethFrom, peggyID, batch) -} - -// waitForService awaits an active ClientConn to a GRPC service. -//func waitForService(ctx context.Context, clientconn *grpc.ClientConn) { -// for { -// select { -// case <-ctx.Done(): -// log.Fatalln("GRPC service wait timed out") -// default: -// state := clientconn.GetState() -// -// if state != connectivity.Ready { -// log.WithField("state", state.String()).Warningln("state of GRPC connection not ready") -// time.Sleep(5 * time.Second) -// continue -// } -// -// return -// } -// } -//} diff --git a/orchestrator/cosmos/load_balanced.go b/orchestrator/cosmos/load_balanced.go index c3c79680..620da606 100644 --- a/orchestrator/cosmos/load_balanced.go +++ b/orchestrator/cosmos/load_balanced.go @@ -6,14 +6,12 @@ import ( "time" "github.com/cosmos/cosmos-sdk/crypto/keyring" - gethcommon "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" log "github.com/xlab/suplog" "google.golang.org/grpc" "google.golang.org/grpc/connectivity" "github.com/InjectiveLabs/peggo/orchestrator/ethereum/keystore" - peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" "github.com/InjectiveLabs/sdk-go/chain/peggy/types" peggytypes "github.com/InjectiveLabs/sdk-go/chain/peggy/types" chainclient "github.com/InjectiveLabs/sdk-go/client/chain" @@ -82,7 +80,7 @@ func NewLoadBalancedNetwork( ExplorerClient: explorer, } - log.WithFields(log.Fields{"chain_id": chainID, "connection": "load_balanced"}).Infoln("connected to Injective network") + log.WithFields(log.Fields{"chain_id": chainID, "conn": "load_balanced"}).Infoln("connected to Injective network") return n, nil } @@ -101,95 +99,26 @@ func (n *LoadBalancedNetwork) GetBlockCreationTime(ctx context.Context, height i return blockTime, nil } -func (n *LoadBalancedNetwork) PeggyParams(ctx context.Context) (*peggytypes.Params, error) { - return n.PeggyQueryClient.PeggyParams(ctx) -} - func (n *LoadBalancedNetwork) LastClaimEvent(ctx context.Context) (*peggytypes.LastClaimEvent, error) { return n.LastClaimEventByAddr(ctx, n.AccFromAddress()) } -func (n *LoadBalancedNetwork) SendEthereumClaims( - ctx context.Context, - lastClaimEvent uint64, - oldDeposits []*peggyevents.PeggySendToCosmosEvent, - deposits []*peggyevents.PeggySendToInjectiveEvent, - withdraws []*peggyevents.PeggyTransactionBatchExecutedEvent, - erc20Deployed []*peggyevents.PeggyERC20DeployedEvent, - valsetUpdates []*peggyevents.PeggyValsetUpdatedEvent, -) error { - return n.PeggyBroadcastClient.SendEthereumClaims(ctx, - lastClaimEvent, - oldDeposits, - deposits, - withdraws, - erc20Deployed, - valsetUpdates, - ) -} - -func (n *LoadBalancedNetwork) UnbatchedTokenFees(ctx context.Context) ([]*peggytypes.BatchFees, error) { - return n.PeggyQueryClient.UnbatchedTokensWithFees(ctx) -} - -func (n *LoadBalancedNetwork) SendRequestBatch(ctx context.Context, denom string) error { - return n.PeggyBroadcastClient.SendRequestBatch(ctx, denom) -} - func (n *LoadBalancedNetwork) OldestUnsignedValsets(ctx context.Context) ([]*peggytypes.Valset, error) { return n.PeggyQueryClient.OldestUnsignedValsets(ctx, n.AccFromAddress()) } -func (n *LoadBalancedNetwork) LatestValsets(ctx context.Context) ([]*peggytypes.Valset, error) { - return n.PeggyQueryClient.LatestValsets(ctx) -} - -func (n *LoadBalancedNetwork) AllValsetConfirms(ctx context.Context, nonce uint64) ([]*peggytypes.MsgValsetConfirm, error) { - return n.PeggyQueryClient.AllValsetConfirms(ctx, nonce) -} - -func (n *LoadBalancedNetwork) ValsetAt(ctx context.Context, nonce uint64) (*peggytypes.Valset, error) { - return n.PeggyQueryClient.ValsetAt(ctx, nonce) -} - -func (n *LoadBalancedNetwork) SendValsetConfirm( - ctx context.Context, - peggyID gethcommon.Hash, - valset *peggytypes.Valset, - ethFrom gethcommon.Address, -) error { - return n.PeggyBroadcastClient.SendValsetConfirm(ctx, ethFrom, peggyID, valset) -} - func (n *LoadBalancedNetwork) OldestUnsignedTransactionBatch(ctx context.Context) (*peggytypes.OutgoingTxBatch, error) { return n.PeggyQueryClient.OldestUnsignedTransactionBatch(ctx, n.AccFromAddress()) } -func (n *LoadBalancedNetwork) LatestTransactionBatches(ctx context.Context) ([]*peggytypes.OutgoingTxBatch, error) { - return n.PeggyQueryClient.LatestTransactionBatches(ctx) -} - -func (n *LoadBalancedNetwork) TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract gethcommon.Address) ([]*peggytypes.MsgConfirmBatch, error) { - return n.PeggyQueryClient.TransactionBatchSignatures(ctx, nonce, tokenContract) -} - -func (n *LoadBalancedNetwork) SendBatchConfirm( - ctx context.Context, - peggyID gethcommon.Hash, - batch *peggytypes.OutgoingTxBatch, - ethFrom gethcommon.Address, -) error { - return n.PeggyBroadcastClient.SendBatchConfirm(ctx, ethFrom, peggyID, batch) -} - // waitForService awaits an active ClientConn to a GRPC service. -func waitForService(ctx context.Context, clientconn *grpc.ClientConn) { +func waitForService(ctx context.Context, clientConn *grpc.ClientConn) { for { select { case <-ctx.Done(): log.Fatalln("GRPC service wait timed out") default: - state := clientconn.GetState() + state := clientConn.GetState() if state != connectivity.Ready { log.WithField("state", state.String()).Warningln("state of GRPC connection not ready") diff --git a/orchestrator/injective.go b/orchestrator/injective.go index 66209d27..6e6fb25d 100644 --- a/orchestrator/injective.go +++ b/orchestrator/injective.go @@ -26,15 +26,15 @@ type InjectiveNetwork interface { valsetUpdates []*peggyevents.PeggyValsetUpdatedEvent, ) error - UnbatchedTokenFees(ctx context.Context) ([]*peggytypes.BatchFees, error) + UnbatchedTokensWithFees(ctx context.Context) ([]*peggytypes.BatchFees, error) SendRequestBatch(ctx context.Context, denom string) error OldestUnsignedTransactionBatch(ctx context.Context) (*peggytypes.OutgoingTxBatch, error) - SendBatchConfirm(ctx context.Context, peggyID gethcommon.Hash, batch *peggytypes.OutgoingTxBatch, ethFrom gethcommon.Address) error + SendBatchConfirm(ctx context.Context, ethFrom gethcommon.Address, peggyID gethcommon.Hash, batch *peggytypes.OutgoingTxBatch) error LatestTransactionBatches(ctx context.Context) ([]*peggytypes.OutgoingTxBatch, error) TransactionBatchSignatures(ctx context.Context, nonce uint64, tokenContract gethcommon.Address) ([]*peggytypes.MsgConfirmBatch, error) OldestUnsignedValsets(ctx context.Context) ([]*peggytypes.Valset, error) - SendValsetConfirm(ctx context.Context, peggyID gethcommon.Hash, valset *peggytypes.Valset, ethFrom gethcommon.Address) error + SendValsetConfirm(ctx context.Context, ethFrom gethcommon.Address, peggyID gethcommon.Hash, valset *peggytypes.Valset) error LatestValsets(ctx context.Context) ([]*peggytypes.Valset, error) AllValsetConfirms(ctx context.Context, nonce uint64) ([]*peggytypes.MsgValsetConfirm, error) ValsetAt(ctx context.Context, nonce uint64) (*peggytypes.Valset, error) diff --git a/orchestrator/mocks_test.go b/orchestrator/mocks_test.go index 636bf5b6..1011dcf4 100644 --- a/orchestrator/mocks_test.go +++ b/orchestrator/mocks_test.go @@ -53,9 +53,15 @@ type mockInjective struct { latestTransactionBatchesFn func(context.Context) ([]*peggytypes.OutgoingTxBatch, error) transactionBatchSignaturesFn func(context.Context, uint64, eth.Address) ([]*peggytypes.MsgConfirmBatch, error) + + hasRegisteredEthAddress func(ctx context.Context, address eth.Address) (bool, error) +} + +func (i *mockInjective) HasRegisteredEthAddress(ctx context.Context, addr eth.Address) (bool, error) { + return i.hasRegisteredEthAddress(ctx, addr) } -func (i *mockInjective) UnbatchedTokenFees(ctx context.Context) ([]*peggytypes.BatchFees, error) { +func (i *mockInjective) UnbatchedTokensWithFees(ctx context.Context) ([]*peggytypes.BatchFees, error) { i.unbatchedTokenFeesCallCount++ return i.unbatchedTokenFeesFn(ctx) } @@ -98,7 +104,7 @@ func (i *mockInjective) OldestUnsignedValsets(ctx context.Context) ([]*peggytype return i.oldestUnsignedValsetsFn(ctx) } -func (i *mockInjective) SendValsetConfirm(ctx context.Context, peggyID eth.Hash, valset *peggytypes.Valset, ethFrom eth.Address) error { +func (i *mockInjective) SendValsetConfirm(ctx context.Context, ethFrom eth.Address, peggyID eth.Hash, valset *peggytypes.Valset) error { return i.sendValsetConfirmFn(ctx, peggyID, valset, ethFrom) } @@ -114,7 +120,7 @@ func (i *mockInjective) AllValsetConfirms(ctx context.Context, nonce uint64) ([] return i.allValsetConfirmsFn(ctx, nonce) } -func (i *mockInjective) SendBatchConfirm(ctx context.Context, peggyID eth.Hash, batch *peggytypes.OutgoingTxBatch, ethFrom eth.Address) error { +func (i *mockInjective) SendBatchConfirm(ctx context.Context, ethFrom eth.Address, peggyID eth.Hash, batch *peggytypes.OutgoingTxBatch) error { return i.sendBatchConfirmFn(ctx, peggyID, batch, ethFrom) } diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index 9112e89b..f2485b0c 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -197,6 +197,11 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { return errors.Wrap(err, "failed to query last claim event from Injective") } + l.logger.WithFields(log.Fields{ + "event_nonce": lastClaimEvent.EthereumEventNonce, + "event_block": lastClaimEvent.EthereumEventHeight, + }).Debugln("last Ethereum claim event on Injective") + legacyDeposits = filterSendToCosmosEventsByNonce(legacyDeposits, lastClaimEvent.EthereumEventNonce) deposits = filterSendToInjectiveEventsByNonce(deposits, lastClaimEvent.EthereumEventNonce) withdrawals = filterTransactionBatchExecutedEventsByNonce(withdrawals, lastClaimEvent.EthereumEventNonce) @@ -221,12 +226,11 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { } l.Logger().WithFields(log.Fields{ - "last_claim_event_nonce": lastClaimEvent.EthereumEventNonce, - "legacy_deposits": len(legacyDeposits), - "deposits": len(deposits), - "withdrawals": len(withdrawals), - "erc20_deployments": len(erc20Deployments), - "valset_updates": len(valsetUpdates), + "legacy_deposits": len(legacyDeposits), + "deposits": len(deposits), + "withdrawals": len(withdrawals), + "erc20_deployments": len(erc20Deployments), + "valset_updates": len(valsetUpdates), }).Infoln("sent new claims to Injective") return nil diff --git a/orchestrator/signer.go b/orchestrator/signer.go index 6aa3b8d9..98eb61d9 100644 --- a/orchestrator/signer.go +++ b/orchestrator/signer.go @@ -153,7 +153,7 @@ func (l *ethSignerLoop) getUnsignedBatch(ctx context.Context) (*types.OutgoingTx func (l *ethSignerLoop) signBatch(ctx context.Context, batch *types.OutgoingTxBatch) error { if err := retry.Do( - func() error { return l.inj.SendBatchConfirm(ctx, l.peggyID, batch, l.ethFrom) }, + func() error { return l.inj.SendBatchConfirm(ctx, l.ethFrom, l.peggyID, batch) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -196,7 +196,7 @@ func (l *ethSignerLoop) getUnsignedValsets(ctx context.Context) ([]*types.Valset func (l *ethSignerLoop) signValset(ctx context.Context, vs *types.Valset) error { if err := retry.Do(func() error { - return l.inj.SendValsetConfirm(ctx, l.peggyID, vs, l.ethFrom) + return l.inj.SendValsetConfirm(ctx, l.ethFrom, l.peggyID, vs) }, retry.Context(ctx), retry.Attempts(l.maxAttempts), From 8600ca1d5c4f56c832713ffef2477dc1e840d63b Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Fri, 29 Dec 2023 16:23:50 +0100 Subject: [PATCH 30/35] rollback block range query --- orchestrator/oracle.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index f2485b0c..b6495afb 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -143,22 +143,13 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { return errors.Wrap(err, "failed to get latest ethereum header") } - latestHeight = latestHeader.Number.Uint64() - - if latestHeight < ethBlockConfirmationDelay { - latestHeight = currentHeight // no blocks scanned - return nil - } - // add delay to ensure minimum confirmations are received and block is finalised - latestHeight = latestHeight - ethBlockConfirmationDelay - if latestHeight <= currentHeight { - latestHeight = currentHeight // no blocks scanned + latestHeight = latestHeader.Number.Uint64() - ethBlockConfirmationDelay + if latestHeight < currentHeight { return nil } - // calculate right bound of block search - if currentHeight+defaultBlocksToSearch < latestHeight { + if latestHeight > currentHeight+defaultBlocksToSearch { latestHeight = currentHeight + defaultBlocksToSearch } From 02de657df370a3e352c2cd5b97920758b2eab928 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Fri, 29 Dec 2023 17:00:27 +0100 Subject: [PATCH 31/35] logs --- orchestrator/cosmos/broadcast.go | 20 ++++++++++---------- orchestrator/ethereum/peggy/submit_batch.go | 2 +- orchestrator/ethereum/peggy/valset_update.go | 11 +++++------ orchestrator/relayer.go | 8 ++++---- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/orchestrator/cosmos/broadcast.go b/orchestrator/cosmos/broadcast.go index 533c670b..5c0bc731 100644 --- a/orchestrator/cosmos/broadcast.go +++ b/orchestrator/cosmos/broadcast.go @@ -253,7 +253,7 @@ func (s *peggyBroadcastClient) sendOldDepositClaims( "destination": sdk.AccAddress(oldDeposit.Destination[12:32]).String(), "amount": oldDeposit.Amount.String(), "event_nonce": oldDeposit.EventNonce.String(), - }).Debugln("observed SendToCosmos event. Sending MsgDepositClaim...") + }).Debugln("observed SendToCosmosEvent. Sending claim...") msg := &types.MsgDepositClaim{ EventNonce: oldDeposit.EventNonce.Uint64(), @@ -274,7 +274,7 @@ func (s *peggyBroadcastClient) sendOldDepositClaims( log.WithFields(log.Fields{ "event_nonce": oldDeposit.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent old deposit event successfully") + }).Infoln("Oracle sent SendToCosmosEvent successfully") } return nil @@ -299,7 +299,7 @@ func (s *peggyBroadcastClient) sendDepositClaims( "amount": deposit.Amount.String(), "event_nonce": deposit.EventNonce.String(), "data": deposit.Data, - }).Debugln("observed SendToInjective event. Sending MsgDepositClaim...") + }).Debugln("observed SendToInjectiveEvent. Sending claim...") msg := &types.MsgDepositClaim{ EventNonce: deposit.EventNonce.Uint64(), @@ -320,7 +320,7 @@ func (s *peggyBroadcastClient) sendDepositClaims( log.WithFields(log.Fields{ "event_nonce": deposit.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent deposit event successfully") + }).Infoln("Oracle sent SendToInjectiveEvent successfully") } return nil @@ -338,7 +338,7 @@ func (s *peggyBroadcastClient) sendWithdrawClaims( "nonce": withdraw.BatchNonce.String(), "token_contract": withdraw.Token.Hex(), "event_nonce": withdraw.EventNonce.String(), - }).Debugln("observed TransactionBatchExecuted event. Sending MsgWithdrawClaim...") + }).Debugln("observed TransactionBatchExecutedEvent. Sending claim...") // WithdrawClaim claims that a batch of withdrawal // operations on the bridge contract was executed. @@ -358,7 +358,7 @@ func (s *peggyBroadcastClient) sendWithdrawClaims( log.WithFields(log.Fields{ "event_nonce": withdraw.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent withdraw event successfully") + }).Infoln("Oracle sent TransactionBatchExecutedEvent successfully") } return nil @@ -379,7 +379,7 @@ func (s *peggyBroadcastClient) sendValsetUpdateClaims( "powers": valsetUpdate.Powers, "reward_amount": valsetUpdate.RewardAmount, "reward_token": valsetUpdate.RewardToken.Hex(), - }).Debugln("observed ValsetUpdatedEvent event. Sending MsgValsetUpdatedClaim...") + }).Debugln("observed ValsetUpdatedEvent. Sending claim...") members := make([]*types.BridgeValidator, len(valsetUpdate.Validators)) for i, val := range valsetUpdate.Validators { @@ -407,7 +407,7 @@ func (s *peggyBroadcastClient) sendValsetUpdateClaims( log.WithFields(log.Fields{ "event_nonce": valsetUpdate.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent valset update event successfully") + }).Infoln("Oracle sent ValsetUpdatedEvent successfully") } return nil @@ -428,7 +428,7 @@ func (s *peggyBroadcastClient) sendErc20DeployedClaims( "name": erc20Deployed.Name, "symbol": erc20Deployed.Symbol, "decimals": erc20Deployed.Decimals, - }).Debugln("observed ERC20Deployed event. Sending MsgERC20DeployedClaim...") + }).Debugln("observed ERC20DeployedEvent. Sending claim...") msg := &types.MsgERC20DeployedClaim{ EventNonce: erc20Deployed.EventNonce.Uint64(), @@ -449,7 +449,7 @@ func (s *peggyBroadcastClient) sendErc20DeployedClaims( log.WithFields(log.Fields{ "event_nonce": erc20Deployed.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent erc20 deployed event successfully") + }).Infoln("Oracle sent ERC20DeployedEvent successfully") } return nil diff --git a/orchestrator/ethereum/peggy/submit_batch.go b/orchestrator/ethereum/peggy/submit_batch.go index 09b7d17b..6206c2f7 100644 --- a/orchestrator/ethereum/peggy/submit_batch.go +++ b/orchestrator/ethereum/peggy/submit_batch.go @@ -24,7 +24,7 @@ func (s *peggyContract) SendTransactionBatch( log.WithFields(log.Fields{ "token_contract": batch.TokenContract, - "nonce": batch.BatchNonce, + "batch_nonce": batch.BatchNonce, "transactions": len(batch.Transactions), "confirmations": len(confirms), }).Debugln("checking signatures and submitting batch to Ethereum") diff --git a/orchestrator/ethereum/peggy/valset_update.go b/orchestrator/ethereum/peggy/valset_update.go index e6921545..edc7a6e9 100644 --- a/orchestrator/ethereum/peggy/valset_update.go +++ b/orchestrator/ethereum/peggy/valset_update.go @@ -38,9 +38,10 @@ func (s *peggyContract) SendEthValsetUpdate( } log.WithFields(log.Fields{ - "old_nonce": oldValset.Nonce, - "new_nonce": newValset.Nonce, - }).Infoln("Checking signatures and submitting validator set update to Ethereum") + "valset_nonce": newValset.Nonce, + "validators": len(newValset.Members), + "confirmations": len(confirms), + }).Debugln("checking signatures and submitting valset to Ethereum") newValidators, newPowers := validatorsAndPowers(newValset) newValsetNonce := new(big.Int).SetUint64(newValset.Nonce) @@ -86,7 +87,7 @@ func (s *peggyContract) SendEthValsetUpdate( // bytes32[] memory _r, // bytes32[] memory _s // ) - log.Debugln("Sending updateValset Ethereum tx", "currentValidators", currentValidators, "currentPowers", currentPowers, "currentValsetNonce", currentValsetNonce) + txData, err := peggyABI.Pack("updateValset", newValsetArgs, currentValsetArgs, @@ -112,8 +113,6 @@ func (s *peggyContract) SendEthValsetUpdate( return nil, err } - log.Infoln("Sent Tx (Peggy updateValset):", txHash.Hex()) - // let before_nonce = get_valset_nonce(peggy_contract_address, eth_address, web3).await?; // if before_nonce != old_nonce { // info!( diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index 505761e9..b167081f 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -181,7 +181,7 @@ func (l *relayerLoop) relayBatch(ctx context.Context) error { return nil } - l.Logger().WithFields(log.Fields{"inj_batch_nonce": oldestConfirmedBatch.BatchNonce, "eth_batch_nonce": latestEthereumBatch.Uint64()}).Infoln("latest batch updates") + l.Logger().WithFields(log.Fields{"inj_batch_nonce": oldestConfirmedBatch.BatchNonce, "eth_batch_nonce": latestEthereumBatch.Uint64()}).Debugln("latest batch updates") // Check custom time delay offset blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedBatch.Block)) @@ -201,7 +201,7 @@ func (l *relayerLoop) relayBatch(ctx context.Context) error { return err } - l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("sent batch tx to Ethereum") + l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("sent tx batch to Ethereum") return nil } @@ -260,7 +260,7 @@ func (l *relayerLoop) relayValset(ctx context.Context) error { return nil } - l.Logger().WithFields(log.Fields{"inj_valset_nonce": oldestConfirmedValset.Nonce, "eth_valset_nonce": latestEthereumValsetNonce.Uint64()}).Infoln("latest valset updates") + l.Logger().WithFields(log.Fields{"inj_valset_nonce": oldestConfirmedValset.Nonce, "eth_valset_nonce": latestEthereumValsetNonce.Uint64()}).Debugln("latest valset updates") // Check custom time delay offset blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedValset.Height)) @@ -284,7 +284,7 @@ func (l *relayerLoop) relayValset(ctx context.Context) error { return err } - l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("updated valset on Ethereum") + l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("sent valset update on Ethereum") return nil } From 61ad0d3e8ad10c3ce87ed785a7530883dca022d2 Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 4 Jan 2024 12:10:31 +0100 Subject: [PATCH 32/35] adapt registeEthKeyCmd for new .env usage --- cmd/peggo/options.go | 2 - cmd/peggo/tx.go | 105 ++++++++++++++----------------------------- 2 files changed, 34 insertions(+), 73 deletions(-) diff --git a/cmd/peggo/options.go b/cmd/peggo/options.go index 94181ad0..d89556cf 100644 --- a/cmd/peggo/options.go +++ b/cmd/peggo/options.go @@ -61,14 +61,12 @@ func initCosmosOptions( Name: "cosmos-grpc", Desc: "Cosmos GRPC querying endpoint", EnvVar: "PEGGO_COSMOS_GRPC", - Value: "tcp://localhost:9900", }) *tendermintRPC = cmd.String(cli.StringOpt{ Name: "tendermint-rpc", Desc: "Tendermint RPC endpoint", EnvVar: "PEGGO_TENDERMINT_RPC", - Value: "http://localhost:26657", }) *cosmosGasPrices = cmd.String(cli.StringOpt{ diff --git a/cmd/peggo/tx.go b/cmd/peggo/tx.go index dc52f792..136adb57 100644 --- a/cmd/peggo/tx.go +++ b/cmd/peggo/tx.go @@ -4,18 +4,10 @@ import ( "context" "time" - rpchttp "github.com/cometbft/cometbft/rpc/client/http" - "google.golang.org/grpc" - "google.golang.org/grpc/connectivity" - cli "github.com/jawher/mow.cli" "github.com/xlab/closer" log "github.com/xlab/suplog" - "github.com/InjectiveLabs/sdk-go/chain/peggy/types" - chainclient "github.com/InjectiveLabs/sdk-go/client/chain" - "github.com/InjectiveLabs/sdk-go/client/common" - "github.com/InjectiveLabs/peggo/orchestrator/cosmos" ) @@ -134,57 +126,48 @@ func registerEthKeyCmd(cmd *cli.Cmd) { return } - clientCtx, err := chainclient.NewClientContext(*cosmosChainID, valAddress.String(), cosmosKeyring) - if err != nil { - log.WithError(err).Fatalln("failed to initialize cosmos client context") - } - clientCtx = clientCtx.WithNodeURI(*tendermintRPC) - - tmRPC, err := rpchttp.New(*tendermintRPC, "/websocket") - if err != nil { - log.WithError(err) - } - - clientCtx = clientCtx.WithClient(tmRPC) - - var networkName string + // here + var ( + peggyBroadcastClient cosmos.PeggyBroadcastClient + customCosmosRPC = *cosmosGRPC != "" && *tendermintRPC != "" + ) - switch *cosmosChainID { - case "injective-1": - networkName = "mainnet" - case "injective-777": - networkName = "devnet" - case "injective-888": - networkName = "testnet" - } + if customCosmosRPC { + net, err := cosmos.NewCustomRPCNetwork( + *cosmosChainID, + valAddress.String(), + *cosmosGRPC, + *cosmosGasPrices, + *tendermintRPC, + cosmosKeyring, + personalSignFn, + ) + + if err != nil { + log.Fatalln("failed to connect to Injective network") + } - netCfg := common.LoadNetwork(networkName, "lb") + peggyBroadcastClient = net.PeggyBroadcastClient + } else { + net, err := cosmos.NewLoadBalancedNetwork( + *cosmosChainID, + valAddress.String(), + *cosmosGasPrices, + cosmosKeyring, + personalSignFn, + ) + + if err != nil { + log.Fatalln("failed to connect to Injective network") + } - daemonClient, err := chainclient.NewChainClient(clientCtx, netCfg, common.OptionGasPrices(*cosmosGasPrices)) - if err != nil { - log.WithError(err).WithFields(log.Fields{ - "endpoint": *cosmosGRPC, - }).Fatalln("failed to connect to Cosmos daemon") + peggyBroadcastClient = net.PeggyBroadcastClient } - log.Infoln("Waiting for injectived GRPC") - time.Sleep(1 * time.Second) - - daemonWaitCtx, cancelWait := context.WithTimeout(context.Background(), time.Minute) - grpcConn := daemonClient.QueryClient() - waitForService(daemonWaitCtx, grpcConn) - peggyQuerier := types.NewQueryClient(grpcConn) - peggyBroadcaster := cosmos.NewPeggyBroadcastClient( - peggyQuerier, - daemonClient, - personalSignFn, - ) - cancelWait() - broadcastCtx, cancelFn := context.WithTimeout(context.Background(), 15*time.Second) defer cancelFn() - if err = peggyBroadcaster.UpdatePeggyOrchestratorAddresses(broadcastCtx, ethKeyFromAddress, valAddress); err != nil { + if err = peggyBroadcastClient.UpdatePeggyOrchestratorAddresses(broadcastCtx, ethKeyFromAddress, valAddress); err != nil { log.WithError(err).Errorln("failed to broadcast Tx") time.Sleep(time.Second) return @@ -194,23 +177,3 @@ func registerEthKeyCmd(cmd *cli.Cmd) { ethKeyFromAddress, valAddress.String()) } } - -// waitForService awaits an active ClientConn to a GRPC service. -func waitForService(ctx context.Context, clientconn *grpc.ClientConn) { - for { - select { - case <-ctx.Done(): - log.Fatalln("GRPC service wait timed out") - default: - state := clientconn.GetState() - - if state != connectivity.Ready { - log.WithField("state", state.String()).Warningln("state of GRPC connection not ready") - time.Sleep(5 * time.Second) - continue - } - - return - } - } -} From cb7d4030bafe02400c2e99a691e1dcb23541ff2b Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 4 Jan 2024 12:58:48 +0100 Subject: [PATCH 33/35] cleanup --- cmd/peggo/orchestrator.go | 3 +- cmd/peggo/tx.go | 1 - orchestrator/ethereum/peggy/submit_batch.go | 2 +- orchestrator/ethereum/peggy/valset_update.go | 2 +- orchestrator/oracle.go | 8 +- orchestrator/relayer.go | 175 +++++++------------ orchestrator/signer.go | 51 +++--- 7 files changed, 102 insertions(+), 140 deletions(-) diff --git a/cmd/peggo/orchestrator.go b/cmd/peggo/orchestrator.go index bc6d729e..3eac2716 100644 --- a/cmd/peggo/orchestrator.go +++ b/cmd/peggo/orchestrator.go @@ -2,11 +2,12 @@ package main import ( "context" + "os" + gethcommon "github.com/ethereum/go-ethereum/common" cli "github.com/jawher/mow.cli" "github.com/xlab/closer" log "github.com/xlab/suplog" - "os" "github.com/InjectiveLabs/peggo/orchestrator" "github.com/InjectiveLabs/peggo/orchestrator/coingecko" diff --git a/cmd/peggo/tx.go b/cmd/peggo/tx.go index 136adb57..c69c41ff 100644 --- a/cmd/peggo/tx.go +++ b/cmd/peggo/tx.go @@ -126,7 +126,6 @@ func registerEthKeyCmd(cmd *cli.Cmd) { return } - // here var ( peggyBroadcastClient cosmos.PeggyBroadcastClient customCosmosRPC = *cosmosGRPC != "" && *tendermintRPC != "" diff --git a/orchestrator/ethereum/peggy/submit_batch.go b/orchestrator/ethereum/peggy/submit_batch.go index 6206c2f7..427e09b9 100644 --- a/orchestrator/ethereum/peggy/submit_batch.go +++ b/orchestrator/ethereum/peggy/submit_batch.go @@ -27,7 +27,7 @@ func (s *peggyContract) SendTransactionBatch( "batch_nonce": batch.BatchNonce, "transactions": len(batch.Transactions), "confirmations": len(confirms), - }).Debugln("checking signatures and submitting batch to Ethereum") + }).Debugln("checking signatures and submitting batch") validators, powers, sigV, sigR, sigS, err := checkBatchSigsAndRepack(currentValset, confirms) if err != nil { diff --git a/orchestrator/ethereum/peggy/valset_update.go b/orchestrator/ethereum/peggy/valset_update.go index edc7a6e9..8fbbc7b6 100644 --- a/orchestrator/ethereum/peggy/valset_update.go +++ b/orchestrator/ethereum/peggy/valset_update.go @@ -41,7 +41,7 @@ func (s *peggyContract) SendEthValsetUpdate( "valset_nonce": newValset.Nonce, "validators": len(newValset.Members), "confirmations": len(confirms), - }).Debugln("checking signatures and submitting valset to Ethereum") + }).Debugln("checking signatures and submitting valset update") newValidators, newPowers := validatorsAndPowers(newValset) newValsetNonce := new(big.Int).SetUint64(newValset.Nonce) diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index b6495afb..4a755f9a 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -30,7 +30,7 @@ func (s *PeggyOrchestrator) EthOracleMainLoop(ctx context.Context) error { return err } - s.logger.Debugln("last observed ethereum block", lastConfirmedEthHeight) + s.logger.Debugln("last observed Ethereum block", lastConfirmedEthHeight) loop := ethOracleLoop{ PeggyOrchestrator: s, @@ -188,9 +188,9 @@ func (l *ethOracleLoop) relayEvents(ctx context.Context) (uint64, error) { return errors.Wrap(err, "failed to query last claim event from Injective") } - l.logger.WithFields(log.Fields{ - "event_nonce": lastClaimEvent.EthereumEventNonce, - "event_block": lastClaimEvent.EthereumEventHeight, + l.Logger().WithFields(log.Fields{ + "event_nonce": lastClaimEvent.EthereumEventNonce, + "event_height": lastClaimEvent.EthereumEventHeight, }).Debugln("last Ethereum claim event on Injective") legacyDeposits = filterSendToCosmosEventsByNonce(legacyDeposits, lastClaimEvent.EthereumEventNonce) diff --git a/orchestrator/relayer.go b/orchestrator/relayer.go index b167081f..7eb61507 100644 --- a/orchestrator/relayer.go +++ b/orchestrator/relayer.go @@ -84,207 +84,168 @@ func (l *relayerLoop) relayValsetsAndBatches(ctx context.Context) error { return nil } -func (l *relayerLoop) loopFn(ctx context.Context) func() error { - return func() error { - var pg loops.ParanoidGroup - - if l.valsetRelayEnabled { - pg.Go(func() error { - return retry.Do(func() error { return l.relayValset(ctx) }, - retry.Context(ctx), - retry.Attempts(l.maxAttempts), - retry.OnRetry(func(n uint, err error) { - l.Logger().WithError(err).Warningf("failed to relay valsets, will retry (%d)", n) - }), - ) - }) - } - - if l.batchRelayEnabled { - pg.Go(func() error { - return retry.Do(func() error { return l.relayBatch(ctx) }, - retry.Context(ctx), - retry.Attempts(l.maxAttempts), - retry.OnRetry(func(n uint, err error) { - l.Logger().WithError(err).Warningf("failed to relay batches, will retry (%d)", n) - }), - ) - }) - } - - if pg.Initialized() { - if err := pg.Wait(); err != nil { - l.Logger().WithError(err).Errorln("got error, loop exits") - return err - } - } - - return nil - } -} - -func (l *relayerLoop) relayBatch(ctx context.Context) error { +func (l *relayerLoop) relayValset(ctx context.Context) error { metrics.ReportFuncCall(l.svcTags) doneFn := metrics.ReportFuncTiming(l.svcTags) defer doneFn() - latestBatches, err := l.inj.LatestTransactionBatches(ctx) + // we should determine if we need to relay one + // to Ethereum for that we will find the latest confirmed valset and compare it to the ethereum chain + latestValsets, err := l.inj.LatestValsets(ctx) if err != nil { - return err + return errors.Wrap(err, "failed to get latest valset updates from Injective") } var ( - oldestConfirmedBatch *types.OutgoingTxBatch - oldestConfirmedBatchSigs []*types.MsgConfirmBatch + oldestConfirmedValset *types.Valset + oldestConfirmedValsetSigs []*types.MsgValsetConfirm ) - for _, batch := range latestBatches { - sigs, err := l.inj.TransactionBatchSignatures(ctx, batch.BatchNonce, common.HexToAddress(batch.TokenContract)) + for _, set := range latestValsets { + sigs, err := l.inj.AllValsetConfirms(ctx, set.Nonce) if err != nil { - return err + return errors.Wrapf(err, "failed to get valset confirmations for nonce %d", set.Nonce) } else if len(sigs) == 0 { continue } - oldestConfirmedBatch = batch - oldestConfirmedBatchSigs = sigs + oldestConfirmedValsetSigs = sigs + oldestConfirmedValset = set + break } - if oldestConfirmedBatch == nil { - l.Logger().Debugln("no outgoing batch to relay") + if oldestConfirmedValset == nil { + l.Logger().Debugln("no valset update to relay") return nil } - latestEthereumBatch, err := l.eth.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) - if err != nil { - return err - } - - currentValset, err := l.findLatestValsetOnEth(ctx, l.inj, l.eth) + currentEthValset, err := l.findLatestValsetOnEth(ctx, l.inj, l.eth) if err != nil { - return errors.Wrap(err, "failed to find latest valset") - } else if currentValset == nil { - return errors.Wrap(err, "latest valset not found") + return errors.Wrap(err, "failed to find latest confirmed valset update on Ethereum") } - if oldestConfirmedBatch.BatchNonce <= latestEthereumBatch.Uint64() { + if oldestConfirmedValset.Nonce <= currentEthValset.Nonce { return nil } - latestEthereumBatch, err = l.eth.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) + latestEthereumValsetNonce, err := l.eth.GetValsetNonce(ctx) if err != nil { - return err + return errors.Wrap(err, "failed to get latest valset nonce from Ethereum") } - // Check if ethereum batch was updated by other validators - if oldestConfirmedBatch.BatchNonce <= latestEthereumBatch.Uint64() { + // Check if other validators already updated the valset + if oldestConfirmedValset.Nonce <= latestEthereumValsetNonce.Uint64() { return nil } - l.Logger().WithFields(log.Fields{"inj_batch_nonce": oldestConfirmedBatch.BatchNonce, "eth_batch_nonce": latestEthereumBatch.Uint64()}).Debugln("latest batch updates") + l.Logger().WithFields(log.Fields{"inj_valset_nonce": oldestConfirmedValset.Nonce, "eth_valset_nonce": latestEthereumValsetNonce.Uint64()}).Debugln("latest valset updates") // Check custom time delay offset - blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedBatch.Block)) + blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedValset.Height)) if err != nil { return errors.Wrap(err, "failed to parse timestamp from block") } - if timeElapsed := time.Since(blockTime); timeElapsed <= l.relayBatchOffsetDur { - timeRemaining := time.Duration(int64(l.relayBatchOffsetDur) - int64(timeElapsed)) - l.Logger().WithField("time_remaining", timeRemaining.String()).Debugln("batch relay offset duration not expired") + if timeElapsed := time.Since(blockTime); timeElapsed <= l.relayValsetOffsetDur { + timeRemaining := time.Duration(int64(l.relayValsetOffsetDur) - int64(timeElapsed)) + l.Logger().WithField("time_remaining", timeRemaining.String()).Debugln("valset relay offset duration not expired") return nil } - // Send SendTransactionBatch to Ethereum - txHash, err := l.eth.SendTransactionBatch(ctx, currentValset, oldestConfirmedBatch, oldestConfirmedBatchSigs) + txHash, err := l.eth.SendEthValsetUpdate( + ctx, + currentEthValset, + oldestConfirmedValset, + oldestConfirmedValsetSigs, + ) if err != nil { return err } - l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("sent tx batch to Ethereum") + l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("sent valset update to Ethereum") return nil } -func (l *relayerLoop) relayValset(ctx context.Context) error { +func (l *relayerLoop) relayBatch(ctx context.Context) error { metrics.ReportFuncCall(l.svcTags) doneFn := metrics.ReportFuncTiming(l.svcTags) defer doneFn() - // we should determine if we need to relay one - // to Ethereum for that we will find the latest confirmed valset and compare it to the ethereum chain - latestValsets, err := l.inj.LatestValsets(ctx) + latestBatches, err := l.inj.LatestTransactionBatches(ctx) if err != nil { - return errors.Wrap(err, "failed to get latest valset updates from Injective") + return err } var ( - oldestConfirmedValset *types.Valset - oldestConfirmedValsetSigs []*types.MsgValsetConfirm + oldestConfirmedBatch *types.OutgoingTxBatch + oldestConfirmedBatchSigs []*types.MsgConfirmBatch ) - for _, set := range latestValsets { - sigs, err := l.inj.AllValsetConfirms(ctx, set.Nonce) + for _, batch := range latestBatches { + sigs, err := l.inj.TransactionBatchSignatures(ctx, batch.BatchNonce, common.HexToAddress(batch.TokenContract)) if err != nil { - return errors.Wrapf(err, "failed to get valset confirmations for nonce %d", set.Nonce) + return err } else if len(sigs) == 0 { continue } - oldestConfirmedValsetSigs = sigs - oldestConfirmedValset = set - break + oldestConfirmedBatch = batch + oldestConfirmedBatchSigs = sigs } - if oldestConfirmedValset == nil { - l.Logger().Debugln("no valset update to relay") + if oldestConfirmedBatch == nil { + l.Logger().Debugln("no outgoing batch to relay") return nil } - currentEthValset, err := l.findLatestValsetOnEth(ctx, l.inj, l.eth) + latestEthereumBatch, err := l.eth.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) if err != nil { - return errors.Wrap(err, "failed to find latest confirmed valset update on Ethereum") + return err } - if oldestConfirmedValset.Nonce <= currentEthValset.Nonce { + currentValset, err := l.findLatestValsetOnEth(ctx, l.inj, l.eth) + if err != nil { + return errors.Wrap(err, "failed to find latest valset") + } else if currentValset == nil { + return errors.Wrap(err, "latest valset not found") + } + + if oldestConfirmedBatch.BatchNonce <= latestEthereumBatch.Uint64() { return nil } - latestEthereumValsetNonce, err := l.eth.GetValsetNonce(ctx) + latestEthereumBatch, err = l.eth.GetTxBatchNonce(ctx, common.HexToAddress(oldestConfirmedBatch.TokenContract)) if err != nil { - return errors.Wrap(err, "failed to get latest valset nonce from Ethereum") + return err } - // Check if other validators already updated the valset - if oldestConfirmedValset.Nonce <= latestEthereumValsetNonce.Uint64() { + // Check if ethereum batch was updated by other validators + if oldestConfirmedBatch.BatchNonce <= latestEthereumBatch.Uint64() { return nil } - l.Logger().WithFields(log.Fields{"inj_valset_nonce": oldestConfirmedValset.Nonce, "eth_valset_nonce": latestEthereumValsetNonce.Uint64()}).Debugln("latest valset updates") + l.Logger().WithFields(log.Fields{"inj_batch_nonce": oldestConfirmedBatch.BatchNonce, "eth_batch_nonce": latestEthereumBatch.Uint64()}).Debugln("latest batch updates") // Check custom time delay offset - blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedValset.Height)) + blockTime, err := l.inj.GetBlockCreationTime(ctx, int64(oldestConfirmedBatch.Block)) if err != nil { return errors.Wrap(err, "failed to parse timestamp from block") } - if timeElapsed := time.Since(blockTime); timeElapsed <= l.relayValsetOffsetDur { - timeRemaining := time.Duration(int64(l.relayValsetOffsetDur) - int64(timeElapsed)) - l.Logger().WithField("time_remaining", timeRemaining.String()).Debugln("valset relay offset duration not expired") + if timeElapsed := time.Since(blockTime); timeElapsed <= l.relayBatchOffsetDur { + timeRemaining := time.Duration(int64(l.relayBatchOffsetDur) - int64(timeElapsed)) + l.Logger().WithField("time_remaining", timeRemaining.String()).Debugln("batch relay offset duration not expired") return nil } - txHash, err := l.eth.SendEthValsetUpdate( - ctx, - currentEthValset, - oldestConfirmedValset, - oldestConfirmedValsetSigs, - ) + // Send SendTransactionBatch to Ethereum + txHash, err := l.eth.SendTransactionBatch(ctx, currentValset, oldestConfirmedBatch, oldestConfirmedBatchSigs) if err != nil { return err } - l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("sent valset update on Ethereum") + l.Logger().WithField("tx_hash", txHash.Hex()).Infoln("sent tx batch to Ethereum") return nil } diff --git a/orchestrator/signer.go b/orchestrator/signer.go index 98eb61d9..cdb9b688 100644 --- a/orchestrator/signer.go +++ b/orchestrator/signer.go @@ -69,20 +69,16 @@ func (l *ethSignerLoop) Logger() log.Logger { func (l *ethSignerLoop) Run(ctx context.Context) error { return loops.RunLoop(ctx, l.loopDuration, func() error { - return l.signBatchesAndValsets(ctx) - }) -} - -func (l *ethSignerLoop) signBatchesAndValsets(ctx context.Context) error { - if err := l.signNewValsetUpdates(ctx); err != nil { - return err - } + if err := l.signNewValsetUpdates(ctx); err != nil { + return err + } - if err := l.signNewBatch(ctx); err != nil { - return err - } + if err := l.signNewBatch(ctx); err != nil { + return err + } - return nil + return nil + }) } func (l *ethSignerLoop) signNewValsetUpdates(ctx context.Context) error { @@ -101,7 +97,7 @@ func (l *ethSignerLoop) signNewValsetUpdates(ctx context.Context) error { return err } - // todo: in case of multiple updates, we should sleep in between confirms requests (non-continuous nonce) + // todo: in case of multiple updates, we should sleep in between tx (non-continuous nonce) } return nil @@ -126,18 +122,18 @@ func (l *ethSignerLoop) signNewBatch(ctx context.Context) error { } func (l *ethSignerLoop) getUnsignedBatch(ctx context.Context) (*types.OutgoingTxBatch, error) { - var oldestUnsignedTransactionBatch *types.OutgoingTxBatch - retryFn := func() (err error) { + var oldestUnsignedBatch *types.OutgoingTxBatch + getOldestUnsignedBatchFn := func() (err error) { // sign the last unsigned batch, TODO check if we already have signed this - oldestUnsignedTransactionBatch, err = l.inj.OldestUnsignedTransactionBatch(ctx) - if errors.Is(err, cosmos.ErrNotFound) || oldestUnsignedTransactionBatch == nil { + oldestUnsignedBatch, err = l.inj.OldestUnsignedTransactionBatch(ctx) + if errors.Is(err, cosmos.ErrNotFound) || oldestUnsignedBatch == nil { return nil } return err } - if err := retry.Do(retryFn, + if err := retry.Do(getOldestUnsignedBatchFn, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -148,12 +144,15 @@ func (l *ethSignerLoop) getUnsignedBatch(ctx context.Context) (*types.OutgoingTx return nil, err } - return oldestUnsignedTransactionBatch, nil + return oldestUnsignedBatch, nil } func (l *ethSignerLoop) signBatch(ctx context.Context, batch *types.OutgoingTxBatch) error { - if err := retry.Do( - func() error { return l.inj.SendBatchConfirm(ctx, l.ethFrom, l.peggyID, batch) }, + signFn := func() error { + return l.inj.SendBatchConfirm(ctx, l.ethFrom, l.peggyID, batch) + } + + if err := retry.Do(signFn, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -164,7 +163,7 @@ func (l *ethSignerLoop) signBatch(ctx context.Context, batch *types.OutgoingTxBa return err } - l.Logger().WithFields(log.Fields{"token_contract": batch.TokenContract, "nonce": batch.BatchNonce, "txs": len(batch.Transactions)}).Infoln("confirmed batch on Injective") + l.Logger().WithFields(log.Fields{"token_contract": batch.TokenContract, "batch_nonce": batch.BatchNonce, "txs": len(batch.Transactions)}).Infoln("confirmed batch on Injective") return nil } @@ -195,9 +194,11 @@ func (l *ethSignerLoop) getUnsignedValsets(ctx context.Context) ([]*types.Valset } func (l *ethSignerLoop) signValset(ctx context.Context, vs *types.Valset) error { - if err := retry.Do(func() error { + signFn := func() error { return l.inj.SendValsetConfirm(ctx, l.ethFrom, l.peggyID, vs) - }, + } + + if err := retry.Do(signFn, retry.Context(ctx), retry.Attempts(l.maxAttempts), retry.OnRetry(func(n uint, err error) { @@ -208,7 +209,7 @@ func (l *ethSignerLoop) signValset(ctx context.Context, vs *types.Valset) error return err } - l.Logger().WithFields(log.Fields{"nonce": vs.Nonce, "members": len(vs.Members)}).Infoln("confirmed valset update on Injective") + l.Logger().WithFields(log.Fields{"valset_nonce": vs.Nonce, "validators": len(vs.Members)}).Infoln("confirmed valset update on Injective") return nil } From c60092a4008d53780bfac81e4eb7b90b7166622d Mon Sep 17 00:00:00 2001 From: Dusan Brajovic Date: Thu, 4 Jan 2024 15:47:01 +0100 Subject: [PATCH 34/35] claim logs --- orchestrator/cosmos/broadcast.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/orchestrator/cosmos/broadcast.go b/orchestrator/cosmos/broadcast.go index 5c0bc731..d88a229e 100644 --- a/orchestrator/cosmos/broadcast.go +++ b/orchestrator/cosmos/broadcast.go @@ -253,7 +253,7 @@ func (s *peggyBroadcastClient) sendOldDepositClaims( "destination": sdk.AccAddress(oldDeposit.Destination[12:32]).String(), "amount": oldDeposit.Amount.String(), "event_nonce": oldDeposit.EventNonce.String(), - }).Debugln("observed SendToCosmosEvent. Sending claim...") + }).Debugln("observed SendToCosmosEvent") msg := &types.MsgDepositClaim{ EventNonce: oldDeposit.EventNonce.Uint64(), @@ -274,7 +274,7 @@ func (s *peggyBroadcastClient) sendOldDepositClaims( log.WithFields(log.Fields{ "event_nonce": oldDeposit.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent SendToCosmosEvent successfully") + }).Debugln("Oracle sent MsgDepositClaim") } return nil @@ -299,7 +299,7 @@ func (s *peggyBroadcastClient) sendDepositClaims( "amount": deposit.Amount.String(), "event_nonce": deposit.EventNonce.String(), "data": deposit.Data, - }).Debugln("observed SendToInjectiveEvent. Sending claim...") + }).Debugln("observed SendToInjectiveEvent") msg := &types.MsgDepositClaim{ EventNonce: deposit.EventNonce.Uint64(), @@ -320,7 +320,7 @@ func (s *peggyBroadcastClient) sendDepositClaims( log.WithFields(log.Fields{ "event_nonce": deposit.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent SendToInjectiveEvent successfully") + }).Debugln("Oracle sent MsgDepositClaim") } return nil @@ -338,7 +338,7 @@ func (s *peggyBroadcastClient) sendWithdrawClaims( "nonce": withdraw.BatchNonce.String(), "token_contract": withdraw.Token.Hex(), "event_nonce": withdraw.EventNonce.String(), - }).Debugln("observed TransactionBatchExecutedEvent. Sending claim...") + }).Debugln("observed TransactionBatchExecutedEvent") // WithdrawClaim claims that a batch of withdrawal // operations on the bridge contract was executed. @@ -358,7 +358,7 @@ func (s *peggyBroadcastClient) sendWithdrawClaims( log.WithFields(log.Fields{ "event_nonce": withdraw.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent TransactionBatchExecutedEvent successfully") + }).Debugln("Oracle sent MsgWithdrawClaim") } return nil @@ -379,7 +379,7 @@ func (s *peggyBroadcastClient) sendValsetUpdateClaims( "powers": valsetUpdate.Powers, "reward_amount": valsetUpdate.RewardAmount, "reward_token": valsetUpdate.RewardToken.Hex(), - }).Debugln("observed ValsetUpdatedEvent. Sending claim...") + }).Debugln("observed ValsetUpdatedEvent") members := make([]*types.BridgeValidator, len(valsetUpdate.Validators)) for i, val := range valsetUpdate.Validators { @@ -407,7 +407,7 @@ func (s *peggyBroadcastClient) sendValsetUpdateClaims( log.WithFields(log.Fields{ "event_nonce": valsetUpdate.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent ValsetUpdatedEvent successfully") + }).Debugln("Oracle sent MsgValsetUpdatedClaim") } return nil @@ -428,7 +428,7 @@ func (s *peggyBroadcastClient) sendErc20DeployedClaims( "name": erc20Deployed.Name, "symbol": erc20Deployed.Symbol, "decimals": erc20Deployed.Decimals, - }).Debugln("observed ERC20DeployedEvent. Sending claim...") + }).Debugln("observed ERC20DeployedEvent") msg := &types.MsgERC20DeployedClaim{ EventNonce: erc20Deployed.EventNonce.Uint64(), @@ -449,7 +449,7 @@ func (s *peggyBroadcastClient) sendErc20DeployedClaims( log.WithFields(log.Fields{ "event_nonce": erc20Deployed.EventNonce.String(), "tx_hash": txResponse.TxResponse.TxHash, - }).Infoln("Oracle sent ERC20DeployedEvent successfully") + }).Debugln("Oracle sent MsgERC20DeployedClaim") } return nil From 25abdbafe55ae14377427f3894a30c1754d35b35 Mon Sep 17 00:00:00 2001 From: Albert Chon Date: Fri, 5 Jan 2024 13:23:20 +0900 Subject: [PATCH 35/35] chore: change ethBlockConfirmationDelay back to 12 --- orchestrator/oracle.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/orchestrator/oracle.go b/orchestrator/oracle.go index 4a755f9a..b6b6a108 100644 --- a/orchestrator/oracle.go +++ b/orchestrator/oracle.go @@ -9,6 +9,7 @@ import ( log "github.com/xlab/suplog" "github.com/InjectiveLabs/metrics" + "github.com/InjectiveLabs/peggo/orchestrator/loops" peggyevents "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol" ) @@ -18,7 +19,7 @@ import ( // we broadcast only 20 events in each iteration. // So better to search only 20 blocks to ensure all the events are broadcast to Injective Chain without misses. const ( - ethBlockConfirmationDelay uint64 = 96 + ethBlockConfirmationDelay uint64 = 12 defaultBlocksToSearch uint64 = 2000 )