From f09e8fd5aa3c598a2df8ffa4b794be896fbcaa3d Mon Sep 17 00:00:00 2001 From: dantaik <99078276+dantaik@users.noreply.github.com> Date: Fri, 18 Nov 2022 15:01:51 +0800 Subject: [PATCH 1/6] Enable whitelisting provers --- packages/protocol/contracts/L1/LibData.sol | 1 + packages/protocol/contracts/L1/TaikoL1.sol | 25 ++++++++++++- .../protocol/contracts/L1/v1/V1Events.sol | 2 ++ .../protocol/contracts/L1/v1/V1Proving.sol | 36 +++++++++++++++++-- .../protocol/contracts/libs/LibConstants.sol | 2 ++ 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/packages/protocol/contracts/L1/LibData.sol b/packages/protocol/contracts/L1/LibData.sol index 5b22387b9f..04c6f6aafb 100644 --- a/packages/protocol/contracts/L1/LibData.sol +++ b/packages/protocol/contracts/L1/LibData.sol @@ -43,6 +43,7 @@ library LibData { // block id => parent hash => fork choice mapping(uint256 => mapping(bytes32 => ForkChoice)) forkChoices; mapping(bytes32 => uint256) commits; + mapping(address => bool) provers; // Whitelisted provers uint64 genesisHeight; uint64 latestFinalizedHeight; uint64 latestFinalizedId; diff --git a/packages/protocol/contracts/L1/TaikoL1.sol b/packages/protocol/contracts/L1/TaikoL1.sol index c038ae4401..2d4a8e7513 100644 --- a/packages/protocol/contracts/L1/TaikoL1.sol +++ b/packages/protocol/contracts/L1/TaikoL1.sol @@ -28,7 +28,7 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { using SafeCastUpgradeable for uint256; LibData.State public state; - uint256[45] private __gap; + uint256[44] private __gap; function init( address _addressManager, @@ -134,6 +134,29 @@ contract TaikoL1 is EssentialContract, IHeaderSync, V1Events { ); } + /** + * Add or remove a prover from the whitelist. + * + * @param prover The prover to be added or removed. + * @param whitelisted True to add; remove otherwise. + */ + function whitelistProver( + address prover, + bool whitelisted + ) public onlyOwner { + V1Proving.whitelistProver(state, prover, whitelisted); + } + + /** + * Return whether a prover is whitelisted. + * + * @param prover The prover. + * @return True if the prover is whitelisted, false otherwise. + */ + function isProverWhitelisted(address prover) public view returns (bool) { + return V1Proving.isProverWhitelisted(state, prover); + } + /// @notice Finalize up to N blocks. /// @param maxBlocks Max number of blocks to finalize. function finalizeBlocks(uint256 maxBlocks) external nonReentrant { diff --git a/packages/protocol/contracts/L1/v1/V1Events.sol b/packages/protocol/contracts/L1/v1/V1Events.sol index e870d63ed9..92d53e2255 100644 --- a/packages/protocol/contracts/L1/v1/V1Events.sol +++ b/packages/protocol/contracts/L1/v1/V1Events.sol @@ -27,4 +27,6 @@ abstract contract V1Events { uint64 provenAt, address prover ); + + event ProverWhitelisted(address prover, bool whitelisted); } diff --git a/packages/protocol/contracts/L1/v1/V1Proving.sol b/packages/protocol/contracts/L1/v1/V1Proving.sol index 85fb5ad74d..7c0fb97755 100644 --- a/packages/protocol/contracts/L1/v1/V1Proving.sol +++ b/packages/protocol/contracts/L1/v1/V1Proving.sol @@ -46,12 +46,21 @@ library V1Proving { address prover ); + event ProverWhitelisted(address prover, bool whitelisted); + + modifier onlyWhitelistedProver(LibData.State storage s) { + if (LibConstants.TAIKO_WHITELIST_PROVERS) { + require(s.provers[msg.sender], "L1:whitelist"); + } + _; + } + function proveBlock( LibData.State storage s, AddressResolver resolver, uint256 blockIndex, bytes[] calldata inputs - ) public { + ) public onlyWhitelistedProver(s) { // Check and decode inputs require(inputs.length == 3, "L1:inputs:size"); Evidence memory evidence = abi.decode(inputs[0], (Evidence)); @@ -126,7 +135,7 @@ library V1Proving { AddressResolver resolver, uint256 blockIndex, bytes[] calldata inputs - ) public { + ) public onlyWhitelistedProver(s) { // Check and decode inputs require(inputs.length == 3, "L1:inputs:size"); Evidence memory evidence = abi.decode(inputs[0], (Evidence)); @@ -182,6 +191,29 @@ library V1Proving { ); } + function whitelistProver( + LibData.State storage s, + address prover, + bool enabled + ) public { + require(LibConstants.TAIKO_WHITELIST_PROVERS, "L1:featureDisabled"); + require( + prover != address(0) && s.provers[prover] != enabled, + "L1:precondition" + ); + + s.provers[prover] = enabled; + emit ProverWhitelisted(prover, enabled); + } + + function isProverWhitelisted( + LibData.State storage s, + address prover + ) public view returns (bool) { + require(LibConstants.TAIKO_WHITELIST_PROVERS, "L1:featureDisabled"); + return s.provers[prover]; + } + function _proveBlock( LibData.State storage s, AddressResolver resolver, diff --git a/packages/protocol/contracts/libs/LibConstants.sol b/packages/protocol/contracts/libs/LibConstants.sol index 98593758d6..9ab878e9ed 100644 --- a/packages/protocol/contracts/libs/LibConstants.sol +++ b/packages/protocol/contracts/libs/LibConstants.sol @@ -31,4 +31,6 @@ library LibConstants { bytes32 public constant V1_INVALIDATE_BLOCK_LOG_TOPIC = keccak256("BlockInvalidated(bytes32)"); + + bool public constant TAIKO_WHITELIST_PROVERS = false; } From 46af7e124ddab039fb9bfd8995cb2b4f6918b503 Mon Sep 17 00:00:00 2001 From: dantaik <99078276+dantaik@users.noreply.github.com> Date: Fri, 18 Nov 2022 15:02:04 +0800 Subject: [PATCH 2/6] reformat --- .../contracts/test/bridge/libs/TestBadReceiver.sol | 1 - .../contracts/test/bridge/libs/TestLibBridgeRetry.sol | 8 ++++---- .../contracts/test/thirdparty/TestMessageSender.sol | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/protocol/contracts/test/bridge/libs/TestBadReceiver.sol b/packages/protocol/contracts/test/bridge/libs/TestBadReceiver.sol index 0ed64f9bc8..2a050934a0 100644 --- a/packages/protocol/contracts/test/bridge/libs/TestBadReceiver.sol +++ b/packages/protocol/contracts/test/bridge/libs/TestBadReceiver.sol @@ -8,7 +8,6 @@ // ╱╱╰╯╰╯╰┻┻╯╰┻━━╯╰━━━┻╯╰┻━━┻━━╯ pragma solidity ^0.8.9; - contract TestBadReceiver { receive() external payable { revert("can not send to this contract"); diff --git a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol index 512a4efd18..8de54c2eaf 100644 --- a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol +++ b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol @@ -21,10 +21,10 @@ contract TestLibBridgeRetry is EssentialContract { EssentialContract._init(_addressManager); } - function retryMessage(IBridge.Message calldata message, bool lastAttempt) - public - payable - { + function retryMessage( + IBridge.Message calldata message, + bool lastAttempt + ) public payable { LibBridgeRetry.retryMessage( state, AddressResolver(this), diff --git a/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol b/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol index 0a907dea5c..a5fd7697b4 100644 --- a/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol +++ b/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.9; import "../../bridge/IBridge.sol"; contract TestMessageSender { - - bytes32 signal = 0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab; + bytes32 signal = + 0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab; function sendMessage( IBridge.Message calldata message From 6c60bec584ab74556493dcf26477d9739601734d Mon Sep 17 00:00:00 2001 From: dantaik <99078276+dantaik@users.noreply.github.com> Date: Fri, 18 Nov 2022 15:08:07 +0800 Subject: [PATCH 3/6] index event --- packages/protocol/contracts/L1/v1/V1Events.sol | 2 +- packages/protocol/contracts/L1/v1/V1Proving.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/protocol/contracts/L1/v1/V1Events.sol b/packages/protocol/contracts/L1/v1/V1Events.sol index 92d53e2255..90f0ca94c3 100644 --- a/packages/protocol/contracts/L1/v1/V1Events.sol +++ b/packages/protocol/contracts/L1/v1/V1Events.sol @@ -28,5 +28,5 @@ abstract contract V1Events { address prover ); - event ProverWhitelisted(address prover, bool whitelisted); + event ProverWhitelisted(address indexed prover, bool whitelisted); } diff --git a/packages/protocol/contracts/L1/v1/V1Proving.sol b/packages/protocol/contracts/L1/v1/V1Proving.sol index 7c0fb97755..6a73c82380 100644 --- a/packages/protocol/contracts/L1/v1/V1Proving.sol +++ b/packages/protocol/contracts/L1/v1/V1Proving.sol @@ -46,7 +46,7 @@ library V1Proving { address prover ); - event ProverWhitelisted(address prover, bool whitelisted); + event ProverWhitelisted(address indexed prover, bool whitelisted); modifier onlyWhitelistedProver(LibData.State storage s) { if (LibConstants.TAIKO_WHITELIST_PROVERS) { From cbd8d69da06f6cf52058d39a26211a3afa73801e Mon Sep 17 00:00:00 2001 From: dantaik <99078276+dantaik@users.noreply.github.com> Date: Fri, 18 Nov 2022 15:10:25 +0800 Subject: [PATCH 4/6] rename constant --- packages/protocol/contracts/L1/v1/V1Proving.sol | 6 +++--- packages/protocol/contracts/libs/LibConstants.sol | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/protocol/contracts/L1/v1/V1Proving.sol b/packages/protocol/contracts/L1/v1/V1Proving.sol index 6a73c82380..0be26baf0e 100644 --- a/packages/protocol/contracts/L1/v1/V1Proving.sol +++ b/packages/protocol/contracts/L1/v1/V1Proving.sol @@ -49,7 +49,7 @@ library V1Proving { event ProverWhitelisted(address indexed prover, bool whitelisted); modifier onlyWhitelistedProver(LibData.State storage s) { - if (LibConstants.TAIKO_WHITELIST_PROVERS) { + if (LibConstants.K_WHITELIST_PROVERS) { require(s.provers[msg.sender], "L1:whitelist"); } _; @@ -196,7 +196,7 @@ library V1Proving { address prover, bool enabled ) public { - require(LibConstants.TAIKO_WHITELIST_PROVERS, "L1:featureDisabled"); + require(LibConstants.K_WHITELIST_PROVERS, "L1:featureDisabled"); require( prover != address(0) && s.provers[prover] != enabled, "L1:precondition" @@ -210,7 +210,7 @@ library V1Proving { LibData.State storage s, address prover ) public view returns (bool) { - require(LibConstants.TAIKO_WHITELIST_PROVERS, "L1:featureDisabled"); + require(LibConstants.K_WHITELIST_PROVERS, "L1:featureDisabled"); return s.provers[prover]; } diff --git a/packages/protocol/contracts/libs/LibConstants.sol b/packages/protocol/contracts/libs/LibConstants.sol index 9ab878e9ed..870c512288 100644 --- a/packages/protocol/contracts/libs/LibConstants.sol +++ b/packages/protocol/contracts/libs/LibConstants.sol @@ -32,5 +32,5 @@ library LibConstants { bytes32 public constant V1_INVALIDATE_BLOCK_LOG_TOPIC = keccak256("BlockInvalidated(bytes32)"); - bool public constant TAIKO_WHITELIST_PROVERS = false; + bool public constant K_WHITELIST_PROVERS = false; } From f6dab0c2781a9c6bcac9a630072d474b22c85a2b Mon Sep 17 00:00:00 2001 From: cyberhorsey <113397187+cyberhorsey@users.noreply.github.com> Date: Sat, 19 Nov 2022 07:09:03 -0800 Subject: [PATCH 5/6] chore(relayer): add HTTP service for health and prometheus metrics (#295) --- go.mod | 19 ++++- go.sum | 107 +++++++++++++++++++++++++ packages/relayer/.default.env | 4 +- packages/relayer/cli/cli.go | 16 ++++ packages/relayer/http/errors.go | 14 ++++ packages/relayer/http/routes.go | 5 ++ packages/relayer/http/server.go | 115 +++++++++++++++++++++++++++ packages/relayer/http/server_test.go | 97 ++++++++++++++++++++++ 8 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 packages/relayer/http/errors.go create mode 100644 packages/relayer/http/routes.go create mode 100644 packages/relayer/http/server.go create mode 100644 packages/relayer/http/server_test.go diff --git a/go.mod b/go.mod index 342d122c9b..879b65ab04 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/cyberhorsey/errors v0.0.0-20220929234051-087d6d8bb841 github.com/ethereum/go-ethereum v1.10.25 github.com/joho/godotenv v1.4.0 + github.com/labstack/echo/v4 v4.9.1 github.com/pkg/errors v0.9.1 github.com/pressly/goose v2.7.0+incompatible github.com/pressly/goose/v3 v3.7.0 @@ -26,8 +27,10 @@ require ( github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Microsoft/hcsshim v0.9.4 // indirect github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/containerd/cgroups v1.0.4 // indirect github.com/containerd/containerd v1.6.8 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -41,13 +44,19 @@ require ( github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/labstack/echo-contrib v0.13.0 // indirect + github.com/labstack/gommon v0.4.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/moby/sys/mount v0.3.3 // indirect github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect @@ -56,17 +65,25 @@ require ( github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/opencontainers/runc v1.1.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.12.2 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect github.com/rjeczalik/notify v0.9.1 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.1 // indirect go.opencensus.io v0.23.0 // indirect golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad // indirect - google.golang.org/grpc v1.47.0 // indirect + google.golang.org/grpc v1.48.0 // indirect google.golang.org/protobuf v1.28.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index f3aa718ca9..770b714051 100644 --- a/go.sum +++ b/go.sum @@ -10,18 +10,27 @@ cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6T cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 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= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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/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= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 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= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= @@ -79,6 +88,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -87,6 +97,7 @@ github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZo github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= @@ -111,6 +122,7 @@ 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= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= @@ -328,9 +340,11 @@ github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= 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= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= @@ -367,6 +381,8 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= @@ -387,6 +403,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -412,6 +429,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a 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= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -424,12 +442,14 @@ github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYV github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -536,13 +556,17 @@ github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52Cu github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -563,6 +587,12 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/labstack/echo-contrib v0.13.0 h1:bzSG0SpuZZd7BmJLvsWtPfU23W0Enh3K0tok3aENVKA= +github.com/labstack/echo-contrib v0.13.0/go.mod h1:IF9+MJu22ADOZEHD+bAV67XMIO3vNXUy7Naz/ABPHEs= +github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y= +github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo= +github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -579,12 +609,15 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= @@ -593,6 +626,7 @@ github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= @@ -618,6 +652,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= @@ -625,6 +660,7 @@ github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2 github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= @@ -700,10 +736,15 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= @@ -711,6 +752,10 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -722,6 +767,9 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= @@ -812,6 +860,10 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -826,7 +878,9 @@ github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= @@ -843,6 +897,7 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= @@ -942,6 +997,10 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -950,9 +1009,12 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -960,6 +1022,8 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= 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= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1022,10 +1086,16 @@ golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1045,18 +1115,24 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1074,6 +1150,9 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1115,11 +1194,20 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -1140,8 +1228,13 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1168,11 +1261,20 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad h1:kqrS+lhvaMHCxul6sKQvKJ8nAAhlVItmZV822hYFH/U= google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= @@ -1188,14 +1290,18 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= 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= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1275,6 +1381,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 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= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= diff --git a/packages/relayer/.default.env b/packages/relayer/.default.env index 948eb9fb34..3944213170 100644 --- a/packages/relayer/.default.env +++ b/packages/relayer/.default.env @@ -1,4 +1,5 @@ HTTP_PORT=4102 +PROMETHEUS_HTTP_PORT=6060 MYSQL_USER=root MYSQL_PASSWORD=root MYSQL_DATABASE=relayer @@ -16,4 +17,5 @@ MYSQL_MAX_OPEN_CONNS= MYSQL_CONN_MAX_LIFETIME_IN_MS= NUM_GOROUTINES=20 SUBSCRIPTION_BACKOFF_IN_SECONDS=3 -CONFIRMATIONS_BEFORE_PROCESSING=15 \ No newline at end of file +CONFIRMATIONS_BEFORE_PROCESSING=15 +CORS_ORIGINS=* \ No newline at end of file diff --git a/packages/relayer/cli/cli.go b/packages/relayer/cli/cli.go index f8df41398f..ea4311ac44 100644 --- a/packages/relayer/cli/cli.go +++ b/packages/relayer/cli/cli.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" + "github.com/labstack/echo/v4" "github.com/ethereum/go-ethereum/ethclient" "github.com/joho/godotenv" @@ -16,6 +17,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/taikochain/taiko-mono/packages/relayer" "github.com/taikochain/taiko-mono/packages/relayer/db" + "github.com/taikochain/taiko-mono/packages/relayer/http" "github.com/taikochain/taiko-mono/packages/relayer/indexer" "github.com/taikochain/taiko-mono/packages/relayer/repo" "gorm.io/driver/mysql" @@ -36,6 +38,7 @@ var ( "MYSQL_HOST", "RELAYER_ECDSA_KEY", "CONFIRMATIONS_BEFORE_PROCESSING", + "PROMETHEUS_HTTP_PORT", } defaultBlockBatchSize = 2 @@ -77,6 +80,13 @@ func Run(mode relayer.Mode, layer relayer.Layer) { log.Fatal(err) } + srv, err := http.NewServer(http.NewServerOpts{ + Echo: echo.New(), + }) + if err != nil { + log.Fatal(err) + } + indexers, closeFunc, err := makeIndexers(layer, db) if err != nil { sqlDB.Close() @@ -96,6 +106,12 @@ func Run(mode relayer.Mode, layer relayer.Layer) { }(i) } + go func() { + if err := srv.Start(fmt.Sprintf(":%v", os.Getenv("HTTP_PORT"))); err != nil { + log.Fatal(err) + } + }() + <-forever } diff --git a/packages/relayer/http/errors.go b/packages/relayer/http/errors.go new file mode 100644 index 0000000000..438fea9c9d --- /dev/null +++ b/packages/relayer/http/errors.go @@ -0,0 +1,14 @@ +package http + +import "github.com/cyberhorsey/errors" + +var ( + ErrNoHTTPFramework = errors.Validation.NewWithKeyAndDetail( + "ERR_NO_HTTP_ENGINE", + "HTTP framework required", + ) + ErrNoRewarder = errors.Validation.NewWithKeyAndDetail( + "ERR_NO_REWARDER", + "Rewarder is required", + ) +) diff --git a/packages/relayer/http/routes.go b/packages/relayer/http/routes.go new file mode 100644 index 0000000000..0b416279db --- /dev/null +++ b/packages/relayer/http/routes.go @@ -0,0 +1,5 @@ +package http + +func (srv *Server) configureRoutes() { + srv.echo.GET("/healthz", srv.Health) +} diff --git a/packages/relayer/http/server.go b/packages/relayer/http/server.go new file mode 100644 index 0000000000..8df99750f6 --- /dev/null +++ b/packages/relayer/http/server.go @@ -0,0 +1,115 @@ +package http + +import ( + "context" + "fmt" + "net/http" + "os" + + "github.com/labstack/echo/v4/middleware" + + echoprom "github.com/labstack/echo-contrib/prometheus" + echo "github.com/labstack/echo/v4" +) + +type Server struct { + echo *echo.Echo +} + +type NewServerOpts struct { + Echo *echo.Echo + CorsOrigins []string +} + +func (opts NewServerOpts) Validate() error { + if opts.Echo == nil { + return ErrNoHTTPFramework + } + + return nil +} + +func NewServer(opts NewServerOpts) (*Server, error) { + if err := opts.Validate(); err != nil { + return nil, err + } + + srv := &Server{ + echo: opts.Echo, + } + + corsOrigins := opts.CorsOrigins + if corsOrigins == nil { + corsOrigins = []string{"*"} + } + + srv.configureMiddleware(corsOrigins) + + return srv, nil +} + +// Start starts the HTTP server +func (srv *Server) Start(address string) error { + return srv.echo.Start(address) +} + +// Shutdown shuts down the HTTP server +func (srv *Server) Shutdown(ctx context.Context) error { + return srv.echo.Shutdown(ctx) +} + +// ServeHTTP implements the `http.Handler` interface which serves HTTP requests +func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { + srv.echo.ServeHTTP(w, r) +} + +// Health endpoints for probes +func (srv *Server) Health(c echo.Context) error { + return c.NoContent(http.StatusOK) +} + +func LogSkipper(c echo.Context) bool { + switch c.Request().URL.Path { + case "/healthz": + return true + case "/metrics": + return true + default: + return false + } +} + +func (srv *Server) configureMiddleware(corsOrigins []string) { + srv.echo.Use(middleware.RequestID()) + + srv.echo.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ + Skipper: LogSkipper, + Format: `{"time":"${time_rfc3339_nano}","level":"INFO","message":{"id":"${id}","remote_ip":"${remote_ip}",` + //nolint:lll + `"host":"${host}","method":"${method}","uri":"${uri}","user_agent":"${user_agent}",` + //nolint:lll + `"response_status":${status},"error":"${error}","latency":${latency},"latency_human":"${latency_human}",` + + `"bytes_in":${bytes_in},"bytes_out":${bytes_out}}}` + "\n", + Output: os.Stdout, + })) + + srv.echo.Use(middleware.CORSWithConfig(middleware.CORSConfig{ + AllowOrigins: corsOrigins, + AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept}, + AllowMethods: []string{http.MethodGet, http.MethodHead}, + })) + + srv.configureAndStartPrometheus() + + srv.configureRoutes() +} + +func (srv *Server) configureAndStartPrometheus() { + // Enable metrics middleware + p := echoprom.NewPrometheus("echo", nil) + p.Use(srv.echo) + e := echo.New() + p.SetMetricsPath(e) + + go func() { + _ = e.Start(fmt.Sprintf(":%v", os.Getenv("PROMETHEUS_HTTP_PORT"))) + }() +} diff --git a/packages/relayer/http/server_test.go b/packages/relayer/http/server_test.go new file mode 100644 index 0000000000..6e05bbcbf6 --- /dev/null +++ b/packages/relayer/http/server_test.go @@ -0,0 +1,97 @@ +package http + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/joho/godotenv" + echo "github.com/labstack/echo/v4" + "github.com/stretchr/testify/assert" +) + +func newTestServer(url string) *Server { + _ = godotenv.Load("../.test.env") + + srv := &Server{ + echo: echo.New(), + } + + srv.configureMiddleware([]string{"*"}) + srv.configureRoutes() + srv.configureAndStartPrometheus() + + return srv +} + +func Test_NewServer(t *testing.T) { + tests := []struct { + name string + opts NewServerOpts + wantErr error + }{ + { + "success", + NewServerOpts{ + Echo: echo.New(), + CorsOrigins: make([]string, 0), + }, + nil, + }, + { + "noCorsOrigins", + NewServerOpts{ + Echo: echo.New(), + }, + nil, + }, + { + "noHttpFramework", + NewServerOpts{ + CorsOrigins: make([]string, 0), + }, + ErrNoHTTPFramework, + }, + } + + for _, tt := range tests { + _, err := NewServer(tt.opts) + assert.Equal(t, tt.wantErr, err) + } +} + +func Test_Health(t *testing.T) { + srv := newTestServer("") + + req, _ := http.NewRequest(echo.GET, "/healthz", nil) + rec := httptest.NewRecorder() + + srv.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("Test_Health expected code %v, got %v", http.StatusOK, rec.Code) + } +} + +func Test_Metrics(t *testing.T) { + srv := newTestServer("") + + req, _ := http.NewRequest(echo.GET, "/metrics", nil) + rec := httptest.NewRecorder() + + srv.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("Test_Metrics expected code %v, got %v", http.StatusOK, rec.Code) + } +} + +func Test_StartShutdown(t *testing.T) { + srv := newTestServer("") + + go func() { + _ = srv.Start(":3928") + }() + assert.Nil(t, srv.Shutdown(context.Background())) +} From a1a1d65d6e022ad323a5a23514367106308936cc Mon Sep 17 00:00:00 2001 From: cyberhorsey <113397187+cyberhorsey@users.noreply.github.com> Date: Sat, 19 Nov 2022 07:09:44 -0800 Subject: [PATCH 6/6] chore(relayer): add additional test coverage (#291) --- packages/relayer/.golangci.yml | 4 +- packages/relayer/bridge.go | 22 ++++ packages/relayer/caller.go | 7 ++ packages/relayer/cli/cli.go | 4 +- packages/relayer/cmd/main.go | 9 +- packages/relayer/flags.go | 9 ++ packages/relayer/header_syncer.go | 7 ++ .../relayer/indexer/filter_then_subscribe.go | 14 ++- .../indexer/filter_then_subscribe_test.go | 73 +++++++++++++ packages/relayer/indexer/handle_event.go | 2 + packages/relayer/indexer/handle_event_test.go | 2 +- .../indexer/handle_no_events_in_batch_test.go | 2 +- .../handle_no_events_remaining_test.go | 2 +- packages/relayer/indexer/service.go | 4 +- packages/relayer/indexer/service_test.go | 36 +++++- ...t_initial_processing_block_by_mode_test.go | 2 +- packages/relayer/indexer/subscribe.go | 12 ++ packages/relayer/indexer/subscribe_test.go | 26 +++++ packages/relayer/message/process_message.go | 4 +- .../relayer/message/process_message_test.go | 93 ++++++++++++++++ packages/relayer/message/processor.go | 30 ++--- packages/relayer/message/processor_test.go | 24 ++++ packages/relayer/mock/bridge.go | 103 ++++++++++++++++++ packages/relayer/mock/eth_client.go | 40 ++++++- packages/relayer/mock/event_repository.go | 16 +++ packages/relayer/mock/header_syncer.go | 21 ++++ .../relayer/proof/encoded_signal_proof.go | 5 +- packages/relayer/proof/types.go | 5 - 28 files changed, 539 insertions(+), 39 deletions(-) create mode 100644 packages/relayer/bridge.go create mode 100644 packages/relayer/caller.go create mode 100644 packages/relayer/header_syncer.go create mode 100644 packages/relayer/indexer/filter_then_subscribe_test.go create mode 100644 packages/relayer/indexer/subscribe_test.go create mode 100644 packages/relayer/message/process_message_test.go create mode 100644 packages/relayer/mock/bridge.go create mode 100644 packages/relayer/mock/event_repository.go create mode 100644 packages/relayer/mock/header_syncer.go diff --git a/packages/relayer/.golangci.yml b/packages/relayer/.golangci.yml index b2008b7e90..57711e7574 100644 --- a/packages/relayer/.golangci.yml +++ b/packages/relayer/.golangci.yml @@ -13,6 +13,7 @@ output: linters: enable: + - errcheck - funlen - gocognit - gocritic @@ -21,6 +22,7 @@ linters: - gosec - gosimple - lll + - unused - whitespace - wsl @@ -29,7 +31,7 @@ linters-settings: lines: 116 statements: 48 gocognit: - min-complexity: 35 + min-complexity: 37 issues: exclude-rules: diff --git a/packages/relayer/bridge.go b/packages/relayer/bridge.go new file mode 100644 index 0000000000..450debdfba --- /dev/null +++ b/packages/relayer/bridge.go @@ -0,0 +1,22 @@ +package relayer + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/taikochain/taiko-mono/packages/relayer/contracts" +) + +type Bridge interface { + WatchMessageSent( + opts *bind.WatchOpts, + sink chan<- *contracts.BridgeMessageSent, + signal [][32]byte, + ) (event.Subscription, error) + FilterMessageSent(opts *bind.FilterOpts, signal [][32]byte) (*contracts.BridgeMessageSentIterator, error) + GetMessageStatus(opts *bind.CallOpts, signal [32]byte) (uint8, error) + ProcessMessage(opts *bind.TransactOpts, message contracts.IBridgeMessage, proof []byte) (*types.Transaction, error) + IsMessageReceived(opts *bind.CallOpts, signal [32]byte, srcChainId *big.Int, proof []byte) (bool, error) // nolint +} diff --git a/packages/relayer/caller.go b/packages/relayer/caller.go new file mode 100644 index 0000000000..9902151cfc --- /dev/null +++ b/packages/relayer/caller.go @@ -0,0 +1,7 @@ +package relayer + +import "context" + +type Caller interface { + CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error +} diff --git a/packages/relayer/cli/cli.go b/packages/relayer/cli/cli.go index ea4311ac44..22c88d65f9 100644 --- a/packages/relayer/cli/cli.go +++ b/packages/relayer/cli/cli.go @@ -47,7 +47,7 @@ var ( defaultConfirmations = 15 ) -func Run(mode relayer.Mode, layer relayer.Layer) { +func Run(mode relayer.Mode, watchMode relayer.WatchMode, layer relayer.Layer) { if err := loadAndValidateEnv(); err != nil { log.Fatal(err) } @@ -100,7 +100,7 @@ func Run(mode relayer.Mode, layer relayer.Layer) { for _, i := range indexers { go func(i *indexer.Service) { - if err := i.FilterThenSubscribe(context.Background(), mode); err != nil { + if err := i.FilterThenSubscribe(context.Background(), mode, watchMode); err != nil { log.Fatal(err) } }(i) diff --git a/packages/relayer/cmd/main.go b/packages/relayer/cmd/main.go index 4a23067f7f..e583c5c285 100644 --- a/packages/relayer/cmd/main.go +++ b/packages/relayer/cmd/main.go @@ -23,6 +23,13 @@ func main() { both: watch l1 => l2 and l2 => l1 bridge messages `) + watchModePtr := flag.String("watch-mode", string(relayer.FilterAndSubscribeWatchMode), `watch mode to run in. + options: + filter: only filter previous messages + subscribe: only subscribe to new messages + filter-and-subscribe: catch up on all previous messages, then subscribe to new messages + `) + flag.Parse() if !relayer.IsInSlice(relayer.Mode(*modePtr), relayer.Modes) { @@ -33,5 +40,5 @@ func main() { log.Fatal("mode not valid") } - cli.Run(relayer.Mode(*modePtr), relayer.Layer(*layersPtr)) + cli.Run(relayer.Mode(*modePtr), relayer.WatchMode(*watchModePtr), relayer.Layer(*layersPtr)) } diff --git a/packages/relayer/flags.go b/packages/relayer/flags.go index 4baeee3c30..9fa09507fd 100644 --- a/packages/relayer/flags.go +++ b/packages/relayer/flags.go @@ -16,3 +16,12 @@ var ( Both Layer = "both" Layers = []Layer{L1, L2, Both} ) + +type WatchMode string + +var ( + FilterWatchMode WatchMode = "filter" + SubscribeWatchMode WatchMode = "subscribe" + FilterAndSubscribeWatchMode WatchMode = "filter-and-subscribe" + WatchModes = []WatchMode{FilterWatchMode, SubscribeWatchMode} +) diff --git a/packages/relayer/header_syncer.go b/packages/relayer/header_syncer.go new file mode 100644 index 0000000000..069feb37c6 --- /dev/null +++ b/packages/relayer/header_syncer.go @@ -0,0 +1,7 @@ +package relayer + +import "github.com/ethereum/go-ethereum/accounts/abi/bind" + +type HeaderSyncer interface { + GetLatestSyncedHeader(opts *bind.CallOpts) ([32]byte, error) +} diff --git a/packages/relayer/indexer/filter_then_subscribe.go b/packages/relayer/indexer/filter_then_subscribe.go index 6924969270..b1d6cc4350 100644 --- a/packages/relayer/indexer/filter_then_subscribe.go +++ b/packages/relayer/indexer/filter_then_subscribe.go @@ -17,12 +17,17 @@ var ( // FilterThenSubscribe gets the most recent block height that has been indexed, and works it's way // up to the latest block. As it goes, it tries to process messages. // When it catches up, it then starts to Subscribe to latest events as they come in. -func (svc *Service) FilterThenSubscribe(ctx context.Context, mode relayer.Mode) error { +func (svc *Service) FilterThenSubscribe(ctx context.Context, mode relayer.Mode, watchMode relayer.WatchMode) error { chainID, err := svc.ethClient.ChainID(ctx) if err != nil { return errors.Wrap(err, "svc.ethClient.ChainID()") } + // if subscribing to new events, skip filtering and subscribe + if watchMode == relayer.SubscribeWatchMode { + return svc.subscribe(ctx, chainID) + } + if err := svc.setInitialProcessingBlockByMode(ctx, mode, chainID); err != nil { return errors.Wrap(err, "svc.setInitialProcessingBlockByMode") } @@ -107,7 +112,12 @@ func (svc *Service) FilterThenSubscribe(ctx context.Context, mode relayer.Mode) } if svc.processingBlock.Height < latestBlock.Number.Uint64() { - return svc.FilterThenSubscribe(ctx, relayer.SyncMode) + return svc.FilterThenSubscribe(ctx, relayer.SyncMode, watchMode) + } + + // we are caught up and specified not to subscribe, we can return now + if watchMode == relayer.FilterWatchMode { + return nil } return svc.subscribe(ctx, chainID) diff --git a/packages/relayer/indexer/filter_then_subscribe_test.go b/packages/relayer/indexer/filter_then_subscribe_test.go new file mode 100644 index 0000000000..107dee3369 --- /dev/null +++ b/packages/relayer/indexer/filter_then_subscribe_test.go @@ -0,0 +1,73 @@ +package indexer + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/taikochain/taiko-mono/packages/relayer" + "github.com/taikochain/taiko-mono/packages/relayer/mock" +) + +func Test_FilterThenSubscribe(t *testing.T) { + svc, bridge := newTestService() + b := bridge.(*mock.Bridge) + + svc.processingBlock = &relayer.Block{ + Height: 0, + } + + go func() { + _ = svc.FilterThenSubscribe( + context.Background(), + relayer.Mode(relayer.SyncMode), + relayer.FilterAndSubscribeWatchMode, + ) + }() + + <-time.After(6 * time.Second) + + assert.Equal(t, b.MessagesSent, 1) + assert.Equal(t, b.ErrorsSent, 1) +} + +func Test_FilterThenSubscribe_subscribeWatchMode(t *testing.T) { + svc, bridge := newTestService() + b := bridge.(*mock.Bridge) + + go func() { + _ = svc.FilterThenSubscribe( + context.Background(), + relayer.Mode(relayer.SyncMode), + relayer.SubscribeWatchMode, + ) + }() + + <-time.After(6 * time.Second) + + assert.Equal(t, b.MessagesSent, 1) + assert.Equal(t, b.ErrorsSent, 1) +} + +func Test_FilterThenSubscribe_alreadyCaughtUp(t *testing.T) { + svc, bridge := newTestService() + b := bridge.(*mock.Bridge) + + svc.processingBlock = &relayer.Block{ + Height: mock.LatestBlockNumber.Uint64(), + } + + go func() { + _ = svc.FilterThenSubscribe( + context.Background(), + relayer.Mode(relayer.SyncMode), + relayer.FilterAndSubscribeWatchMode, + ) + }() + + <-time.After(6 * time.Second) + + assert.Equal(t, b.MessagesSent, 1) + assert.Equal(t, b.ErrorsSent, 1) +} diff --git a/packages/relayer/indexer/handle_event.go b/packages/relayer/indexer/handle_event.go index bd98caabc8..075bcaec96 100644 --- a/packages/relayer/indexer/handle_event.go +++ b/packages/relayer/indexer/handle_event.go @@ -18,6 +18,8 @@ func (svc *Service) handleEvent( chainID *big.Int, event *contracts.BridgeMessageSent, ) error { + log.Infof("event found for signal: %v", common.Hash(event.Signal).Hex()) + raw := event.Raw // handle chain re-org by checking Removed property, no need to diff --git a/packages/relayer/indexer/handle_event_test.go b/packages/relayer/indexer/handle_event_test.go index 4d6e140b0c..bde0b48281 100644 --- a/packages/relayer/indexer/handle_event_test.go +++ b/packages/relayer/indexer/handle_event_test.go @@ -102,7 +102,7 @@ func Test_eventStatusFromSignal(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - svc := newTestService() + svc, _ := newTestService() status, err := svc.eventStatusFromSignal(tt.ctx, tt.gasLimit, tt.signal) if tt.wantErr != nil { diff --git a/packages/relayer/indexer/handle_no_events_in_batch_test.go b/packages/relayer/indexer/handle_no_events_in_batch_test.go index 0c54dc8ae3..d4d5e92f72 100644 --- a/packages/relayer/indexer/handle_no_events_in_batch_test.go +++ b/packages/relayer/indexer/handle_no_events_in_batch_test.go @@ -25,7 +25,7 @@ func Test_handleNoEventsInBatch(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - svc := newTestService() + svc, _ := newTestService() assert.NotEqual(t, svc.processingBlock.Height, uint64(tt.blockNumber)) diff --git a/packages/relayer/indexer/handle_no_events_remaining_test.go b/packages/relayer/indexer/handle_no_events_remaining_test.go index 1758e7d773..eeba6cb2c3 100644 --- a/packages/relayer/indexer/handle_no_events_remaining_test.go +++ b/packages/relayer/indexer/handle_no_events_remaining_test.go @@ -33,7 +33,7 @@ func Test_handleNoEventsRemaining(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - svc := newTestService() + svc, _ := newTestService() err := svc.handleNoEventsRemaining(context.Background(), tt.chainID, tt.events) assert.Equal(t, tt.wantErr, err) }) diff --git a/packages/relayer/indexer/service.go b/packages/relayer/indexer/service.go index dd5a8b847f..afc9072e77 100644 --- a/packages/relayer/indexer/service.go +++ b/packages/relayer/indexer/service.go @@ -35,8 +35,8 @@ type Service struct { processingBlock *relayer.Block - bridge *contracts.Bridge - destBridge *contracts.Bridge + bridge relayer.Bridge + destBridge relayer.Bridge processor *message.Processor diff --git a/packages/relayer/indexer/service_test.go b/packages/relayer/indexer/service_test.go index 4668c7cdcf..880001a8d5 100644 --- a/packages/relayer/indexer/service_test.go +++ b/packages/relayer/indexer/service_test.go @@ -5,24 +5,52 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/assert" "github.com/taikochain/taiko-mono/packages/relayer" + "github.com/taikochain/taiko-mono/packages/relayer/message" "github.com/taikochain/taiko-mono/packages/relayer/mock" + "github.com/taikochain/taiko-mono/packages/relayer/proof" "github.com/taikochain/taiko-mono/packages/relayer/repo" ) var dummyEcdsaKey = "8da4ef21b864d2cc526dbdb2a120bd2874c36c9d0a1fb7f8c63d7f7a8b41de8f" var dummyAddress = "0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377" -func newTestService() *Service { +func newTestService() (*Service, relayer.Bridge) { + b := &mock.Bridge{} + + privateKey, _ := crypto.HexToECDSA(dummyEcdsaKey) + + prover, _ := proof.New( + &mock.Blocker{}, + ) + + processor, _ := message.NewProcessor(message.NewProcessorOpts{ + EventRepo: &mock.EventRepository{}, + DestBridge: &mock.Bridge{}, + SrcETHClient: &mock.EthClient{}, + DestETHClient: &mock.EthClient{}, + ECDSAKey: privateKey, + DestHeaderSyncer: &mock.HeaderSyncer{}, + Prover: prover, + RPCClient: &mock.Caller{}, + }) + return &Service{ - blockRepo: &mock.BlockRepository{}, - ethClient: &mock.EthClient{}, + blockRepo: &mock.BlockRepository{}, + eventRepo: &mock.EventRepository{}, + bridge: b, + destBridge: b, + ethClient: &mock.EthClient{}, + numGoroutines: 10, processingBlock: &relayer.Block{}, - } + processor: processor, + blockBatchSize: 100, + }, b } func Test_NewService(t *testing.T) { diff --git a/packages/relayer/indexer/set_initial_processing_block_by_mode_test.go b/packages/relayer/indexer/set_initial_processing_block_by_mode_test.go index 16e158c2b3..8750db7e30 100644 --- a/packages/relayer/indexer/set_initial_processing_block_by_mode_test.go +++ b/packages/relayer/indexer/set_initial_processing_block_by_mode_test.go @@ -50,7 +50,7 @@ func Test_SetInitialProcessingBlockByMode(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - svc := newTestService() + svc, _ := newTestService() err := svc.setInitialProcessingBlockByMode( context.Background(), tt.mode, diff --git a/packages/relayer/indexer/subscribe.go b/packages/relayer/indexer/subscribe.go index 5dd65a3e4e..3ab9f67f8f 100644 --- a/packages/relayer/indexer/subscribe.go +++ b/packages/relayer/indexer/subscribe.go @@ -8,12 +8,24 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/pkg/errors" log "github.com/sirupsen/logrus" + "github.com/taikochain/taiko-mono/packages/relayer" "github.com/taikochain/taiko-mono/packages/relayer/contracts" "golang.org/x/sync/errgroup" ) // subscribe subscribes to latest events func (svc *Service) subscribe(ctx context.Context, chainID *big.Int) error { + log.Info("subscribing to new events") + + latestBlock, err := svc.ethClient.HeaderByNumber(ctx, nil) + if err != nil { + return errors.Wrap(err, "svc.ethClient.HeaderByNumber") + } + + svc.processingBlock = &relayer.Block{ + Height: latestBlock.Number.Uint64(), + } + sink := make(chan *contracts.BridgeMessageSent) sub := event.ResubscribeErr(svc.subscriptionBackoff, func(ctx context.Context, err error) (event.Subscription, error) { diff --git a/packages/relayer/indexer/subscribe_test.go b/packages/relayer/indexer/subscribe_test.go new file mode 100644 index 0000000000..505a6f3206 --- /dev/null +++ b/packages/relayer/indexer/subscribe_test.go @@ -0,0 +1,26 @@ +package indexer + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/taikochain/taiko-mono/packages/relayer/mock" +) + +func Test_subscribe(t *testing.T) { + svc, bridge := newTestService() + + go func() { + _ = svc.subscribe(context.Background(), big.NewInt(1)) + }() + + <-time.After(6 * time.Second) + + b := bridge.(*mock.Bridge) + + assert.Equal(t, b.MessagesSent, 1) + assert.Equal(t, b.ErrorsSent, 1) +} diff --git a/packages/relayer/message/process_message.go b/packages/relayer/message/process_message.go index 7f0c8553d4..3d2dfb50bf 100644 --- a/packages/relayer/message/process_message.go +++ b/packages/relayer/message/process_message.go @@ -26,6 +26,8 @@ func (p *Processor) ProcessMessage( event *contracts.BridgeMessageSent, e *relayer.Event, ) error { + log.Infof("processing message for signal: %v", common.Hash(event.Signal).Hex()) + // TODO: if relayer can not process, save this to DB with status Unprocessable if event.Message.GasLimit == nil || event.Message.GasLimit.Cmp(common.Big0) == 0 { return errors.New("only user can process this, gasLimit set to 0") @@ -55,8 +57,6 @@ func (p *Processor) ProcessMessage( key := hex.EncodeToString(hashed) - log.Infof("processing message for signal: %v, key: %v", common.Hash(event.Signal).Hex(), key) - encodedSignalProof, err := p.prover.EncodedSignalProof(ctx, p.rpc, event.Raw.Address, key, latestSyncedHeader) if err != nil { return errors.Wrap(err, "p.prover.GetEncodedSignalProof") diff --git a/packages/relayer/message/process_message_test.go b/packages/relayer/message/process_message_test.go new file mode 100644 index 0000000000..8febb8bbb0 --- /dev/null +++ b/packages/relayer/message/process_message_test.go @@ -0,0 +1,93 @@ +package message + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/taikochain/taiko-mono/packages/relayer" + "github.com/taikochain/taiko-mono/packages/relayer/contracts" + "github.com/taikochain/taiko-mono/packages/relayer/mock" +) + +func Test_getLatestNonce(t *testing.T) { + p := newTestProcessor() + + err := p.getLatestNonce(context.Background(), &bind.TransactOpts{}) + assert.Nil(t, err) + + assert.Equal(t, p.destNonce, mock.PendingNonce) +} + +func Test_waitForConfirmations(t *testing.T) { + p := newTestProcessor() + + err := p.waitForConfirmations(context.TODO(), mock.SucceedTxHash, uint64(mock.BlockNum)) + assert.Nil(t, err) +} + +func Test_sendProcessMessageCall(t *testing.T) { + p := newTestProcessor() + + _, err := p.sendProcessMessageCall( + context.Background(), + &contracts.BridgeMessageSent{ + Message: contracts.IBridgeMessage{ + DestChainId: mock.MockChainID, + }, + }, []byte{}) + + assert.Nil(t, err) + + assert.Equal(t, p.destNonce, mock.PendingNonce) +} + +func Test_ProcessMessage_messageNotReceived(t *testing.T) { + p := newTestProcessor() + + err := p.ProcessMessage(context.Background(), &contracts.BridgeMessageSent{ + Message: contracts.IBridgeMessage{ + GasLimit: big.NewInt(1), + }, + }, &relayer.Event{}) + assert.EqualError(t, err, "message not received") +} + +func Test_ProcessMessage_gasLimit0(t *testing.T) { + p := newTestProcessor() + + err := p.ProcessMessage(context.Background(), &contracts.BridgeMessageSent{}, &relayer.Event{}) + assert.EqualError(t, errors.New("only user can process this, gasLimit set to 0"), err.Error()) +} + +func Test_ProcessMessage_noChainId(t *testing.T) { + p := newTestProcessor() + + err := p.ProcessMessage(context.Background(), &contracts.BridgeMessageSent{ + Message: contracts.IBridgeMessage{ + GasLimit: big.NewInt(1), + }, + Signal: mock.SuccessSignal, + }, &relayer.Event{}) + assert.EqualError(t, err, "p.sendProcessMessageCall: bind.NewKeyedTransactorWithChainID: no chain id specified") +} + +func Test_ProcessMessage(t *testing.T) { + p := newTestProcessor() + + err := p.ProcessMessage(context.Background(), &contracts.BridgeMessageSent{ + Message: contracts.IBridgeMessage{ + GasLimit: big.NewInt(1), + DestChainId: mock.MockChainID, + }, + Signal: mock.SuccessSignal, + }, &relayer.Event{}) + + assert.Nil( + t, + err, + ) +} diff --git a/packages/relayer/message/processor.go b/packages/relayer/message/processor.go index db2781e9f8..81442d3875 100644 --- a/packages/relayer/message/processor.go +++ b/packages/relayer/message/processor.go @@ -1,27 +1,31 @@ package message import ( + "context" "crypto/ecdsa" "sync" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/taikochain/taiko-mono/packages/relayer" - "github.com/taikochain/taiko-mono/packages/relayer/contracts" "github.com/taikochain/taiko-mono/packages/relayer/proof" ) +type ethClient interface { + PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) + TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) + BlockNumber(ctx context.Context) (uint64, error) +} type Processor struct { eventRepo relayer.EventRepository - srcEthClient *ethclient.Client - destEthClient *ethclient.Client - rpc *rpc.Client + srcEthClient ethClient + destEthClient ethClient + rpc relayer.Caller ecdsaKey *ecdsa.PrivateKey - destBridge *contracts.Bridge - destHeaderSyncer *contracts.IHeaderSync + destBridge relayer.Bridge + destHeaderSyncer relayer.HeaderSyncer prover *proof.Prover @@ -35,12 +39,12 @@ type Processor struct { type NewProcessorOpts struct { Prover *proof.Prover ECDSAKey *ecdsa.PrivateKey - RPCClient *rpc.Client - SrcETHClient *ethclient.Client - DestETHClient *ethclient.Client - DestBridge *contracts.Bridge + RPCClient relayer.Caller + SrcETHClient ethClient + DestETHClient ethClient + DestBridge relayer.Bridge EventRepo relayer.EventRepository - DestHeaderSyncer *contracts.IHeaderSync + DestHeaderSyncer relayer.HeaderSyncer RelayerAddress common.Address Confirmations uint64 } diff --git a/packages/relayer/message/processor_test.go b/packages/relayer/message/processor_test.go index ee833270f2..9cf5d2a276 100644 --- a/packages/relayer/message/processor_test.go +++ b/packages/relayer/message/processor_test.go @@ -2,17 +2,41 @@ package message import ( "crypto/ecdsa" + "sync" "testing" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" "github.com/taikochain/taiko-mono/packages/relayer" "github.com/taikochain/taiko-mono/packages/relayer/contracts" + "github.com/taikochain/taiko-mono/packages/relayer/mock" "github.com/taikochain/taiko-mono/packages/relayer/proof" "github.com/taikochain/taiko-mono/packages/relayer/repo" "gopkg.in/go-playground/assert.v1" ) +var dummyEcdsaKey = "8da4ef21b864d2cc526dbdb2a120bd2874c36c9d0a1fb7f8c63d7f7a8b41de8f" + +func newTestProcessor() *Processor { + privateKey, _ := crypto.HexToECDSA(dummyEcdsaKey) + + prover, _ := proof.New( + &mock.Blocker{}, + ) + + return &Processor{ + eventRepo: &mock.EventRepository{}, + destBridge: &mock.Bridge{}, + srcEthClient: &mock.EthClient{}, + destEthClient: &mock.EthClient{}, + mu: &sync.Mutex{}, + ecdsaKey: privateKey, + destHeaderSyncer: &mock.HeaderSyncer{}, + prover: prover, + rpc: &mock.Caller{}, + } +} func Test_NewProcessor(t *testing.T) { tests := []struct { name string diff --git a/packages/relayer/mock/bridge.go b/packages/relayer/mock/bridge.go new file mode 100644 index 0000000000..9e51feb101 --- /dev/null +++ b/packages/relayer/mock/bridge.go @@ -0,0 +1,103 @@ +package mock + +import ( + "errors" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/taikochain/taiko-mono/packages/relayer" + "github.com/taikochain/taiko-mono/packages/relayer/contracts" +) + +var ( + SuccessSignal = [32]byte{0x1} + FailSignal = [32]byte{0x2} +) + +var dummyAddress = "0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377" + +type Bridge struct { + MessagesSent int + ErrorsSent int +} + +type Subscription struct { + errChan chan error + done bool +} + +func (s *Subscription) Err() <-chan error { + return s.errChan +} + +func (s *Subscription) Unsubscribe() {} + +func (b *Bridge) WatchMessageSent( + opts *bind.WatchOpts, + sink chan<- *contracts.BridgeMessageSent, + signal [][32]byte, +) (event.Subscription, error) { + s := &Subscription{ + errChan: make(chan error), + } + + go func(sink chan<- *contracts.BridgeMessageSent) { + <-time.After(2 * time.Second) + + sink <- &contracts.BridgeMessageSent{} + b.MessagesSent++ + }(sink) + + go func(errChan chan error) { + <-time.After(5 * time.Second) + + errChan <- errors.New("fail") + + s.done = true + b.ErrorsSent++ + }(s.errChan) + + return s, nil +} + +func (b *Bridge) FilterMessageSent( + opts *bind.FilterOpts, + signal [][32]byte, +) (*contracts.BridgeMessageSentIterator, error) { + return &contracts.BridgeMessageSentIterator{}, nil +} + +func (b *Bridge) GetMessageStatus(opts *bind.CallOpts, signal [32]byte) (uint8, error) { + if signal == SuccessSignal { + return uint8(relayer.EventStatusNew), nil + } + + return uint8(relayer.EventStatusDone), nil +} + +func (b *Bridge) ProcessMessage( + opts *bind.TransactOpts, + message contracts.IBridgeMessage, + proof []byte, +) (*types.Transaction, error) { + return types.NewTransaction( + PendingNonce, + common.HexToAddress(dummyAddress), + big.NewInt(1), + 100, + big.NewInt(10), + nil, + ), nil +} + +func (b *Bridge) IsMessageReceived(opts *bind.CallOpts, signal [32]byte, srcChainId *big.Int, proof []byte) (bool, error) { // nolint + if signal == SuccessSignal { + return true, nil + } + + return false, nil +} diff --git a/packages/relayer/mock/eth_client.go b/packages/relayer/mock/eth_client.go index 4e9079dd5a..b7cca8a08e 100644 --- a/packages/relayer/mock/eth_client.go +++ b/packages/relayer/mock/eth_client.go @@ -4,11 +4,19 @@ import ( "context" "math/big" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) var ( - MockChainID = big.NewInt(167001) + MockChainID = big.NewInt(167001) + LatestBlockNumber = big.NewInt(10) + NotFoundTxHash = common.HexToHash("0x123") + SucceedTxHash = common.HexToHash("0x456") + FailTxHash = common.HexToHash("0x789") + BlockNum = 10 + PendingNonce uint64 = 10 ) type EthClient struct { @@ -19,7 +27,37 @@ func (c *EthClient) ChainID(ctx context.Context) (*big.Int, error) { } func (c *EthClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + if number == nil { + number = LatestBlockNumber + } + return &types.Header{ Number: number, }, nil } + +func (c *EthClient) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { + return PendingNonce, nil +} + +func (c *EthClient) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + if txHash == NotFoundTxHash { + return nil, ethereum.NotFound + } + + if txHash == FailTxHash { + return &types.Receipt{ + Status: types.ReceiptStatusFailed, + BlockNumber: big.NewInt(1), + }, nil + } + + return &types.Receipt{ + Status: types.ReceiptStatusSuccessful, + BlockNumber: new(big.Int).Sub(big.NewInt(int64(BlockNum)), big.NewInt(1)), + }, nil +} + +func (c *EthClient) BlockNumber(ctx context.Context) (uint64, error) { + return uint64(BlockNum), nil +} diff --git a/packages/relayer/mock/event_repository.go b/packages/relayer/mock/event_repository.go new file mode 100644 index 0000000000..bca1a5ad77 --- /dev/null +++ b/packages/relayer/mock/event_repository.go @@ -0,0 +1,16 @@ +package mock + +import ( + "github.com/taikochain/taiko-mono/packages/relayer" +) + +type EventRepository struct { +} + +func (r *EventRepository) Save(opts relayer.SaveEventOpts) (*relayer.Event, error) { + return nil, nil +} + +func (r *EventRepository) UpdateStatus(id int, status relayer.EventStatus) error { + return nil +} diff --git a/packages/relayer/mock/header_syncer.go b/packages/relayer/mock/header_syncer.go new file mode 100644 index 0000000000..c5fe29a77c --- /dev/null +++ b/packages/relayer/mock/header_syncer.go @@ -0,0 +1,21 @@ +package mock + +import ( + "errors" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" +) + +var SuccessHeader = [32]byte{0x1} + +type HeaderSyncer struct { + Fail bool +} + +func (h *HeaderSyncer) GetLatestSyncedHeader(opts *bind.CallOpts) ([32]byte, error) { + if h.Fail { + return [32]byte{}, errors.New("fail") + } + + return SuccessHeader, nil +} diff --git a/packages/relayer/proof/encoded_signal_proof.go b/packages/relayer/proof/encoded_signal_proof.go index e42e688456..73e492cc56 100644 --- a/packages/relayer/proof/encoded_signal_proof.go +++ b/packages/relayer/proof/encoded_signal_proof.go @@ -4,6 +4,7 @@ import ( "context" "math/big" + "github.com/taikochain/taiko-mono/packages/relayer" "github.com/taikochain/taiko-mono/packages/relayer/encoding" "github.com/ethereum/go-ethereum/common" @@ -16,7 +17,7 @@ import ( // in our contracts func (p *Prover) EncodedSignalProof( ctx context.Context, - caller caller, + caller relayer.Caller, bridgeAddress common.Address, key string, blockHash common.Hash, @@ -49,7 +50,7 @@ func (p *Prover) EncodedSignalProof( // response from `eth_getProof` func (p *Prover) encodedStorageProof( ctx context.Context, - c caller, + c relayer.Caller, bridgeAddress common.Address, key string, blockNumber int64, diff --git a/packages/relayer/proof/types.go b/packages/relayer/proof/types.go index 092736cfbb..457e55d584 100644 --- a/packages/relayer/proof/types.go +++ b/packages/relayer/proof/types.go @@ -2,7 +2,6 @@ package proof import ( "bytes" - "context" "encoding/json" "fmt" "math/big" @@ -12,10 +11,6 @@ import ( "github.com/pkg/errors" ) -type caller interface { - CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error -} - type Bytes []byte // MarshalText implements encoding.TextMarshaler